Revert "Update package dependency from libwxgtk3.0-dev to libwxgtk3.0-gtk3-dev for...
[ctsim.git] / libctsim / array2dfile.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **      Name:         array2dfile.cpp
5 **      Purpose:      2-dimension array file class
6 **      Programmer:   Kevin Rosenberg
7 **      Date Started: June 2000
8 **
9 **  This is part of the CTSim program
10 **  Copyright (c) 1983-2009 Kevin Rosenberg
11 **
12 **  This program is free software; you can redistribute it and/or modify
13 **  it under the terms of the GNU General Public License (version 2) as
14 **  published by the Free Software Foundation.
15 **
16 **  This program is distributed in the hope that it will be useful,
17 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
18 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 **  GNU General Public License for more details.
20 **
21 **  You should have received a copy of the GNU General Public License
22 **  along with this program; if not, write to the Free Software
23 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 ******************************************************************************/
25
26 #include "array2dfile.h"
27 #include <ctime>
28 #ifdef MSVC
29 typedef long off_t;
30 #endif
31
32 #include <sstream>
33
34 const kuint16 Array2dFile::m_signature = ('I'*256+'F');
35
36 ///////////////////////////////////////////////////////////////////////////
37 // CLASS IMPLEMENTATION
38 //
39 //     Name: Array2dFileLabel
40 //     Purpose: Labels for Array2dFiles
41 ///////////////////////////////////////////////////////////////////////////
42
43 void
44 Array2dFileLabel::init (void)
45 {
46   m_calcTime = 0;
47   m_labelType = L_EMPTY;
48   time_t t = time(0);
49   tm* lt = localtime(&t);
50   m_year = lt->tm_year;
51   m_month = lt->tm_mon;
52   m_day = lt->tm_mday;
53   m_hour = lt->tm_hour;
54   m_minute = lt->tm_min;
55   m_second = lt->tm_sec;
56 }
57
58 Array2dFileLabel::Array2dFileLabel()
59 {
60   init();
61 }
62
63 Array2dFileLabel::Array2dFileLabel(const char* const str, double ctime)
64 : m_strLabel (str)
65 {
66   init();
67
68   m_labelType = L_USER;
69   m_calcTime = ctime;
70 }
71
72 Array2dFileLabel::Array2dFileLabel(const int type, const char* const str, double ctime)
73 :  m_strLabel (str)
74 {
75   init();
76
77   m_labelType = type;
78   m_calcTime = ctime;
79 }
80
81 Array2dFileLabel::~Array2dFileLabel()
82 {
83 }
84
85 void
86 Array2dFileLabel::setDateTime (int year, int month, int day, int hour, int minute, int second)
87 {
88   m_year = year;
89   m_month = month;
90   m_day = day;
91   m_hour = hour;
92   m_minute = minute;
93   m_second = second;
94 }
95
96 void
97 Array2dFileLabel::getDateTime (int& year, int& month, int& day, int& hour, int& minute, int& second) const
98 {
99   year = m_year;
100   month = m_month;
101   day = m_day;
102   hour = m_hour;
103   minute = m_minute;
104   second = m_second;
105 }
106
107 const std::string&
108 Array2dFileLabel::getDateString (void) const
109 {
110   char szDate [128];
111   snprintf (szDate, sizeof(szDate), "%2d/%02d/%4d %02d:%02d:%02d",
112     m_month + 1, m_day, m_year + 1900, m_hour, m_minute, m_second);
113   m_strDate = szDate;
114   return m_strDate;
115 }
116
117
118 Array2dFileLabel::Array2dFileLabel (const Array2dFileLabel& rhs)
119 {
120   m_calcTime = rhs.m_calcTime;
121   m_labelType = rhs.m_labelType;
122   m_strLabel = rhs.m_strLabel;
123   m_year = rhs.m_year; m_month = rhs.m_month; m_day = rhs.m_day;
124   m_hour = rhs.m_hour; m_minute = rhs.m_minute; m_second = rhs.m_second;
125 }
126
127 Array2dFileLabel&
128 Array2dFileLabel::operator= (const Array2dFileLabel& rhs)
129 {
130   m_calcTime = rhs.m_calcTime;
131   m_labelType = rhs.m_labelType;
132   m_strLabel = rhs.m_strLabel;
133   m_year = rhs.m_year; m_month = rhs.m_month; m_day = rhs.m_day;
134   m_hour = rhs.m_hour; m_minute = rhs.m_minute; m_second = rhs.m_second;
135
136   return (*this);
137 }
138
139 void
140 Array2dFileLabel::print (std::ostream& os) const
141 {
142   if (m_labelType == L_HISTORY) {
143     os << "History: " << std::endl;
144     os << "  " << m_strLabel << std::endl;
145     os << "  calc time = " << m_calcTime << " secs" << std::endl;
146     os << "  Timestamp = " << getDateString() << std::endl;
147   } else if (m_labelType == L_USER) {
148     os << "Note: " <<  m_strLabel << std::endl;
149     os << "  Timestamp = %s" << getDateString() << std::endl;
150   } else {
151     os << "Unknown (" << m_labelType << "): " <<  m_strLabel << std::endl;
152     os << "  Timestamp = %s" << getDateString() << std::endl;
153   }
154 }
155
156 void
157 Array2dFileLabel::printBrief (std::ostream& os) const
158 {
159   if (m_labelType == L_HISTORY) {
160     os << "History (";
161     if (m_calcTime > 0)
162       os << m_calcTime << " secs, ";
163     os << getDateString() << "): " << m_strLabel << std::endl;
164   } else if (m_labelType == L_USER) {
165     os << "Note (" <<  getDateString() << "): " << m_strLabel << std::endl;
166   } else {
167     os << "Unknown (" << getDateString() << "): " << m_strLabel << std::endl;
168   }
169 }
170
171 void
172 Array2dFileLabel::printBrief (std::ostringstream& os) const
173 {
174   if (m_labelType == L_HISTORY) {
175     os << "History (";
176     if (m_calcTime > 0)
177       os << m_calcTime << " secs, ";
178     os << getDateString().c_str() << "): " << m_strLabel.c_str() << "\n";
179   } else if (m_labelType == L_USER) {
180     os << "Note (" <<  getDateString() << "): " << m_strLabel << "\n";
181   } else {
182     os << "Unknown (" << getDateString() << "): " << m_strLabel << "\n";
183   }
184 }
185
186
187 ///////////////////////////////////////////////////////////////////////////
188 // CLASS IMPLEMENTATION
189 //
190 //     Name: Array2dFile
191 //     Purpose: Array2dFiles
192 ///////////////////////////////////////////////////////////////////////////
193
194
195 Array2dFile::Array2dFile (int x, int y, int pixelSize, int pixelFormat, int dataType)
196 {
197   init();
198   setArraySize (x, y, pixelSize, pixelFormat, dataType);
199 }
200
201 Array2dFile::~Array2dFile (void)
202 {
203   freeArrays ();
204   for (labelIterator l = m_labels.begin(); l != m_labels.end(); l++)
205     delete *l;
206 }
207
208 Array2dFile::Array2dFile (void)
209 {
210   init();
211 }
212
213 void
214 Array2dFile::init (void)
215 {
216   m_pixelSize = 0;
217   m_pixelFormat = PIXEL_INVALID;
218   m_arrayData = NULL;
219   m_imaginaryArrayData = NULL;
220   m_dataType = DATA_TYPE_INVALID;
221   m_nx = 0;
222   m_ny = 0;
223   m_headersize = 0;
224   m_axisIncrementKnown = false;
225   m_axisIncrementX = m_axisIncrementY = 0;
226   m_axisExtentKnown = false;
227   m_minX = m_maxX = m_minY = m_maxY = 0;
228   m_offsetPV = 0;
229   m_scalePV = 1;
230 }
231
232
233 void
234 Array2dFile::setArraySize (int x, int y, int pixelSize, int pixelFormat, int dataType)
235 {
236   m_pixelSize = pixelSize;
237   m_pixelFormat = pixelFormat;
238   m_dataType = dataType;
239   setArraySize (x, y);
240 }
241
242 void
243 Array2dFile::setArraySize (int x, int y)
244 {
245   m_nx = x;
246   m_ny = y;
247   allocArrays ();
248 }
249
250 bool
251 Array2dFile::reallocComplexToReal ()
252 {
253   if (m_dataType != DATA_TYPE_COMPLEX)
254     return false;
255
256   freeArray (m_imaginaryArrayData);
257   m_dataType = DATA_TYPE_REAL;
258
259   return true;
260 }
261
262
263 bool
264 Array2dFile::reallocRealToComplex ()
265 {
266   if (m_dataType != DATA_TYPE_REAL)
267     return false;
268
269   allocArray (m_imaginaryArrayData);
270   m_dataType = DATA_TYPE_COMPLEX;
271
272   return true;
273 }
274
275
276
277 void
278 Array2dFile::allocArrays ()
279 {
280   if (m_arrayData)
281     freeArray (m_arrayData);
282   if (m_imaginaryArrayData)
283     freeArray (m_imaginaryArrayData);
284
285   allocArray (m_arrayData);
286   if (m_dataType == DATA_TYPE_COMPLEX)
287     allocArray (m_imaginaryArrayData);
288 }
289
290 void
291 Array2dFile::allocArray (unsigned char**& rppData)
292 {
293   m_arraySize = m_nx * m_ny * m_pixelSize;
294   rppData = new unsigned char* [m_nx];
295   int columnBytes = m_ny * m_pixelSize;
296   for (unsigned int i = 0; i < m_nx; i++)
297     rppData[i] = new unsigned char [columnBytes];
298 }
299
300 void
301 Array2dFile::freeArrays ()
302 {
303   if (m_arrayData)
304     freeArray (m_arrayData);
305
306   if (m_imaginaryArrayData)
307     freeArray (m_imaginaryArrayData);
308
309 }
310
311 void
312 Array2dFile::freeArray (unsigned char**& rppData)
313 {
314    for (unsigned int i = 0; i < m_nx; i++)
315       delete rppData[i];
316     delete rppData;
317     rppData = NULL;
318 }
319
320
321 bool
322 Array2dFile::fileWrite (const std::string& filename)
323 {
324   return fileWrite (filename.c_str());
325 }
326
327 bool
328 Array2dFile::fileWrite (const char* const filename)
329 {
330   m_filename = filename;
331
332   frnetorderstream fs (m_filename.c_str(), std::ios::out | std::ios::in | std::ios::trunc | std::ios::binary);
333   if (fs.fail()) {
334     sys_error (ERR_WARNING, "Error opening file %s for writing [fileCreate]", m_filename.c_str());
335     return false;
336   }
337   if (! headerWrite(fs))
338     return false;
339
340   if (! arrayDataWrite (fs))
341     return false;
342
343   if (! labelsWrite (fs))
344     return false;
345
346   return true;
347 }
348
349 bool
350 Array2dFile::fileRead (const std::string& filename)
351 {
352   return fileRead (filename.c_str());
353 }
354
355 bool
356 Array2dFile::fileRead (const char* const filename)
357 {
358   m_filename = filename;
359
360   frnetorderstream fs (m_filename.c_str(), std::ios::out | std::ios::in | std::ios::binary);
361
362   if (fs.fail()) {
363     sys_error (ERR_WARNING, "Unable to open file %s [fileRead]", m_filename.c_str());
364     return false;
365   }
366
367   if (! headerRead(fs))
368     return false;
369
370   allocArrays ();
371
372   if (! arrayDataRead(fs))
373     return false;;
374
375   if (! labelsRead (fs))
376     return false;
377
378   return true;
379 }
380
381 void
382 Array2dFile::setAxisIncrement (double incX, double incY)
383 {
384   m_axisIncrementKnown = true;
385   m_axisIncrementX = incX;
386   m_axisIncrementY = incY;
387 }
388
389 void
390 Array2dFile::setAxisExtent (double minX, double maxX, double minY, double maxY)
391 {
392   m_axisExtentKnown = true;
393   m_minX = minX;
394   m_maxY = maxX;
395   m_minX = minX;
396   m_maxY = maxY;
397 }
398
399 bool
400 Array2dFile::headerRead (frnetorderstream& fs)
401 {
402   if (! fs) {
403     sys_error (ERR_WARNING, "Tried to read header with file closed [headerRead]");
404     return false;
405   }
406
407   fs.seekg (0);
408   kuint16 file_signature;
409
410   fs.readInt16 (m_headersize);
411   fs.readInt16 (file_signature);
412   fs.readInt16 (m_pixelFormat);
413   fs.readInt16 (m_pixelSize);
414   fs.readInt16 (m_numFileLabels);
415   fs.readInt32 (m_nx);
416   fs.readInt32 (m_ny);
417   fs.readInt16 (m_dataType);
418   fs.readInt16 (m_axisIncrementKnown);
419   fs.readFloat64 (m_axisIncrementX);
420   fs.readFloat64 (m_axisIncrementY);
421   fs.readInt16 (m_axisExtentKnown);
422   fs.readFloat64 (m_minX);
423   fs.readFloat64 (m_maxX);
424   fs.readFloat64 (m_minY);
425   fs.readFloat64 (m_maxY);
426   fs.readFloat64 (m_offsetPV);
427   fs.readFloat64 (m_scalePV);
428
429   int read_m_headersize = fs.tellg();
430   if (read_m_headersize != m_headersize) {
431     sys_error (ERR_WARNING, "Read m_headersize %d != file m_headersize %d", read_m_headersize, m_headersize);
432     return false;
433   }
434   if (file_signature != m_signature) {
435     sys_error (ERR_WARNING, "File signature %d != true signature %d", file_signature, m_signature);
436     return false;
437   }
438
439   return ! fs.fail();
440 }
441
442
443 bool
444 Array2dFile::headerWrite (frnetorderstream& fs)
445 {
446   if (! fs) {
447     sys_error (ERR_WARNING, "Tried to write header with ! fs");
448     return false;
449   }
450
451   m_numFileLabels = m_labels.size();
452
453   fs.seekp (0);
454   fs.writeInt16 (m_headersize);
455   fs.writeInt16 (m_signature);
456   fs.writeInt16 (m_pixelFormat);
457   fs.writeInt16 (m_pixelSize);
458   fs.writeInt16 (m_numFileLabels);
459   fs.writeInt32 (m_nx);
460   fs.writeInt32 (m_ny);
461   fs.writeInt16 (m_dataType);
462   fs.writeInt16 (m_axisIncrementKnown);
463   fs.writeFloat64 (m_axisIncrementX);
464   fs.writeFloat64 (m_axisIncrementY);
465   fs.writeInt16 (m_axisExtentKnown);
466   fs.writeFloat64 (m_minX);
467   fs.writeFloat64 (m_maxX);
468   fs.writeFloat64 (m_minY);
469   fs.writeFloat64 (m_maxY);
470   fs.writeFloat64 (m_offsetPV);
471   fs.writeFloat64 (m_scalePV);
472
473   m_headersize = static_cast<kuint16>(fs.tellp());
474   fs.seekp (0);
475   fs.writeInt16 (m_headersize);
476
477   return ! fs.fail();
478 }
479
480
481 bool
482 Array2dFile::arrayDataWrite (frnetorderstream& fs)
483 {
484   if (! fs) {
485     sys_error (ERR_WARNING, "Tried to arrayDataWrite with !fs");
486     return false;
487   }
488
489   if (! m_arrayData)
490     return false;
491
492   fs.seekp (m_headersize);
493   int columnSize = m_ny * m_pixelSize;
494   for (unsigned int ix = 0; ix < m_nx; ix++) {
495     unsigned char* ptrColumn = m_arrayData[ix];
496     if (NativeBigEndian()) {
497       for (unsigned int iy = 0; iy < m_ny; iy++) {
498         ConvertReverseNetworkOrder (ptrColumn, m_pixelSize);
499         fs.write (reinterpret_cast<const char*>(ptrColumn), m_pixelSize);
500         ptrColumn += m_pixelSize;
501       }
502     } else
503       fs.write (reinterpret_cast<const char*>(ptrColumn), columnSize);
504   }
505   if (m_dataType == DATA_TYPE_COMPLEX) {
506     for (unsigned int ix = 0; ix < m_nx; ix++) {
507       unsigned char* ptrColumn = m_imaginaryArrayData[ix];
508       if (NativeBigEndian()) {
509         for (unsigned int iy = 0; iy < m_ny; iy++) {
510           ConvertReverseNetworkOrder (ptrColumn, m_pixelSize);
511           fs.write (reinterpret_cast<const char*>(ptrColumn), m_pixelSize);
512           ptrColumn += m_pixelSize;
513         }
514       } else
515         fs.write (reinterpret_cast<const char*>(ptrColumn), columnSize);
516     }
517   }
518
519   return true;
520 }
521
522
523 bool
524 Array2dFile::arrayDataRead (frnetorderstream& fs)
525 {
526   if (! fs) {
527     sys_error (ERR_WARNING, "Tried to arrayDataRead with ! fs");
528     return false;
529   }
530
531   if (! m_arrayData)
532     return false;
533
534   fs.seekg (m_headersize);
535   int columnSize = m_ny * m_pixelSize;
536   for (unsigned int ix = 0; ix < m_nx; ix++) {
537     unsigned char* ptrColumn = m_arrayData[ix];
538     if (NativeBigEndian()) {
539       for (unsigned int iy = 0; iy < m_ny; iy++) {
540         fs.read (reinterpret_cast<char*>(ptrColumn), m_pixelSize);
541         ConvertReverseNetworkOrder (ptrColumn, m_pixelSize);
542         ptrColumn += m_pixelSize;
543       }
544     } else
545       fs.read (reinterpret_cast<char*>(ptrColumn), columnSize);
546   }
547   if (m_dataType == DATA_TYPE_COMPLEX) {
548     for (unsigned int ix = 0; ix < m_nx; ix++) {
549       unsigned char* ptrColumn = m_imaginaryArrayData[ix];
550       if (NativeBigEndian()) {
551         for (unsigned int iy = 0; iy < m_ny; iy++) {
552           fs.read (reinterpret_cast<char*>(ptrColumn), m_pixelSize);
553           ConvertReverseNetworkOrder (ptrColumn, m_pixelSize);
554           ptrColumn += m_pixelSize;
555         }
556       } else
557         fs.read (reinterpret_cast<char*>(ptrColumn), columnSize);
558     }
559   }
560
561   return true;
562 }
563
564 bool
565 Array2dFile::labelsRead (frnetorderstream& fs)
566 {
567   off_t pos = m_headersize + m_arraySize;
568   fs.seekg (pos);
569   if (fs.fail())
570     return false;
571
572   for (int i = 0; i < m_numFileLabels; i++) {
573     kuint16 labelType, year, month, day, hour, minute, second;
574     kfloat64 calcTime;
575
576     fs.readInt16 (labelType);
577     fs.readInt16 (year);
578     fs.readInt16 (month);
579     fs.readInt16 (day);
580     fs.readInt16 (hour);
581     fs.readInt16 (minute);
582     fs.readInt16 (second);
583     fs.readFloat64 (calcTime);
584
585     kuint16 strLength;
586     fs.readInt16 (strLength);
587     char* pszLabelStr = new char [strLength+1];
588     fs.read (pszLabelStr, strLength);
589     pszLabelStr[strLength] = 0;
590
591     Array2dFileLabel* pLabel = new Array2dFileLabel (labelType, pszLabelStr, calcTime);
592     delete pszLabelStr;
593
594     pLabel->setDateTime (year, month, day, hour, minute, second);
595     m_labels.push_back (pLabel);
596   }
597
598   return true;
599 }
600
601 bool
602 Array2dFile::labelsWrite (frnetorderstream& fs)
603 {
604   off_t pos = m_headersize + m_arraySize;
605   fs.seekp (pos);
606
607   for (constLabelIterator l = m_labels.begin(); l != m_labels.end(); l++) {
608     const Array2dFileLabel& label = **l;
609     kuint16 labelType = label.getLabelType();
610     kfloat64 calcTime = label.getCalcTime();
611     const char* const labelString = label.getLabelString().c_str();
612     int year, month, day, hour, minute, second;
613     kuint16 yearBuf, monthBuf, dayBuf, hourBuf, minuteBuf, secondBuf;
614
615     label.getDateTime (year, month, day, hour, minute, second);
616     yearBuf = year; monthBuf = month; dayBuf = day;
617     hourBuf = hour; minuteBuf = minute; secondBuf = second;
618
619     fs.writeInt16 (labelType);
620     fs.writeInt16 (yearBuf);
621     fs.writeInt16 (monthBuf);
622     fs.writeInt16 (dayBuf);
623     fs.writeInt16 (hourBuf);
624     fs.writeInt16 (minuteBuf);
625     fs.writeInt16 (secondBuf);
626     fs.writeFloat64 (calcTime);
627     kuint16 strlength = strlen (labelString);
628     fs.writeInt16 (strlength);
629     fs.write (labelString, strlength);
630   }
631
632   return true;
633 }
634
635 void
636 Array2dFile::labelAdd (const char* const lstr, double calc_time)
637 {
638   labelAdd (Array2dFileLabel::L_HISTORY, lstr, calc_time);
639 }
640
641
642 void
643 Array2dFile::labelAdd (int type, const char* const lstr, double calc_time)
644 {
645   Array2dFileLabel label (type, lstr, calc_time);
646
647   labelAdd (label);
648 }
649
650
651 void
652 Array2dFile::labelAdd (const Array2dFileLabel& label)
653 {
654   Array2dFileLabel* pLabel = new Array2dFileLabel(label);
655
656   m_labels.push_back (pLabel);
657 }
658
659 void
660 Array2dFile::labelsCopy (const Array2dFile& copyFile, const char* const pszId)
661 {
662   std::string id;
663   if (pszId)
664     id = pszId;
665   for (unsigned int i = 0; i < copyFile.getNumLabels(); i++) {
666     Array2dFileLabel l (copyFile.labelGet (i));
667     std::string lstr = l.getLabelString();
668     lstr = id + lstr;
669     l.setLabelString (lstr);
670     labelAdd (l);
671   }
672 }
673
674 void
675 Array2dFile::arrayDataClear (void)
676 {
677   if (m_arrayData) {
678     int columnSize = m_ny * m_pixelSize;
679     for (unsigned int ix = 0; ix < m_nx; ix++)
680       memset (m_arrayData[ix], 0, columnSize);
681   }
682   if (m_imaginaryArrayData) {
683     int columnSize = m_ny * m_pixelSize;
684     for (unsigned int ix = 0; ix < m_nx; ix++)
685       memset (m_arrayData[ix], 0, columnSize);
686   }
687 }
688
689 void
690 Array2dFile::printLabels (std::ostream& os) const
691 {
692   for (constLabelIterator l = m_labels.begin(); l != m_labels.end(); l++) {
693     const Array2dFileLabel& label = **l;
694
695     label.print (os);
696     os << std::endl;
697   }
698 }
699
700 void
701 Array2dFile::printLabelsBrief (std::ostream& os) const
702 {
703   for (constLabelIterator l = m_labels.begin(); l != m_labels.end(); l++) {
704     const Array2dFileLabel& label = **l;
705
706     label.printBrief (os);
707   }
708 }
709
710 void
711 Array2dFile::printLabelsBrief (std::ostringstream& os) const
712 {
713   for (constLabelIterator l = m_labels.begin(); l != m_labels.end(); l++) {
714     const Array2dFileLabel& label = **l;
715
716     label.printBrief (os);
717   }
718 }
719
720
721 const Array2dFileLabel&
722 Array2dFile::labelGet (int i) const
723 {
724   return *m_labels[i];
725 }