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