QXRD  0.11.16
qcepimagedata.cpp
Go to the documentation of this file.
1 #include "qcepdebug.h"
2 #include "qcepdataobject.h"
3 #include "qcepimagedata.h"
4 #include "qcepmaskdata.h"
5 #include "qcepallocator.h"
6 
7 #include <QSettings>
8 #include <QFileInfo>
9 #include <QDir>
10 #include <QScriptEngine>
11 #include <typeinfo>
12 #include <QMetaProperty>
13 
14 #include "qcepimagedataformat.h"
16 #include "qcepmutexlocker.h"
17 #include "qcepsettingssaver.h"
18 
19 #include "tiffio.h"
20 
21 QAtomicInt allocCount = 0;
22 
24  : QcepDataObject(saver, tr("image"), size, parent),
25  m_Width(saver, this, "width", width, "Image Width"),
26  m_Height(saver, this, "height", height, "Image Height"),
27  m_HStart(saver, this, "hStart", 0.0, "H Start Coord"),
28  m_HStep(saver, this, "hStep", 1.0, "H Step"),
29  m_VStart(saver, this, "vStart", 0.0, "V Start Coord"),
30  m_VStep(saver, this, "vStep", 1.0, "V Step"),
31  m_HLabel(saver, this, "hLabel", "X", "H Label"),
32  m_HUnits(saver, this, "hUnits", "pix", "H Units"),
33  m_VLabel(saver, this, "vLabel", "Y", "V Label"),
34  m_VUnits(saver, this, "vUnits", "pix", "V Units"),
35  m_DataType(saver, this, "dataType", UndefinedData, "Data Type of Image"),
36  m_FileBase(saver, this, "fileBase", "", "File Base of Image"),
37  m_Title(saver, this, "title", "", "Title of Image"),
38  m_ReadoutMode(saver, this, "readoutMode", 0, "Image Readout Mode"),
39  m_ExposureTime(saver, this, "exposureTime", 0, "Image Exposure Time"),
40  m_SummedExposures(saver, this, "summedExposures", 0, "Summed Exposures in Image"),
41  m_ImageSequenceNumber(saver, this, "imageSequenceNumber", -1, "Image Sequence Number"),
42  m_ImageNumber(saver, this, "imageNumber", 0, "Image Number"),
43  m_PhaseNumber(saver, this, "phaseNumber", -1, "Image Phase Number"),
44  m_NPhases(saver, this, "nPhases", -1, "Number of Image Phases"),
45  m_DateTime(saver, this, "dateTime", QDateTime::currentDateTime(), "Image Creation Date and Time"),
46  m_TimeStamp(saver, this, "timeStamp", secondsSinceEpoch(), "Image creation time (secs after UNIX epoch)"),
47  m_HBinning(saver, this, "hBinning", 1, "Image Horizontal Binning Factor"),
48  m_VBinning(saver, this, "vBinning", 1, "Image Vertical Binning Factor"),
49  m_CameraGain(saver, this, "cameraGain", 0, "Image Detector Gain"),
50  m_Triggered(saver, this, "triggered", 0, "Triggered Flag"),
51  m_UserComment1(saver, this,"userComment1","", "User Comment 1"),
52  m_UserComment2(saver, this,"userComment2","", "User Comment 2"),
53  m_UserComment3(saver, this,"userComment3","", "User Comment 3"),
54  m_UserComment4(saver, this,"userComment4","", "User Comment 4"),
55  m_Normalization(saver, this, "normalization", QcepDoubleList(), "Normalization Values"),
56  m_ExtraInputs(saver, this, "extraInputs", QcepDoubleList(), "Extra Input Values"),
57  m_Used(saver, this, "used", true, "Image Used?"),
58  m_ImageCounter(allocCount.fetchAndAddOrdered(1)),
59  m_Mutex(QMutex::Recursive),
60  m_Saver(saver)
61 {
62  set_Type("Image");
63 
65  printf("QcepImageDataBase::QcepImageDataBase(%p)\n", this);
66  }
67 
69 }
70 
72 {
74  printf("QcepImageDataBase::~QcepImageDataBase(%p)\n", this);
75 // QcepSettingsSaverPtr s(m_Saver);
76 
77 // if (s) {
78 // s->printMessage(tr("QcepImageDataBase::~QcepImageDataBase %1[%2]")
79 // .HEXARG(this).arg(m_ImageCounter));
80 // }
81  }
82 
83  QcepAllocator::deallocate(get_ByteSize());
84 }
85 
87 {
88  return tr("[%1 x %2] elements").arg(get_Width()).arg(get_Height());
89 }
90 
91 void QcepImageDataBase::printMessage(QString msg, QDateTime ts) const
92 {
94 
95  if (s) {
96  s->printMessage(msg, ts);
97  } else {
98  printf("%s\n", qPrintable(msg));
99  }
100 }
101 
103 {
104 #if QT_VERSION >= 0x040700
105  return QDateTime::currentMSecsSinceEpoch()/1000.0;
106 #else
107  QDateTime dt = QDateTime::currentDateTime();
108  time_t dt_t = dt.toTime_t();
109  int msec = dt.time().msec();
110 
111  return ((double) dt_t) + msec/1000.0;
112 #endif
113 }
114 
116 {
117  return &m_Mutex;
118 }
119 
121 {
122  dest -> set_Type(get_Type());
123  dest -> set_Creator(get_Creator());
124  dest -> set_Version(get_Version());
125  dest -> set_QtVersion(get_QtVersion());
126  dest -> set_DataType(get_DataType());
127  dest -> set_FileBase(get_FileBase());
128  dest -> set_FileName(get_FileName());
129  dest -> set_Title(get_Title());
130  dest -> set_ReadoutMode(get_ReadoutMode());
131  dest -> set_ExposureTime(get_ExposureTime());
132  dest -> set_SummedExposures(get_SummedExposures());
133  dest -> set_ImageSequenceNumber(get_ImageSequenceNumber());
134  dest -> set_ImageNumber(get_ImageNumber());
135  dest -> set_PhaseNumber(get_PhaseNumber());
136  dest -> set_NPhases(get_NPhases());
137  dest -> set_DateTime(get_DateTime());
138  dest -> set_HBinning(get_HBinning());
139  dest -> set_VBinning(get_VBinning());
140  dest -> set_CameraGain(get_CameraGain());
141  dest -> set_Triggered(get_Triggered());
142  dest -> set_UserComment1(get_UserComment1());
143  dest -> set_UserComment2(get_UserComment2());
144  dest -> set_UserComment3(get_UserComment3());
145  dest -> set_UserComment4(get_UserComment4());
146  dest -> set_ObjectSaved(get_ObjectSaved());
147  dest -> set_Normalization(get_Normalization());
148  dest -> set_ExtraInputs(get_ExtraInputs());
149  dest -> set_Used(get_Used());
150 
151  QByteArray name;
152 
153  foreach(name, dynamicPropertyNames()) {
154  dest -> setProperty(name.data(), property(name.data()));
155  }
156 }
157 
158 void QcepImageDataBase::copyPropertiesFrom(QSharedPointer<QcepImageDataBase> src)
159 {
160  set_Type(src -> get_Type());
161  set_Creator(src -> get_Creator());
162  set_Version(src -> get_Version());
163  set_QtVersion(src->get_QtVersion());
164  set_DataType(src -> get_DataType());
165  set_FileBase(src -> get_FileBase());
166  set_FileName(src -> get_FileName());
167  set_Title(src -> get_Title());
168  set_ReadoutMode(src -> get_ReadoutMode());
169  set_ExposureTime(src -> get_ExposureTime());
170  set_SummedExposures(src -> get_SummedExposures());
171  set_ImageSequenceNumber(src -> get_ImageSequenceNumber());
172  set_ImageNumber(src -> get_ImageNumber());
173  set_PhaseNumber(src -> get_PhaseNumber());
174  set_NPhases(src -> get_NPhases());
175  set_DateTime(src -> get_DateTime());
176  set_HBinning(src -> get_HBinning());
177  set_VBinning(src -> get_VBinning());
178  set_CameraGain(src -> get_CameraGain());
179  set_Triggered(src -> get_Triggered());
180  set_UserComment1(src -> get_UserComment1());
181  set_UserComment2(src -> get_UserComment2());
182  set_UserComment3(src -> get_UserComment3());
183  set_UserComment4(src -> get_UserComment4());
184  set_ObjectSaved(src -> get_ObjectSaved());
185  set_Normalization(src -> get_Normalization());
186  set_ExtraInputs(src -> get_ExtraInputs());
187  set_Used(src -> get_Used());
188 
189  QByteArray name;
190 
191  foreach(name, src -> dynamicPropertyNames()) {
192  setProperty(name.data(), src -> property(name.data()));
193  }
194 }
195 
197 {
198 // printf("QcepImageDataBase::loadMetaData for file %s\n", qPrintable(get_FileName()));
199 
200  QTime tic;
201  tic.start();
202 
203  {
204  set_Creator("Unknown");
205  set_Version("Unknown");
206  set_QtVersion("Unknown");
207 
208  QcepMutexLocker lock(__FILE__, __LINE__, mutex());
209 
210  QSettings settings(get_FileName()+".metadata", QSettings::IniFormat);
211 
212  QcepProperty::readSettings(this, &settings, "metadata");
213 
214  if (settings.contains("metadata/qxrdVersion")) {
215  set_Creator("QXRD");
216  set_Version(settings.value("metadata/qxrdVersion").toString());
217  }
218  }
219 //
220 // printf("QcepImageDataBase::loadMetaData for file %s took %d msec\n", qPrintable(get_FileName()), tic.elapsed());
221 }
222 
224 {
225  saveMetaData(get_FileName());
226 }
227 
229 {
230 // printf("QcepImageDataBase::saveMetaData for file %s\n", qPrintable(name));
231 
232  QTime tic;
233  tic.start();
234 
235 // printf("type 266 = %s\n", QMetaType::typeName(266));
236 
237  {
238  QcepMutexLocker lock(__FILE__, __LINE__, mutex());
239 
240  QSettings settings(name+".metadata", QSettings::IniFormat);
241 
242  QcepProperty::writeSettings(this, &settings, "metadata");
243 
244  settings.beginWriteArray("normalization");
245  QcepDoubleList norm = get_Normalization();
246 
247  for (int i=0; i<norm.length(); i++) {
248  settings.setArrayIndex(i);
249  settings.setValue("val",norm[i]);
250  }
251  settings.endArray();
252  }
253 //
254 // printf("QcepImageDataBase::saveMetaData for file %s took %d msec\n", qPrintable(name), tic.elapsed());
255 }
256 
258 {
259  set_FileName(path);
260  set_Title(QFileInfo(path).fileName());
261 }
262 
264 {
265  switch (get_DataType()) {
266  default:
267  case UndefinedData:
268  return "Undefined";
269 
270  case Raw16Data:
271  return "16 Bit Raw Data";
272 
273  case Raw32Data:
274  return "32 Bit Raw Data";
275 
276  case DarkData:
277  return "Dark Data";
278 
279  case MaskData:
280  return "Mask Data";
281 
282  case SubtractedData:
283  return "Subtracted Data";
284 
285  case GainData:
286  return "Pixel Gain Data";
287 
288  case BadPixelsData:
289  return "Bad Pixel Data";
290  }
291 }
292 
294 {
295  return fileFormatTIFF() + ";;" +
296  fileFormatTabDelimited() + ";;" +
298  fileFormatCSV() + ";;" +
300 }
301 
303 {
304  return "TIFF (*.tif, *.tiff)";
305 }
306 
308 {
309  return "Tab delimited (*.txt.*.dat)";
310 }
311 
313 {
314  return "Transposed Tab delimited (*.txt,*.dat)";
315 }
316 
318 {
319  return "CSV (*.csv)";
320 }
321 
323 {
324  return "Transposed CSV (*.csv)";
325 }
326 
327 double QcepImageDataBase::hValue(int n) const
328 {
329  return get_HStart() + n*get_HStep();
330 }
331 
332 double QcepImageDataBase::vValue(int n) const
333 {
334  return get_VStart() + n*get_VStep();
335 }
336 
337 template <typename T>
339  : QcepImageDataBase(saver, width, height, width*height*sizeof(T), parent),
340  // m_Image(width*height, def),
341  m_Image(width*height),
342  m_MinValue(0),
343  m_MaxValue(0),
344  m_Default(def),
345  m_Mask(NULL),
346  m_Overflow(NULL)
347 {
349  printMessage(tr("QcepImageData<%1>::QcepImageData %2")
350  .arg(typeid(T).name())
351  .HEXARG(this));
352  }
353 
354  if (def) {
355  m_Image.fill(def);
356  }
357 
358  set_Type("Image Data");
359 }
360 
361 template <typename T>
363 {
365  printMessage(tr("QcepImageData<%1>::~QcepImageData %2")
366  .arg(typeid(T).name())
367  .HEXARG(this));
368  }
369 }
370 
371 template <typename T>
372 QSharedPointer< QcepImageData<T> > QcepImageData<T>::newImage(
373  QcepSettingsSaverWPtr saver, QString name, int width, int height, QcepObject *parent)
374 {
375  QSharedPointer< QcepImageData<T> > res(new QcepImageData<T>(saver, width, height, 0, parent));
376 
377  res->setObjectName(name);
378 
379  return res;
380 }
381 
382 template <typename T>
384 {
385  return m_Image.data();
386 }
387 
388 template <typename T>
389 T QcepImageData<T>::value(int x, int y) const
390 {
391  if (x >= 0 && x < get_Width() && y >= 0 && y < get_Height()) {
392  return m_Image.value((get_Height()-y-1)*get_Width()+x);
393  }
394 
395  return m_Default;
396 }
397 
398 template <typename T>
399 T QcepImageData<T>::value(double x, double y) const
400 {
401  int ix = ((int) x), iy = ((int) y);
402  double dx = x-ix, dy = y-iy;
403 
404  double f00 = value((ix) , (iy));
405  double f10 = value((ix+1) , (iy));
406  double f01 = value((ix) , (iy+1));
407  double f11 = value((ix+1) , (iy+1));
408 
409  double f0 = f00*(1-dx)+f10*dx;
410  double f1 = f01*(1-dx)+f11*dx;
411 
412  double f = f0*(1-dy)+f1*dy;
413 
414  return f;
415 }
416 
417 template <typename T>
418 QVector<double> QcepImageData<T>::getImageData(int x0, int y0, int x1, int y1) const
419 {
420  QVector<double> res;
421 
422  for (int y=y0; y<y1; y++) {
423  for (int x=x0; x<x1; x++) {
424  res << this->value(x,y);
425  }
426  }
427 
428  return res;
429 }
430 
431 template <typename T>
432 double QcepImageData<T>::getImageData(int x, int y) const
433 {
434  return this->value(x,y);
435 }
436 
437 //template <typename T>
438 //void QcepImageData<T>::fill(T val)
439 //{
440 // m_Image.fill(val);
441 //}
442 
443 template <typename T>
444 void QcepImageData<T>::fill(double val)
445 {
446  m_Image.fill(val);
447 }
448 
449 template <typename T>
450 void QcepImageData<T>::setImageData(int x, int y, double v)
451 {
452  if (x >= 0 && x < get_Width() && y >= 0 && y < get_Height()) {
453  m_Image[(get_Height()-y-1)*get_Width()+x] = v;
454  }
455 }
456 
457 template <typename T>
458 void QcepImageData<T>::setValue(int x, int y, T val)
459 {
460  if (x >= 0 && x < get_Width() && y >= 0 && y < get_Height()) {
461  m_Image[(get_Height()-y-1)*get_Width()+x] = val;
462  }
463 }
464 
465 template <typename T>
466 void QcepImageData<T>::addValue(int x, int y, T val)
467 {
468  if (x >= 0 && x < get_Width() && y >= 0 && y < get_Height()) {
469  m_Image[(get_Height()-y-1)*get_Width()+x] += val;
470  }
471 }
472 
473 template <typename T>
474 void QcepImageData<T>::subtractValue(int x, int y, T val)
475 {
476  if (x >= 0 && x < get_Width() && y >= 0 && y < get_Height()) {
477  m_Image[(get_Height()-y-1)*get_Width()+x] -= val;
478  }
479 }
480 
481 template <typename T>
482 void QcepImageData<T>::multiplyValue(int x, int y, T val)
483 {
484  if (x >= 0 && x < get_Width() && y >= 0 && y < get_Height()) {
485  m_Image[(get_Height()-y-1)*get_Width()+x] *= val;
486  }
487 }
488 
489 template <typename T>
490 void QcepImageData<T>::divideValue(int x, int y, T val)
491 {
492  if (x >= 0 && x < get_Width() && y >= 0 && y < get_Height()) {
493  m_Image[(get_Height()-y-1)*get_Width()+x] /= val;
494  }
495 }
496 
497 //template <typename T>
498 //T QcepImageData<T>::minValue() const
499 //{
500 // return m_MinValue;
501 //}
502 
503 //template <typename T>
504 //T QcepImageData<T>::maxValue() const
505 //{
506 // return m_MaxValue;
507 //}
508 
509 template <typename T>
511 {
512  T *img = m_Image.data();
513  int total = m_Image.count();
514  int first = true;
515 
516  m_MinValue = 0;
517  m_MaxValue = 0;
518 
519  for (int i = 0; i<total; i++) {
520  T val = img[i];
521 
522  if (val == val) { // NaN test...
523  if (first) {
524  m_MaxValue = val;
525  m_MinValue = val;
526  first = false;
527  } else if (val > m_MaxValue) {
528  m_MaxValue = val;
529  } else if (val < m_MinValue) {
530  m_MinValue = val;
531  }
532  }
533  }
534 }
535 
536 template <typename T>
538 {
539  bool first = 1;
540 
541  double cx = get_Width()/2, cy = get_Height()/2;
542 
543  m_MinValue = 0;
544  m_MaxValue = 0;
545 
546  for (int y=0; y<get_Height(); y++) {
547  double dy = (((double)y)-cy)/cy;
548  double dx = sqrt(1-dy*dy);
549  int x0 = (int) (cx-dx*cx);
550  int x1 = (int) (cx+dx*cx);
551 
552  for (int x=x0; x<x1; x++) {
553  T val = value(x,y);
554 
555  if (val == val) { // NaN test...
556  if (first) {
557  m_MinValue = val;
558  m_MaxValue = val;
559  first = false;
560  } else if (val > m_MaxValue) {
561  m_MaxValue = val;
562  } else if (val < m_MinValue) {
563  m_MinValue = val;
564  }
565  }
566  }
567  }
568 }
569 
570 template <typename T>
571 void QcepImageData<T>::dumpPixels(int x0, int y0, int x1, int y1)
572 {
573  for (int y=y0; y<y1; y++) {
574  for (int x=x0; x<x1; x++) {
575  printf("%g ", (double) value(x,y));
576  }
577  printf("\n");
578  }
579 }
580 
581 template <typename T>
583 {
584  QcepImageData<T> temp(QcepSettingsSaverPtr(), get_Width(), get_Height(), 0, this);
585 
586  int oldwidth = get_Width();
587  int oldheight= get_Height();
588 
589  for (int y=0; y<oldheight; y++) {
590  for (int x=0; x<oldwidth; x++) {
591  temp.setValue(x, y, value(x,y));
592  }
593  }
594 
595  set_Width(width);
596  set_Height(height);
597 
598  m_Image.resize(width*height);
599 
600  for (int y=0; y<height; y++) {
601  for (int x=0; x<width; x++) {
602  setValue(x, y, temp.value(x,y));
603  }
604  }
605 
606  set_ByteSize(width*height*sizeof(T));
607 
608  QcepAllocator::allocate((width*height - oldwidth*oldheight)*sizeof(T));
609 }
610 
611 template <typename T>
613 {
614  m_Image.fill(m_Default);
615 }
616 
617 template <typename T>
619 {
620  return m_Default;
621 }
622 
623 template <typename T>
625 {
626  m_Default = def;
627 }
628 
629 template <typename T>
630 bool QcepImageData<T>::readImage(QString path)
631 {
632  QcepImageDataFormat<T> *loader =
634 
635  if (loader) {
636  bool res = loader -> loadFile(path, this);
637 
638  if (res) {
639  QString fileBase = QFileInfo(path).fileName();
640 
641  set_FileBase(fileBase);
642  set_Title(fileBase);
643  set_FileName(path);
644  set_ObjectSaved(true);
645  }
646 
647  return res;
648  } else {
649  return false;
650  }
651 }
652 
653 template <typename T>
654 template <typename T2>
655 void QcepImageData<T>::subtractDark(const QSharedPointer< QcepImageData<T2> > dark)
656 {
657  // if (get_PerformDarkSubtraction()) {
658  if (dark->get_ExposureTime() != this->get_ExposureTime()) {
659  printMessage("Exposure times of acquired data and dark image are different, skipping");
660  return;
661  }
662 
663  if (dark->get_Width() != this->get_Width() ||
664  dark->get_Height() != this->get_Height()) {
665  printMessage("Dimensions of acquired data and dark image are different, skipping");
666  return;
667  }
668 
669  if (dark->get_CameraGain() != this->get_CameraGain()) {
670  printMessage("Gains of acquired data and dark image are different, skipping");
671  return;
672  }
673 
674  // if (!(image->get_DataType() == QcepDoubleImageData::Raw16Data ||
675  // image->get_DataType() == QcepDoubleImageData::Raw32Data)) {
676  // printMessage("Acquired data is not a raw image, skipping background subtraction");
677  // return;
678  // }
679 
680  QcepMutexLocker lock1(__FILE__, __LINE__, dark->mutex());
681  QcepMutexLocker lock2(__FILE__, __LINE__, this->mutex());
682 
683  int height = this->get_Height();
684  int width = this->get_Width();
685  int nres = this -> get_SummedExposures();
686  int ndrk = dark -> get_SummedExposures();
687  int npixels = width*height;
688 
689  if (nres <= 0) nres = 1;
690 
691  double ratio = ((double) nres)/((double) ndrk);
692 
693  // printf("Dark subtraction nres=%d, ndrk=%d, npixels=%d, ratio=%g\n",
694  // nres, ndrk, npixels, ratio);
695 
696  double *result = this->data();
697  T2 *dk = dark->data();
698  double avgraw = 0;
699  // double avgdark = 0;
700 
701  for (int i=0; i<npixels; i++) {
702  // avgdark += dk[i];
703  avgraw += result[i];
704  result[i] = result[i]-ratio*dk[i];
705  }
706 
707  // set_AverageDark(avgdark/npixels/ndrk);
708 // set_AverageRaw(avgraw/npixels/nres);
709 // set_Average(get_AverageRaw() - get_AverageDark());
710 
711  this -> set_DataType(SubtractedData);
712 }
713 
714 template <typename T>
716 {
717  QFileInfo info(QcepImageData<T>::get_FileName());
718 
719  QString name = info.dir().filePath(info.completeBaseName()+".raw.tif");
720 
721  return name;
722 }
723 
724 template <typename T>
725 template <typename T2>
726 void QcepImageData<T>::copyImage(QSharedPointer< QcepImageData<T2> > dest)
727 {
728  if (dest) {
729  int ncols = this -> get_Width();
730  int nrows = this -> get_Height();
731  int npix = ncols*nrows;
732 
733  dest -> resize(ncols, nrows);
734 
735  this -> copyProperties(dest.data());
736 
737  T *srcp = this -> data();
738  T2 *destp = dest -> data();
739 
740  for (int i=0; i<npix; i++) {
741  *destp++ = *srcp++;
742  }
743  }
744 }
745 
746 template <typename T>
747 template <typename T2>
749 {
750  if (img) {
751  int ncols = img -> get_Width();
752  int nrows = img -> get_Height();
753  int npix = ncols*nrows;
754 
755  this -> resize(ncols, nrows);
756 
757  this -> copyPropertiesFrom(img);
758 
759  T2 *srcp = img -> data();
760  T *destp = this -> data();
761 
762  for (int i=0; i<npix; i++) {
763  *destp++ = *srcp++;
764  }
765  }
766 }
767 
768 template <typename T>
769 template <typename T2>
771 {
772  if (image) {
773  int ncols = this -> get_Width();
774  int nrows = this -> get_Height();
775 
776  this->prop_SummedExposures()->incValue(image->get_SummedExposures());
777 
778  if (ncols == image->get_Width() && nrows == image->get_Height()) {
779  int npix = ncols*nrows;
780 
781  T *srcp = this -> data();
782  T2 *destp = image -> data();
783 
784  for (int i=0; i<npix; i++) {
785  *srcp++ += *destp++;
786  }
787  } else {
788  for (int row=0; row<nrows; row++) {
789  for (int col=0; col<ncols; col++) {
790  this -> addValue(col, row, image->value(col, row));
791  }
792  }
793 
794  QcepDoubleList norm = this->get_Normalization();
795  QcepDoubleList extra = this->get_ExtraInputs();
796 
797  QcepDoubleList norm2 = image->get_Normalization();
798  QcepDoubleList extra2= image->get_ExtraInputs();
799 
800  for (int i=0; i<norm.count(); i++) {
801  norm[i] += norm2.value(i);
802  }
803 
804  for (int i=0; i<extra.count(); i++) {
805  extra[i] += extra2.value(i);
806  }
807 
808  this->set_Normalization(norm);
809  this->set_ExtraInputs(extra);
810  }
811  }
812 }
813 
814 template <typename T>
815 template <typename T2>
816 void QcepImageData<T>::add(QSharedPointer< QcepImageData<T2> > image)
817 {
818  if (image) {
819  int ncols = this -> get_Width();
820  int nrows = this -> get_Height();
821 
822  this->prop_SummedExposures()->incValue(image->get_SummedExposures());
823 
824  if (ncols == image->get_Width() && nrows == image->get_Height()) {
825  int npix = ncols*nrows;
826 
827  T *srcp = this -> data();
828  T2 *destp = image -> data();
829 
830  for (int i=0; i<npix; i++) {
831  *srcp++ += *destp++;
832  }
833  } else {
834  for (int row=0; row<nrows; row++) {
835  for (int col=0; col<ncols; col++) {
836  this -> addValue(col, row, image->value(col, row));
837  }
838  }
839  }
840  }
841 }
842 
843 template <typename T>
844 template <typename T2>
845 void QcepImageData<T>::subtract(QSharedPointer< QcepImageData<T2> > image)
846 {
847  if (image) {
848  int ncols = this -> get_Width();
849  int nrows = this -> get_Height();
850 
851  this->prop_SummedExposures()->incValue(image->get_SummedExposures());
852 
853  if (ncols == image->get_Width() && nrows == image->get_Height()) {
854  int npix = ncols*nrows;
855 
856  T *srcp = this -> data();
857  T2 *destp = image -> data();
858 
859  for (int i=0; i<npix; i++) {
860  *srcp++ -= *destp++;
861  }
862  } else {
863  for (int row=0; row<nrows; row++) {
864  for (int col=0; col<ncols; col++) {
865  this -> subtractValue(col, row, image->value(col, row));
866  }
867  }
868  }
869  }
870 }
871 
872 template <typename T>
873 template <typename T2>
874 void QcepImageData<T>::multiply(QSharedPointer< QcepImageData<T2> > image)
875 {
876  if (image) {
877  int ncols = this -> get_Width();
878  int nrows = this -> get_Height();
879 
880  this->prop_SummedExposures()->incValue(image->get_SummedExposures());
881 
882  if (ncols == image->get_Width() && nrows == image->get_Height()) {
883  int npix = ncols*nrows;
884 
885  T *srcp = this -> data();
886  T2 *destp = image -> data();
887 
888  for (int i=0; i<npix; i++) {
889  *srcp++ *= *destp++;
890  }
891  } else {
892  for (int row=0; row<nrows; row++) {
893  for (int col=0; col<ncols; col++) {
894  this -> multiplyValue(col, row, image->value(col, row));
895  }
896  }
897  }
898  }
899 }
900 
901 template <typename T>
902 template <typename T2>
903 void QcepImageData<T>::divide(QSharedPointer< QcepImageData<T2> > image)
904 {
905  if (image) {
906  int ncols = this -> get_Width();
907  int nrows = this -> get_Height();
908 
909  this->prop_SummedExposures()->incValue(image->get_SummedExposures());
910 
911  if (ncols == image->get_Width() && nrows == image->get_Height()) {
912  int npix = ncols*nrows;
913 
914  T *srcp = this -> data();
915  T2 *destp = image -> data();
916 
917  for (int i=0; i<npix; i++) {
918  *srcp++ /= *destp++;
919  }
920  } else {
921  for (int row=0; row<nrows; row++) {
922  for (int col=0; col<ncols; col++) {
923  this -> divideValue(col, row, image->value(col, row));
924  }
925  }
926  }
927  }
928 }
929 
930 template <typename T>
931 double QcepImageData<T>::correlate(QSharedPointer<QcepImageData<T> > image, int dx, int dy, int mx, int my)
932 {
933  double sum=0;
934 
935  if (image) {
936  int wd = this->get_Width();
937  int ht = this->get_Height();
938 
939  for (int y=my; y<ht-my; y++) {
940  for (int x=mx; x<wd-mx; x++) {
941  sum += this->value(x,y)*image->value(x+dx,y+dy);
942  }
943  }
944  }
945 
946  return sum;
947 }
948 
949 template <typename T>
950 void QcepImageData<T>::shiftImage(QSharedPointer<QcepImageData<T> > image, double dx, double dy)
951 {
952  if (image) {
953  int wd = this->get_Width();
954  int ht = this->get_Height();
955 
956  for (int y=0; y<ht; y++) {
957  for (int x=0; x<wd; x++) {
958  this->setValue(x,y, image->value(x+dx,y+dy));
959  }
960  }
961  }
962 }
963 
964 template <typename T>
966 {
967  m_Mask = mask;
969 }
970 
971 template <typename T>
973 {
974  return m_Mask;
975 }
976 
977 template <typename T>
979 {
980  return m_Overflow;
981 }
982 
983 template <typename T>
985 {
986  return findMin();
987 }
988 
989 template <typename T>
991 {
992  return findMax();
993 }
994 
995 template <typename T>
997 {
998  int ncols = this -> get_Width();
999  int nrows = this -> get_Height();
1000  int first = true;
1001  T minv = 0;
1002 
1003  for (int row=0; row<nrows; row++) {
1004  for (int col=0; col<ncols; col++) {
1005  if (m_Mask == NULL || m_Mask->value(col,row)) {
1006  T val = this->value(col, row);
1007 
1008  if (val == val) { // Skip NaNs
1009  if (first) {
1010  minv = val;
1011  first = false;
1012  } else if (val < minv){
1013  minv = val;
1014  }
1015  }
1016  }
1017  }
1018  }
1019 
1020  return minv;
1021 }
1022 
1023 template <typename T>
1025 {
1026  int ncols = this -> get_Width();
1027  int nrows = this -> get_Height();
1028  int first = true;
1029  T maxv = 0;
1030 
1031  for (int row=0; row<nrows; row++) {
1032  for (int col=0; col<ncols; col++) {
1033  if (m_Mask == NULL || m_Mask->value(col,row)) {
1034  T val = this -> value(col, row);
1035 
1036  if (val == val) {
1037  if (first) {
1038  maxv = val;
1039  first = false;
1040  } else if (val > maxv){
1041  maxv = val;
1042  }
1043  }
1044  }
1045  }
1046  }
1047 
1048  return maxv;
1049 }
1050 
1051 template <typename T>
1053 {
1054  int ncols = this -> get_Width();
1055  int nrows = this -> get_Height();
1056  double npix = 0;
1057  double sum = 0;
1058 
1059  for (int row=0; row<nrows; row++) {
1060  for (int col=0; col<ncols; col++) {
1061  if (m_Mask == NULL || m_Mask->value(col,row)) {
1062  double val = this -> value(col, row);
1063 
1064  if (val==val) {
1065  npix += 1;
1066  sum += val;
1067  }
1068  }
1069  }
1070  }
1071 
1072  if (npix <= 0) {
1073  return 0;
1074  } else {
1075  return sum/npix;
1076  }
1077 }
1078 
1079 template <typename T>
1080 QPointF QcepImageData<T>::percentileRange(double lowpct, double highpct)
1081 {
1082  const int histSize = 65536;
1083  QVector<int> histogramVec(histSize+1);
1084  histogramVec.fill(0.0);
1085  int *histogram = histogramVec.data();
1086 
1087  int ncols = this -> get_Width();
1088  int nrows = this -> get_Height();
1089 
1090  double minVal = minValue();
1091  double maxVal = maxValue();
1092 
1093  double histStep = (maxVal - minVal + 2)/histSize;
1094  int nAbove = 0, nBelow = 0, nTotal = 0;
1095 
1096  for (int row=0; row<nrows; row++) {
1097  for (int col=0; col<ncols; col++) {
1098  if (m_Mask == NULL || m_Mask->value(col, row)) {
1099  double val = value(col, row);
1100 
1101  if (val==val) {
1102  double bin = (val - minVal)/histStep;
1103 
1104  if (bin < 0) {
1105  nBelow += 1;
1106  } else if (bin >= histSize) {
1107  nAbove += 1;
1108  } else {
1109  histogram[(int) bin] += 1;
1110  }
1111 
1112  nTotal += 1;
1113  }
1114  }
1115  }
1116  }
1117 
1118  double lowCount = ((double) nTotal) * lowpct / 100.0;
1119  double highCount = ((double) nTotal) * highpct / 100.0;
1120  double count = nBelow;
1121 
1122  QPointF res(0,0);
1123 
1124  for (int i=0; i<histSize; i++) {
1125  double binVal = minVal + i*histStep;
1126 
1127  count += histogram[i];
1128 
1129  if (count < lowCount) {
1130  res.setX(binVal);
1131  }
1132 
1133  if (count < highCount) {
1134  res.setY(binVal);
1135  }
1136  }
1137 
1138  if (res.y() <= res.x()) {
1139  res.setY(res.x() + 1);
1140  }
1141 
1142  return res;
1143 }
1144 
1145 template <typename T>
1146 void QcepImageData<T>::correctBadBackgroundSubtraction(QcepDoubleImageDataPtr dark, int nImgExposures, int nDarkExposures)
1147 {
1148  int ncols = this -> get_Width();
1149  int nrows = this -> get_Height();
1150 
1151  double badRatio = ((double) this->get_SummedExposures())/((double) dark->get_SummedExposures());
1152  double goodRatio = ((double) nImgExposures)/((double) nDarkExposures);
1153 
1154  for (int row=0; row<nrows; row++) {
1155  for (int col=0; col<ncols; col++) {
1156  double darkValue = dark->value(col,row);
1157  double imgValue = this->value(col,row);
1158 
1159  imgValue += darkValue*badRatio;
1160  imgValue -= darkValue*goodRatio;
1161 
1162  this->setValue(col, row, imgValue);
1163  }
1164  }
1165 
1166  this->set_SummedExposures(nImgExposures);
1167 }
1168 
1169 template <typename T>
1170 QScriptValue QcepImageData<T>::toScriptValue(QScriptEngine *engine, const QSharedPointer< QcepImageData<T> > &data)
1171 {
1172  return engine->newQObject(data.data());
1173 }
1174 
1175 template <typename T>
1176 void QcepImageData<T>::fromScriptValue(const QScriptValue &obj, QSharedPointer<QcepImageData<T> > &data)
1177 {
1178  QObject *qobj = obj.toQObject();
1179 
1180  if (qobj) {
1181  QcepDataObject *qdobj = qobject_cast<QcepDataObject*>(qobj);
1182 
1183  if (qdobj) {
1184  QcepDataObjectPtr p = qdobj->sharedFromThis();
1185 
1186  if (p) {
1187  QSharedPointer<QcepImageData<T> > cs = qSharedPointerDynamicCast< QcepImageData<T> >(p);
1188 
1189  if (cs) {
1190  data = cs;
1191  }
1192  }
1193  }
1194  }
1195 }
1196 
1197 #define TIFFCHECK(a) if (res && ((a)==0)) { res = 0; }
1198 
1199 template <>
1201 {
1202  int nrows = get_Height();
1203  int ncols = get_Width();
1204 
1205  TIFF* tif = TIFFOpen(qPrintable(name),"w");
1206  int res = 1;
1207 
1208  if (tif) {
1209  TIFFCHECK(TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, ncols));
1210  TIFFCHECK(TIFFSetField(tif, TIFFTAG_IMAGELENGTH, nrows));
1211  TIFFCHECK(TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1));
1212 
1213  TIFFCHECK(TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG));
1214  TIFFCHECK(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32));
1215  TIFFCHECK(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP));
1216 
1217  TIFFCHECK(TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, qPrintable(get_FileName())));
1218  TIFFCHECK(TIFFSetField(tif, TIFFTAG_DATETIME, qPrintable(get_DateTime().toString("yyyy:MM:dd hh:mm:ss"))));
1219 
1220  QVector<float> buffvec(ncols);
1221  float* buffer = buffvec.data();
1222 
1223  for (int y=0; y<nrows; y++) {
1224  for (int x=0; x<ncols; x++) {
1225  buffer[x] = value(x,y);
1226  }
1227 
1228  TIFFCHECK(TIFFWriteScanline(tif, buffer, y, 0));
1229  }
1230 
1231  TIFFClose(tif);
1232 
1233  set_FileName(name);
1234  set_ObjectSaved(true);
1235 
1236  saveMetaData();
1237  }
1238 }
1239 
1240 template <typename T>
1242 {
1243  int nrows = get_Height();
1244  int ncols = get_Width();
1245 
1246  TIFF* tif = TIFFOpen(qPrintable(name),"w");
1247  int res = 1;
1248 
1249  if (tif) {
1250  int nsum = get_SummedExposures();
1251 
1252  TIFFCHECK(TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, ncols));
1253  TIFFCHECK(TIFFSetField(tif, TIFFTAG_IMAGELENGTH, nrows));
1254  TIFFCHECK(TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1));
1255 
1256  TIFFCHECK(TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG));
1257 
1258  if (nsum == 0) {
1259  TIFFCHECK(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8));
1260  } else if (nsum == 1) {
1261  TIFFCHECK(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16));
1262  } else {
1263  TIFFCHECK(TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32));
1264  }
1265 
1266  TIFFCHECK(TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT));
1267 
1268  TIFFCHECK(TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, qPrintable(get_FileName())));
1269  TIFFCHECK(TIFFSetField(tif, TIFFTAG_DATETIME, qPrintable(get_DateTime().toString("yyyy:MM:dd hh:mm:ss"))));
1270 
1271  if (nsum == 0) {
1272  QVector<quint8> buffvec(ncols);
1273  quint8* buffer = buffvec.data();
1274 
1275  for (int y=0; y<nrows; y++) {
1276  for (int x=0; x<ncols; x++) {
1277  buffer[x] = value(x,y);
1278  }
1279 
1280  TIFFCHECK(TIFFWriteScanline(tif, buffer, y, 0));
1281  }
1282  } else if (nsum == 1) {
1283  QVector<quint16> buffvec(ncols);
1284  quint16* buffer = buffvec.data();
1285 
1286  for (int y=0; y<nrows; y++) {
1287  for (int x=0; x<ncols; x++) {
1288  buffer[x] = value(x,y);
1289  }
1290 
1291  TIFFCHECK(TIFFWriteScanline(tif, buffer, y, 0));
1292  }
1293  } else {
1294  QVector<quint32> buffvec(ncols);
1295  quint32* buffer = buffvec.data();
1296 
1297  for (int y=0; y<nrows; y++) {
1298  for (int x=0; x<ncols; x++) {
1299  buffer[x] = value(x,y);
1300  }
1301 
1302  TIFFCHECK(TIFFWriteScanline(tif, buffer, y, 0));
1303  }
1304  }
1305 
1306  TIFFClose(tif);
1307 
1308  set_FileName(name);
1309  set_ObjectSaved(true);
1310 
1311  saveMetaData();
1312  }
1313 }
1314 
1315 void QcepImageDataBase::saveTextData(QString name, QString sep, bool transp)
1316 {
1317  FILE *f = fopen(qPrintable(name), "w+");
1318 
1319  if (f) {
1320  const QMetaObject *meta = metaObject();
1321 
1322  int count = meta->propertyCount();
1323  int offset = QObject::staticMetaObject.propertyOffset();
1324 
1325  for (int i=offset; i<count; i++) {
1326  QMetaProperty metaproperty = meta->property(i);
1327  const char *name = metaproperty.name();
1328  QVariant value = property(name);
1329 
1330  fprintf(f, "#%s = %s\n", name, qPrintable(value.toString()));
1331  }
1332 
1333  foreach (QByteArray name, dynamicPropertyNames()) {
1334  QVariant value = property(name);
1335 
1336  fprintf(f, "#%s = %s\n", name.data(), qPrintable(value.toString()));
1337  }
1338 
1339  int nrows = get_Height();
1340  int ncols = get_Width();
1341 
1342  if (transp == false) {
1343  for (int y=0; y<nrows; y++) {
1344  for (int x=0; x<ncols; x++) {
1345  if (x == 0) {
1346  fprintf(f, "%g", getImageData(x,y));
1347  } else {
1348  fprintf(f, "%s%g", qPrintable(sep), getImageData(x,y));
1349  }
1350  }
1351  fprintf(f, "\n");
1352  }
1353  } else { // Transposed
1354  for (int y=0; y<ncols; y++) {
1355  for (int x=0; x<nrows; x++) {
1356  if (x == 0) {
1357  fprintf(f, "%g", getImageData(y,x));
1358  } else {
1359  fprintf(f, "%s%g", qPrintable(sep), getImageData(y,x));
1360  }
1361  }
1362  fprintf(f, "\n");
1363  }
1364  }
1365 
1366  fclose(f);
1367  }
1368 }
1369 
1370 template <typename T>
1371 void QcepImageData<T>::saveData(QString &name, QString filter, Overwrite canOverwrite)
1372 {
1373  mkPath(name);
1374 
1375  if (canOverwrite == NoOverwrite) {
1376  name = uniqueFileName(name);
1377  }
1378 
1379  if (filter == fileFormatTIFF()) {
1380  saveTIFFData(name);
1381  } else if (filter == fileFormatTabDelimited()) {
1382  saveTextData(name, "\t", false);
1383  } else if (filter == fileFormatTransposedTabDelimited()) {
1384  saveTextData(name, "\t", true);
1385  } else if (filter == fileFormatCSV()) {
1386  saveTextData(name, ", ", false);
1387  } else if (filter == fileFormatTransposedCSV()) {
1388  saveTextData(name, ", ", true);
1389  }
1390 }
1391 
1392 template <typename T>
1394 {
1395  int l = qRound(rect.left());
1396  int t = qRound(rect.top());
1397  int r = qRound(rect.right());
1398  int b = qRound(rect.bottom());
1399 
1400  if (l > r) {
1401  l = qRound(rect.right());
1402  r = qRound(rect.left());
1403  }
1404 
1405  if (b > t) {
1406  b = qRound(rect.top());
1407  t = qRound(rect.bottom());
1408  }
1409 
1410  int np = 0;
1411  double sum = 0;
1412 
1413  for (int row=b; row<=t; row++) {
1414  for (int col=l; col<=r; col++) {
1415  if (m_Mask == NULL || m_Mask->value(col, row)) {
1416  T val = value(col, row);
1417 
1418  if (val==val) {
1419  np++;
1420  sum += val;
1421  }
1422  }
1423  }
1424  }
1425 
1426  return sum;
1427 }
1428 
1429 template <typename T>
1431 {
1432  int l = qRound(rect.left());
1433  int t = qRound(rect.top());
1434  int r = qRound(rect.right());
1435  int b = qRound(rect.bottom());
1436 
1437  if (l > r) {
1438  l = qRound(rect.right());
1439  r = qRound(rect.left());
1440  }
1441 
1442  if (b > t) {
1443  b = qRound(rect.top());
1444  t = qRound(rect.bottom());
1445  }
1446 
1447  int np = 0;
1448  double sum = 0;
1449 
1450  for (int row=b; row<=t; row++) {
1451  for (int col=l; col<=r; col++) {
1452  if (m_Mask == NULL || m_Mask->value(col, row)) {
1453  T val = value(col, row);
1454 
1455  if (val==val) {
1456  np++;
1457  sum += val;
1458  }
1459  }
1460  }
1461  }
1462 
1463  return sum/np;
1464 }
1465 
1466 template <typename T>
1468 {
1469  int l = qRound(rect.left());
1470  int t = qRound(rect.top());
1471  int r = qRound(rect.right());
1472  int b = qRound(rect.bottom());
1473 
1474  if (l > r) {
1475  l = qRound(rect.right());
1476  r = qRound(rect.left());
1477  }
1478 
1479  if (b > t) {
1480  b = qRound(rect.top());
1481  t = qRound(rect.bottom());
1482  }
1483 
1484  int first = true;
1485  double min = 0;
1486 
1487  for (int row=b; row<=t; row++) {
1488  for (int col=l; col<=r; col++) {
1489  if (m_Mask == NULL || m_Mask->value(col, row)) {
1490  T val = value(col, row);
1491 
1492  if (val==val) {
1493  if (first) {
1494  min = val;
1495  first = false;
1496  } else if (val < min) {
1497  min = val;
1498  }
1499  }
1500  }
1501  }
1502  }
1503 
1504  return min;
1505 }
1506 
1507 template <typename T>
1509 {
1510  int l = qRound(rect.left());
1511  int t = qRound(rect.top());
1512  int r = qRound(rect.right());
1513  int b = qRound(rect.bottom());
1514 
1515  if (l > r) {
1516  l = qRound(rect.right());
1517  r = qRound(rect.left());
1518  }
1519 
1520  if (b > t) {
1521  b = qRound(rect.top());
1522  t = qRound(rect.bottom());
1523  }
1524 
1525  int first = true;
1526  double max = 0;
1527 
1528  for (int row=b; row<=t; row++) {
1529  for (int col=l; col<=r; col++) {
1530  if (m_Mask == NULL || m_Mask->value(col, row)) {
1531  T val = value(col, row);
1532 
1533  if (val==val) {
1534  if (first) {
1535  max = val;
1536  first = false;
1537  } else if (val > max) {
1538  max = val;
1539  }
1540  }
1541  }
1542  }
1543  }
1544 
1545  return max;
1546 }
1547 
1548 template <typename T>
1550 {
1551  QPointF c = rect.center();
1552  double a = rect.width()/2;
1553  double b = rect.height()/2;
1554 
1555  int bt = qRound(rect.bottom());
1556  int tp = qRound(rect.top());
1557 
1558  int np = 0;
1559  double sum = 0;
1560 
1561  for (int row=tp; row<=bt; row++) {
1562  double y=row - c.y();
1563  double xx = a*sqrt(1 - pow(y/b,2));
1564  int x1 = qRound(c.x() - xx);
1565  int x2 = qRound(c.x() + xx);
1566 
1567  for (int col=x1; col<=x2; col++) {
1568  if (m_Mask == NULL || m_Mask->value(col, row)) {
1569  T val = value(col, row);
1570 
1571  if (val==val) {
1572  np++;
1573  sum += val;
1574  }
1575  }
1576  }
1577  }
1578 
1579  return sum;
1580 }
1581 
1582 template <typename T>
1584 {
1585  QPointF c = rect.center();
1586  double a = rect.width()/2;
1587  double b = rect.height()/2;
1588 
1589  int bt = qRound(rect.bottom());
1590  int tp = qRound(rect.top());
1591 
1592  int np = 0;
1593  double sum = 0;
1594 
1595  for (int row=tp; row<=bt; row++) {
1596  double y=row - c.y();
1597  double xx = a*sqrt(1 - pow(y/b,2));
1598  int x1 = qRound(c.x() - xx);
1599  int x2 = qRound(c.x() + xx);
1600 
1601  for (int col=x1; col<=x2; col++) {
1602  if (m_Mask == NULL || m_Mask->value(col, row)) {
1603  T val = value(col, row);
1604 
1605  if (val==val) {
1606  np++;
1607  sum += val;
1608  }
1609  }
1610  }
1611  }
1612 
1613  return sum/np;
1614 }
1615 
1616 template <typename T>
1618 {
1619  QPointF c = rect.center();
1620  double a = rect.width()/2;
1621  double b = rect.height()/2;
1622 
1623  int bt = qRound(rect.bottom());
1624  int tp = qRound(rect.top());
1625 
1626  int first = true;
1627  double min = 0;
1628 
1629  for (int row=tp; row<=bt; row++) {
1630  double y=row - c.y();
1631  double xx = a*sqrt(1 - pow(y/b,2));
1632  int x1 = qRound(c.x() - xx);
1633  int x2 = qRound(c.x() + xx);
1634 
1635  for (int col=x1; col<=x2; col++) {
1636  if (m_Mask == NULL || m_Mask->value(col, row)) {
1637  T val = value(col, row);
1638 
1639  if (val==val) {
1640  if (first) {
1641  min = val;
1642  first = false;
1643  } else if (val < min) {
1644  min = val;
1645  }
1646  }
1647  }
1648  }
1649  }
1650 
1651  return min;
1652 }
1653 
1654 template <typename T>
1656 {
1657  QPointF c = rect.center();
1658  double a = rect.width()/2;
1659  double b = rect.height()/2;
1660 
1661  int bt = qRound(rect.bottom());
1662  int tp = qRound(rect.top());
1663 
1664  int first = true;
1665  double max = 0;
1666 
1667  for (int row=tp; row<=bt; row++) {
1668  double y=row - c.y();
1669  double xx = a*sqrt(1 - pow(y/b,2));
1670  int x1 = qRound(c.x() - xx);
1671  int x2 = qRound(c.x() + xx);
1672 
1673  for (int col=x1; col<=x2; col++) {
1674  if (m_Mask == NULL || m_Mask->value(col, row)) {
1675  T val = value(col, row);
1676 
1677  if (val==val) {
1678  if (first) {
1679  max = val;
1680  first = false;
1681  } else if (val > max) {
1682  max = val;
1683  }
1684  }
1685  }
1686  }
1687  }
1688 
1689  return max;
1690 }
1691 
1692 template <typename T>
1693 double QcepImageData<T>::sumInPeak(QRectF rect)
1694 {
1695  QPointF c = rect.center();
1696  double w = rect.width()/2;
1697  double h = rect.height()/2;
1698 
1699  int bt = qRound(rect.bottom());
1700  int tp = qRound(rect.top());
1701  int lf = qRound(rect.left());
1702  int rt = qRound(rect.right());
1703 
1704  int ptp = qRound(c.y() - h/2);
1705  int pbt = qRound(c.y() + h/2);
1706  int plf = qRound(c.x() - w/2);
1707  int prt = qRound(c.x() + w/2);
1708 
1709  int np = 0;
1710  double sum = 0;
1711  int npk = 0;
1712  double sumpk = 0;
1713 
1714  for (int row=tp; row<=bt; row++) {
1715  for (int col=lf; col<=rt; col++) {
1716  if (m_Mask == NULL || m_Mask->value(col,row)) {
1717  T val = value(col,row);
1718 
1719  if (val == val) {
1720  if (ptp <= row && row <= pbt && plf <= col && col <= prt) {
1721  npk++;
1722  sumpk += val;
1723  } else {
1724  np++;
1725  sum += val;
1726  }
1727  }
1728  }
1729  }
1730  }
1731 
1732  if (np > 0 && npk > 0) {
1733  double avbk = sum/np;
1734  double avpk = sumpk/npk;
1735 
1736  return (avpk-avbk)*npk;
1737  } else {
1738  return 0;
1739  }
1740 }
1741 
1742 template class QcepImageData<unsigned short>;
1743 template class QcepImageData<short>;
1744 template class QcepImageData<unsigned int>;
1745 template class QcepImageData<int>;
1746 template class QcepImageData<double>;
1747 
1748 template void QcepImageData<double>::subtractDark(const QSharedPointer< QcepImageData<unsigned short> > dark);
1749 template void QcepImageData<double>::subtractDark(const QSharedPointer< QcepImageData<short> > dark);
1750 template void QcepImageData<double>::subtractDark(const QSharedPointer< QcepImageData<unsigned int> > dark);
1751 template void QcepImageData<double>::subtractDark(const QSharedPointer< QcepImageData<int> > dark);
1752 template void QcepImageData<double>::subtractDark(const QSharedPointer< QcepImageData<double> > dark);
1753 
1754 template void QcepImageData<double>::copyFrom<unsigned int>(QSharedPointer<QcepImageData<unsigned int> >);
1755 template void QcepImageData<double>::copyFrom<unsigned short>(QSharedPointer<QcepImageData<unsigned short> >);
1756 template void QcepImageData<double>::copyFrom<double>(QSharedPointer<QcepImageData<double> >);
1757 template void QcepImageData<unsigned int>::copyFrom<unsigned int>(QSharedPointer<QcepImageData<unsigned int> >);
1758 
1759 template void QcepImageData<double>::accumulateImage<double>(QSharedPointer<QcepImageData<double> >);
1760 
1761 template void QcepImageData<double>::add<double>(QSharedPointer<QcepImageData<double> >);
1762 template void QcepImageData<double>::subtract<double>(QSharedPointer<QcepImageData<double> >);
1763 template void QcepImageData<double>::multiply<double>(QSharedPointer<QcepImageData<double> >);
1764 template void QcepImageData<double>::divide<double>(QSharedPointer<QcepImageData<double> >);
void saveTextData(QString name, QString sep, bool transp=false)
double correlate(QSharedPointer< QcepImageData< T > > image, int dx, int dy, int mx, int my)
void shiftImage(QSharedPointer< QcepImageData< T > > image, double dx, double dy)
double sumInPeak(QRectF rect)
static void deallocate(int sz, int width, int height)
QcepMaskDataPtr overflow() const
QcepMaskDataPtr m_Overflow
void subtractValue(int x, int y, T val)
QcepSettingsSaverWPtr m_Saver
void setMask(QcepMaskDataPtr mask, QcepMaskDataPtr overflow)
double maxInRectangle(QRectF rect)
void multiplyValue(int x, int y, T val)
static void readSettings(QObject *object, QSettings *settings, QString section)
qint64 qcepDebug(int cond)
Definition: qcepdebug.cpp:26
#define TIFFCHECK(a)
QString rawFileName()
void addValue(int x, int y, T val)
double maxInEllipse(QRectF rect)
double maxValue() const
double minInRectangle(QRectF rect)
static QSharedPointer< QcepImageData< T > > newImage(QcepSettingsSaverWPtr saver, QString name, int width, int height, QcepObject *parent)
QString uniqueFileName(QString name)
void mkPath(QString filePath)
void resize(int width, int height)
QcepImageData(QcepSettingsSaverWPtr saver, int width, int height, T def, QcepObject *parent)
QString fileFormatTransposedCSV()
void copyImage(QSharedPointer< QcepImageData< T2 > > dest)
static QcepImageDataFormatFactory< T > * factory()
double findAverage() const
double vValue(int n) const
T value(int x, int y) const
QcepImageDataBase(QcepSettingsSaverWPtr saver, int width, int height, int size, QcepObject *parent)
static void fromScriptValue(const QScriptValue &obj, QSharedPointer< QcepImageData< T > > &data)
QcepMaskDataPtr m_Mask
void subtractDark(const QSharedPointer< QcepImageData< T2 > > dark)
void copyProperties(QcepImageDataBase *dest)
void copyPropertiesFrom(QSharedPointer< QcepImageDataBase > src)
void divideValue(int x, int y, T val)
double minInEllipse(QRectF rect)
void calculateRangeInCircle()
static QScriptValue toScriptValue(QScriptEngine *engine, const QSharedPointer< QcepImageData< T > > &data)
T findMax() const
void accumulateImage(QSharedPointer< QcepImageData< T2 > > image)
double sumInRectangle(QRectF rect)
QString fileFormatTIFF()
static void writeSettings(QObject *object, QSettings *settings, QString section)
void setImageData(int x, int y, double v)
virtual double getImageData(int x, int y) const =0
void fill(double val)
QPointF percentileRange(double lowpct, double highpct)
void add(QSharedPointer< QcepImageData< T2 > > image)
double sumInEllipse(QRectF rect)
bool readImage(QString filename)
void divide(QSharedPointer< QcepImageData< T2 > > image)
QList< double > QcepDoubleList
Definition: qcepmacros.h:28
virtual QString fileFormatFilterString()
double hValue(int n) const
void saveTIFFData(QString name)
QSharedPointer< QcepSettingsSaver > QcepSettingsSaverPtr
QAtomicInt allocCount
void printMessage(QString msg, QDateTime ts=QDateTime::currentDateTime()) const
void setValue(int x, int y, T val)
T findMin() const
T defaultValue() const
QString get_DataTypeName() const
#define HEXARG(a)
Definition: qcepdebug.h:50
void multiply(QSharedPointer< QcepImageData< T2 > > image)
QString fileFormatTabDelimited()
void dumpPixels(int x0, int y0, int x1, int y1)
static void allocate(int sz, int width, int height)
QSharedPointer< QcepDataObject > QcepDataObjectPtr
virtual QString description() const
void subtract(QSharedPointer< QcepImageData< T2 > > image)
virtual void saveData(QString &name, QString filter, Overwrite canOverwrite=NoOverwrite)
QVector< T > m_Image
double getImageData(int x, int y) const
QString name
Definition: qcepobject.h:49
QString fileFormatTransposedTabDelimited()
virtual ~QcepImageDataBase()
double minValue() const
void setDefaultValue(T def)
void correctBadBackgroundSubtraction(QcepDoubleImageDataPtr dark, int nImgExposures, int nDarkExposures)
void setDefaultFileName(QString path)
QSharedPointer< QcepMaskData > QcepMaskDataPtr
double averageInRectangle(QRectF rect)
struct tiff TIFF
Definition: qcepimagedata.h:21
void copyFrom(const QSharedPointer< QcepImageData< T2 > > img)
static double secondsSinceEpoch()
QWeakPointer< QcepSettingsSaver > QcepSettingsSaverWPtr
double averageInEllipse(QRectF rect)
QcepSettingsSaverWPtr saver()
QSharedPointer< QcepDoubleImageData > QcepDoubleImageDataPtr
virtual ~QcepImageData()
QcepMaskDataPtr mask() const