r87: Upgraded from MPI to MPI++
[ctsim.git] / include / imagefile.h
1 #ifndef IDF_H
2 #define IDF_H
3
4 #include <string>
5 #include "kstddef.h"
6 #include <sys/types.h>
7 #include <unistd.h>
8 #include <array2d.h>
9
10 using namespace std;
11
12 class Array2dFileLabel
13 {
14 private:
15     void init (void);
16
17 public:
18     kfloat64 calc_time;
19     kuint16 label_type;
20     kuint16 year;
21     kuint16 month;
22     kuint16 day;
23     kuint16 hour;
24     kuint16 minute;
25     kuint16 second;
26     string label_str;
27
28     static const int L_EMPTY = 0;
29     static const int L_HISTORY = 1;
30     static const int L_USER = 2;
31
32     Array2dFileLabel(); 
33
34     Array2dFileLabel(const char* const str, double ctime = 0.);
35
36     Array2dFileLabel(const int type, const char* const str, double ctime = 0.);
37
38     ~Array2dFileLabel();
39
40     string getLabelString (void) const
41         { return label_str; }
42
43     kfloat64 getCalcTime (void) const
44         { return calc_time; }
45
46     kfloat64 getLabelType (void) const
47         { return label_type; }
48
49     string& setLabelString (const char* const str)
50         { label_str = str; return (label_str); }
51
52     string& setLabelString (const string& str)
53         { label_str = str; return (label_str); }
54
55     void getDateString (string& str) const;
56 };
57
58
59 template<class T>
60 class Array2dFile 
61 {
62 private:
63   void init (void);
64   kuint16 signature;
65   kuint16 num_labels;
66   kuint16 headersize;
67   string  filename;
68   int file_id;
69   iostream *io;
70   bool bHeaderWritten;
71   bool bDataWritten;
72
73   bool headerWrite (void);
74
75   bool headerRead (void);
76
77   bool arrayDataRead (void);
78
79   bool labelSeek (unsigned int label_num);
80
81   kuint16 mPixelSize;
82   kuint16 axis_increment_known;
83   kfloat64 mIncX, mIncY;
84   kuint16 axis_extent_known;
85   kfloat64 mMinX, mMaxX, mMinY, mMaxY;
86   kfloat64 mOffsetPV, mScalePV;
87   kuint16 mPixelType;
88   kuint32 mNX;
89   kuint32 mNY;
90
91 public:
92
93   Array2d<T> *array;
94
95   static const int INT8 = 1;
96   static const int UINT8 = 2;
97   static const int INT16 = 3;
98   static const int UINT16 = 4;
99   static const int INT32 = 5;
100   static const int UINT32 = 6;
101   static const int FLOAT32 = 7;
102   static const int FLOAT64 = 8;
103
104   Array2dFile (unsigned int nx, unsigned int ny);
105   Array2dFile (const char* const filename);
106   Array2dFile (const char* const filename, unsigned int nx, unsigned int ny);
107   ~Array2dFile ();
108
109   unsigned int getNumLabels (void) const
110       { return num_labels; }
111
112   bool labelRead (Array2dFileLabel& label, unsigned int label_num);
113
114   void labelAdd (const Array2dFileLabel& label);
115
116   void labelAdd (const char* const label_str, double calc_time=0.);
117
118   void labelAdd (int type, const char* const label_str, double calc_time=0.);
119
120   void labelsCopy (Array2dFile& file, const char* const idStr = NULL);
121
122   void fileClose (void);
123
124   void setPixelType (int type)
125       { mPixelType = type; }
126
127   kuint32 nx (void) const
128       { return mNX; }
129
130   kuint32 ny (void) const
131       { return mNY; }
132
133   void setAxisIncrement (double mIncX, double mIncY);
134
135   void setAxisExtent (double mMinX, double mMaxX, double mMinY, double mMaxY);
136
137   void getPixelValueRange (T& pvmin, T& pvmax) const;
138       
139   void doPixelOffsetScale (double offset, double scale);
140
141   T** getArray (void) const
142       { return (array == NULL ? NULL : array->getArray()); }
143
144   bool arrayDataWrite (void);
145
146   void arrayDataClear (void);
147
148   bool fileRead (void);
149
150   bool fileCreate (void);
151
152   const string& GetFilename (void) const 
153       {  return filename; }
154 };
155
156
157 template<class T>
158 Array2dFile<T>::Array2dFile (unsigned int x, unsigned int y)
159 {
160     init();
161     mNX = x;
162     mNY = y;
163     array = new Array2d<T> (mNX, mNY);
164 }
165
166 template<class T>
167 Array2dFile<T>::Array2dFile (const char * const str, unsigned int x, unsigned int y)
168   : filename(str)
169 {
170     init();
171     mNX = x;
172     mNY = y;
173     array = new Array2d<T> (mNX, mNY);
174 }
175
176 template<class T>
177 Array2dFile<T>::Array2dFile (const char * const str)
178   : filename(str)
179 {
180     init();
181 }
182
183 template<class T>
184 void
185 Array2dFile<T>::init (void)
186 {
187   mPixelSize = sizeof(T);
188   signature = ('I' * 256 + 'F');
189   file_id = -1;
190   mNX = 0;
191   mNY = 0;
192   headersize = 0;
193   num_labels = 0;
194   axis_increment_known = false;
195   axis_extent_known = false;
196   mIncX = mMinY = 0;
197   mMinX = mMaxX = mMinY = mMaxY = 0;
198   mOffsetPV = 0;
199   mScalePV = 1;
200   array = NULL;
201   io = NULL;
202
203 #if 0
204   const type_info& t_id = typeid(T);
205   cout << t_id.name() << endl;
206   const type_info& comp_id = typeid(T);
207
208   if (t_id == comp_id)
209       mPixelType = FLOAT64;
210   else if (t_id == typeid(kfloat32))
211     mPixelType = FLOAT32;
212   else if (t_id == typeid(kint32))
213     mPixelType = INT32;
214   else if (t_id == typeid(kuint32))
215     mPixelType = UINT32;
216   else if (t_id == typeid(kint16))
217     mPixelType = INT16;
218   else if (t_id == typeid(kuint16))
219     mPixelType = UINT16;
220   else if (t_id == typeid(kint8))
221     mPixelType = INT8;
222   else if (t_id == typeid(kuint8))
223     mPixelType = UINT8;
224   else
225 #endif
226       mPixelType = 0;
227
228   bHeaderWritten = false;
229   bDataWritten = false;
230 }
231
232 template<class T>
233 Array2dFile<T>::~Array2dFile (void)
234 {
235     fileClose ();
236 }
237
238
239 template<class T>
240 void
241 Array2dFile<T>::fileClose (void)
242 {
243   headerWrite ();
244   if (file_id >= 0 && array != NULL) {
245     arrayDataWrite ();
246     close (file_id);
247     file_id = -1;
248   }
249 }
250
251 template<class T>
252 bool
253 Array2dFile<T>::fileCreate (void)
254 {
255   //  io = new iostream(filename, ios::out | ios::in | ios::trunc | io::binary);
256     if ((file_id = open (filename.c_str(), O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
257         sys_error (ERR_WARNING, "Error opening file %s for writing [fileCreate]", filename.c_str());
258         return (false);
259     }
260   headerWrite();
261   return (true);
262 }
263
264 template<class T>
265 bool
266 Array2dFile<T>::fileRead (void)
267 {
268   // io = new iostream(filename, ios::out | ios::in | io::binary);
269   if ((file_id = open (filename.c_str(), O_RDONLY | O_BINARY)) < 0) {
270     sys_error (ERR_WARNING, "Unable to open file %s [fileRead]", filename.c_str());
271     return (false);
272   }
273
274   headerRead();
275   if (array != NULL)
276     delete array;
277
278   array = new Array2d<T> (mNX, mNY);
279
280   arrayDataRead();
281
282   return (true);
283 }
284
285 template<class T>
286 void
287 Array2dFile<T>::setAxisIncrement (double incX, double incY)
288 {
289     axis_increment_known = true;
290     mIncX = incX;
291     mIncY = incY;
292 }
293
294 template<class T>
295 void 
296 Array2dFile<T>::setAxisExtent (double minX, double maxX, double minY, double maxY)
297 {
298     axis_extent_known = true;
299     mMinX = minX;
300     mMaxY = maxX;
301     mMinX = minX;
302     mMaxY = maxY;
303 }
304
305 template<class T>
306 void 
307 Array2dFile<T>::getPixelValueRange (T& pvmin, T& pvmax) const
308 {
309     if (array != NULL) {
310         T** da = array->getArray();
311         pvmax = pvmin = da[0][0];
312         for (int ix = 0; ix < mNX; ix++)
313             for (int iy = 0; iy < mNY; iy++)
314                 if (pvmax < da[ix][iy])
315                     pvmax = da[ix][iy];
316                 else if (pvmin > da[ix][iy])
317                     pvmin = da[ix][iy];
318     }
319 }
320
321 template<class T>
322 void
323 Array2dFile<T>::doPixelOffsetScale (double offset, double scale)
324 {
325     if (adf != NULL) {
326       mOffsetPV = offset;
327       mScalePV = scale;
328
329       T** ad = adf->getArray();
330       for (unsigned int ix = 0; ix < mNX; ix++) 
331           for (unsigned int iy = 0; iy < mNY; iy++)
332               ad[ix][iy] = (ad[ix][iy] - offset) * scale;
333     }
334 }
335
336 template<class T>
337 bool
338 Array2dFile<T>::headerRead (void)
339 {
340   if (file_id < 0) {
341     sys_error (ERR_WARNING, "Tried to read header with file closed [headerRead]");
342     return (false);
343   }
344
345   lseek (file_id, 0, SEEK_SET);
346   kuint16 file_signature;
347   kuint16 file_mPixelSize;
348   kuint16 file_mPixelType;
349
350   read_nint16 (&headersize, file_id);
351   read_nint16 (&file_signature, file_id);
352   read_nint16 (&num_labels, file_id);
353   read_nint16 (&file_mPixelType, file_id);
354   read_nint16 (&file_mPixelSize, file_id);
355   read_nint32 (&mNX, file_id);
356   read_nint32 (&mNY, file_id);
357   read_nint16 (&axis_increment_known, file_id);
358   read_nfloat64 (&mIncX, file_id);
359   read_nfloat64 (&mIncY, file_id);
360   read_nint16 (&axis_extent_known, file_id);
361   read_nfloat64 (&mMinX, file_id);
362   read_nfloat64 (&mMaxX, file_id);
363   read_nfloat64 (&mMinY, file_id);
364   read_nfloat64 (&mMaxY, file_id);
365   read_nfloat64 (&mOffsetPV, file_id);
366   read_nfloat64 (&mScalePV, file_id);
367
368   int read_headersize = lseek (file_id, 0, SEEK_CUR);
369   if (read_headersize != headersize) {
370     sys_error (ERR_WARNING, "Read headersize %d != file headersize %d", read_headersize, headersize);
371     return (false);
372   }
373   if (file_signature != signature) {
374     sys_error (ERR_WARNING, "File signature %d != true signature %d", file_signature, signature);
375     return (false);
376   }
377   if (file_mPixelType != mPixelType) {
378     sys_error (ERR_WARNING, "File pixel type %d != class pixel type %d", file_mPixelType, mPixelType);
379     return (false);
380   }
381   if (file_mPixelSize != mPixelSize) {
382     sys_error (ERR_WARNING, "File pixel size %d != class pixel size %d", file_mPixelSize, mPixelSize);
383     return (false);
384   }
385
386   return (true);
387 }
388
389 template<class T>
390 bool
391 Array2dFile<T>::headerWrite (void)
392 {
393   if (file_id < 0) {
394     sys_error (ERR_WARNING, "Tried to write header with file closed");
395     return (false);
396   }
397
398   lseek (file_id, 0, SEEK_SET);
399   write_nint16 (&headersize, file_id);
400   write_nint16 (&signature, file_id);
401   write_nint16 (&num_labels, file_id);
402   write_nint16 (&mPixelType, file_id);
403   write_nint16 (&mPixelSize, file_id);
404   write_nint32 (&mNX, file_id);
405   write_nint32 (&mNY, file_id);
406   write_nint16 (&axis_increment_known, file_id);
407   write_nfloat64 (&mIncX, file_id);
408   write_nfloat64 (&mIncY, file_id);
409   write_nint16 (&axis_extent_known, file_id);
410   write_nfloat64 (&mMinX, file_id);
411   write_nfloat64 (&mMaxX, file_id);
412   write_nfloat64 (&mMinY, file_id);
413   write_nfloat64 (&mMaxY, file_id);
414   write_nfloat64 (&mOffsetPV, file_id);
415   write_nfloat64 (&mScalePV, file_id);
416
417   headersize = lseek (file_id, 0, SEEK_CUR);
418   lseek (file_id, 0, SEEK_SET);
419   write_nint16 (&headersize, file_id);
420   
421   return (true);
422 }
423
424 template<class T>
425 bool
426 Array2dFile<T>::arrayDataWrite (void)
427 {
428   if (file_id < 0) {
429     sys_error (ERR_WARNING, "Tried to arrayDataWrite with file_id < 0");
430     return (false);
431   }
432
433   lseek (file_id, headersize, SEEK_SET);
434   for (unsigned int ix = 0; ix < mNX; ix++)
435       for (unsigned int iy = 0; iy < mNY; iy++) {
436           T value = array->array_data[ix][iy];
437           ConvertNetworkOrder (&value, sizeof(T));
438           write (file_id, &value, mPixelSize);
439       }
440
441   return (true);
442 }
443
444 template<class T>
445 bool
446 Array2dFile<T>::arrayDataRead (void)
447 {
448   if (file_id < 0) {
449     sys_error (ERR_WARNING, "Tried to arrayDataRead with file_id < 0");
450     return (false);
451   }
452
453   lseek (file_id, headersize, SEEK_SET);
454   T pixelBuffer;
455   for (int ix = 0; ix < mNX; ix++) 
456       for (unsigned int iy = 0; iy < mNY; iy++) {
457           read (file_id, &pixelBuffer, mPixelSize);
458           ConvertNetworkOrder (&pixelBuffer, sizeof(T));
459           array->array_data[ix][iy] = pixelBuffer;
460       }
461
462   return (true);
463 }
464
465 template<class T>
466 bool
467 Array2dFile<T>::labelSeek (unsigned int label_num)
468 {
469   if (label_num > num_labels) {
470     sys_error (ERR_WARNING, "label_num %d > num_labels %d [labelSeek]");
471     return (false);
472   }
473
474   if (array == NULL) {    // Could not have written data if array not allocated
475     sys_error (ERR_WARNING, "array == NULL [labelSeek]");
476     return (false);
477   }
478
479   off_t pos = headersize + array->sizeofArray();
480   if (lseek (file_id, pos, SEEK_SET) != pos) {
481     sys_error (ERR_WARNING, "Can't seek to end of data array");
482     return (false);
483   }
484
485   for (int i = 0; i < label_num; i++)
486       {
487           pos += 22;  // Skip to string length
488           if (lseek (file_id, pos, SEEK_SET) != pos) {
489             sys_error (ERR_WARNING, "Can't seek to string length");
490             return (false);
491           }
492           kuint16 strlength;
493           read_nint16 (&strlength, file_id);
494           pos += 2 + strlength;  // Skip label string length + data
495           if (lseek (file_id, pos, SEEK_SET) != pos) {
496             sys_error (ERR_WARNING, "Can't seek past label string");
497             return (false);
498           }
499       }
500
501   return (true);
502 }
503
504 template<class T>
505 bool
506 Array2dFile<T>::labelRead (Array2dFileLabel& label, unsigned int label_num)
507 {
508   if (label_num >= num_labels) {
509     sys_error (ERR_WARNING, "Trying to read past number of labels [labelRead]");
510     return (false);
511   }
512
513   if (! labelSeek (label_num)) {
514     sys_error (ERR_WARNING, "Error calling labelSeek");
515     return (false);
516   }
517
518   read_nint16 (&label.label_type, file_id);
519   read_nint16 (&label.year, file_id);
520   read_nint16 (&label.month, file_id);
521   read_nint16 (&label.day, file_id);
522   read_nint16 (&label.hour, file_id);
523   read_nint16 (&label.minute, file_id);
524   read_nint16 (&label.second, file_id);
525   read_nfloat64 (&label.calc_time, file_id);
526
527   kuint16 strlength;
528   read_nint16 (&strlength, file_id);
529   char *str = new char [strlength+1];
530   read (file_id, str, strlength);
531   label.label_str = str;
532
533   return (true);
534 }
535
536
537 template<class T>
538 void
539 Array2dFile<T>::labelAdd (const char* const lstr, double calc_time=0.)
540 {
541   labelAdd (Array2dFileLabel::L_HISTORY, lstr, calc_time);
542 }
543
544 template<class T>
545 void
546 Array2dFile<T>::labelAdd (int type, const char* const lstr, double calc_time=0.)
547 {
548   Array2dFileLabel label (type, lstr, calc_time);
549
550   labelAdd (label);
551 }
552
553 template<class T>
554 void
555 Array2dFile<T>::labelAdd (const Array2dFileLabel& label)
556 {
557   labelSeek (num_labels);
558   
559   write_nint16 (&label.label_type, file_id);
560   write_nint16 (&label.year, file_id);
561   write_nint16 (&label.month, file_id);
562   write_nint16 (&label.day, file_id);
563   write_nint16 (&label.hour, file_id);
564   write_nint16 (&label.minute, file_id);
565   write_nint16 (&label.second, file_id);
566   write_nfloat64 (&label.calc_time, file_id);
567   kuint16 strlength = label.label_str.length();
568   write_nint16 (&strlength, file_id);
569   write (file_id, static_cast<const void*>(label.label_str.c_str()), strlength);
570
571   num_labels++;
572
573   headerWrite();
574   fsync(file_id);
575 }
576
577 template<class T>
578 void
579 Array2dFile<T>::labelsCopy (Array2dFile& copyFile, const char* const idStr)
580 {
581     string id = idStr;
582     for (int i = 0; i < copyFile.getNumLabels(); i++) {
583       Array2dFileLabel l;
584       copyFile.labelRead (l, i);
585       string lstr = l.getLabelString();
586       lstr = idStr + lstr;
587       l.setLabelString (lstr);
588       labelAdd (l);
589     }
590 }
591
592 template<class T>
593 void 
594 Array2dFile<T>::arrayDataClear (void)
595 {
596     if (array != NULL) {
597         T** v = array->getArray();
598         for (unsigned int ix = 0; ix < mNX; ix++)
599             for (unsigned int iy = 0; iy < mNY; iy++)
600                 v[ix][iy] = 0;
601     }
602 }
603
604
605 #ifdef MPI_CT
606 #include <mpi.h>
607 #endif
608
609 class F32Image
610 {
611 public:
612   Array2dFile<kfloat32> adf;
613
614   F32Image (const char* const fname, unsigned int nx, unsigned int ny) : adf (fname, nx, ny)
615   {
616       adf.setPixelType (Array2dFile<kfloat64>::FLOAT32);
617   }
618
619   F32Image (unsigned int nx, unsigned int ny) : adf (nx, ny)
620   {
621       adf.setPixelType (Array2dFile<kfloat64>::FLOAT32);
622   }
623
624   F32Image (const char* const fname) : adf (fname)
625   {
626       adf.setPixelType (Array2dFile<kfloat64>::FLOAT32);
627   }
628
629   kfloat32** getArray(void) const
630       { return adf.getArray(); }
631
632   kuint32 nx(void) const
633       { return adf.nx(); }
634
635   kuint32 ny(void) const
636       { return adf.ny(); }
637
638 #ifdef HAVE_MPI
639   MPI::Datatype getMPIDataType (void) const
640       { return MPI::FLOAT; }
641 #endif
642 };
643
644
645 class F64Image 
646 {
647 public:
648   Array2dFile<kfloat64> adf;
649
650 #ifdef HAVE_MPI
651   MPI::Datatype getMPIDataType (void) const
652       { return MPI::DOUBLE; }
653 #endif
654
655   F64Image (const char* const fname, unsigned int nx, unsigned int ny) : adf (fname, nx, ny)
656   {
657       adf.setPixelType (Array2dFile<kfloat64>::FLOAT64);
658   }
659
660   F64Image (unsigned int nx, unsigned int ny) : adf (nx, ny)
661   {
662       adf.setPixelType (Array2dFile<kfloat64>::FLOAT64);
663   }
664
665   F64Image (const char* const fname) : adf (fname)
666   {
667       adf.setPixelType (Array2dFile<kfloat64>::FLOAT64);
668   }
669
670   kfloat64** getArray(void) const
671       { return adf.getArray(); }
672
673   kuint32 nx(void) const
674       { return adf.nx(); }
675
676   kuint32 ny(void) const
677       { return adf.ny(); }
678 };
679
680 typedef F64Image   ImageFile;
681 typedef kfloat64   ImageFileValue;
682 typedef kfloat64*  ImageFileColumn;
683 typedef kfloat64** ImageFileArray;
684
685 #endif
686
687
688