cctw  0.2.1
cctwimporter.cpp
Go to the documentation of this file.
1 #include "cctwimporter.h"
2 #include "cctwapplication.h"
3 #include <QDir>
4 #include <QtConcurrentRun>
5 #include "qcepmutexlocker.h"
6 #include "cctwinputdatah5.h"
7 
8 CctwImporter::CctwImporter(CctwApplication *application, QString name, QObject *parent) :
9  CctwObject(name, parent),
10  m_Application(application),
11  m_BacklogSemaphore(8),
12  m_CompletionSemaphore(0),
13  m_FileId(-1),
14  m_DatasetId(-1),
15  m_DataspaceId(-1),
16  m_InputBuffer(NULL),
17  m_InputBufferCount(0),
18  m_DarkImage(new QcepImageData<double>(QcepSettingsSaverWPtr(),0,0)),
19  m_DataFormat(m_Application->saver(), this, "dataFormat", 0, "Imported data format (0=auto)"),
20  m_DarkImagePath(m_Application->saver(), this, "darkImagePath", "", "Dark image path"),
21  m_ImagePaths(m_Application->saver(), this, "imagePaths", QcepStringList(), "Imported image paths"),
22  m_ImageDirectory(m_Application->saver(), this, "imageDirectory", "", "Image directory"),
23  m_ImagePattern(m_Application->saver(), this, "imagePattern", "", "Image pattern"),
24  m_OutputPath(m_Application->saver(), this, "outputPath", "./output.h5", "Destination for imported data"),
25  m_OutputDataset(m_Application->saver(), this, "outputDataset", "/data", "Destination Dataset for imported data"),
26  m_ChunkSize(m_Application->saver(), this, "chunkSize", CctwIntVector3D(32,32,32), "output chunk size"),
27  m_Compression(m_Application->saver(), this, "compression", 0, "output compression type"),
28  m_XDimension(QcepSettingsSaverWPtr(), this, "xDimension", 0, "X Dimension of output"),
29  m_YDimension(QcepSettingsSaverWPtr(), this, "yDimension", 0, "Y Dimension of output"),
30  m_ZDimension(QcepSettingsSaverWPtr(), this, "zDimension", 0, "Z Dimension of output"),
31  m_InputDataBuffering(m_Application->saver(), this, "inputDataBuffering", 0, "Input Data Buffering"),
32  m_CheckRigorously(m_Application->saver(), this, "checkRigorously", false, "Perform rigorous check (every element) of imported data"),
33  m_CheckApproximately(m_Application->saver(), this, "checkApproximately", true, "Perform approximate check (about 30 seconds) of imported data")
34 {
35 }
36 
38 {
40 }
41 
43 {
44  prop_ImagePaths()->clear();
45 }
46 
48 {
49  set_ImageDirectory(path);
50 }
51 
53 {
54  prop_ImagePaths()->appendValue(path);
55 }
56 
57 void CctwImporter::appendMatchingFiles(QString pattern)
58 {
59  set_ImagePattern(pattern);
60 
61  QDir d(get_ImageDirectory());
62  d.setFilter(QDir::Files);
63 
64  QStringList patts(pattern);
65  d.setNameFilters(patts);
66 
67  QStringList newFiles = d.entryList();
68 
69  QStringList l = get_ImagePaths();
70 
71  l.append(newFiles);
72 
73  set_ImagePaths(l);
74 }
75 
77 {
78  QString dkPath = get_DarkImagePath();
79 
80  if (dkPath.length() > 0) {
81  if (m_DarkImage->readImage(get_DarkImagePath())) {
82  printMessage(tr("Reading dark image from %1").arg(dkPath));
83  m_DarkImage->loadMetaData();
84  } else {
85  printMessage(tr("Failed to read dark image from %1").arg(dkPath));
86  }
87  } else {
88  printMessage(tr("No dark image specified"));
89  }
90 }
91 
93 {
94  QTime startAt;
95  startAt.start();
96 
97  QStringList paths = get_ImagePaths();
98  int n = paths.count();
99  QVector< QFuture<void> > results(n);
100  QDir inp(get_ImageDirectory());
101 
102  if (m_Application) {
104  m_Application->set_Progress(0);
105  m_Application->set_Halting(false);
106  m_Application->set_ProgressLimit(n);
107  }
108 
109  loadDarkImage();
110 
111  printMessage(tr("Importing %1 frames of data").arg(n));
112 
113  set_ZDimension(n);
114 
115  if (get_InputDataBuffering() <= 1) {
116  for (int i=0; i<n; i++) {
117  if (m_Application) {
119  }
120 
121  m_BacklogSemaphore.acquire(1);
122  // printMessage("acquired backlog semaphore");
123  QtConcurrent::run(this, &CctwImporter::importDataFrame,
124  i, inp.filePath(paths[i]));
125  }
126  } else {
127  int nb = get_InputDataBuffering();
128 
130 
131  for (int i=0; i<n; i++) {
132  if (m_Application) {
134  }
135 
136  readDataFrameToBuffer(i, nb, inp.filePath(paths[i]));
137  }
138 
140 
142  }
143 
144  // waitTillFinished();
145 
146  m_CompletionSemaphore.acquire(n);
147  closeOutputFile();
148 
149  if (m_Application->get_Halting()) {
150  printMessage(tr("Import Cancelled after %1 sec").arg(startAt.elapsed()/1000.0));
151  } else {
152  printMessage(tr("Import Completed after %1 sec").arg(startAt.elapsed()/1000.0));
153  }
154 }
155 
157 {
158  QcepMutexLocker lock(__FILE__, __LINE__, &m_OutputMutex);
159 
160  if (m_FileId >= 0) {
161  return true;
162  }
163 
164  printMessage("About to open output file");
165 
166  int res = true;
167 
168  QString fileName = get_OutputPath();
169  QFileInfo f(fileName);
170 
171  hid_t fileId = -1;
172  hid_t gplist = -1;
173  hid_t dsetId = -1;
174  hid_t dspcId = -1;
175  hid_t plist = -1;
176 
177  if (!f.exists()) {
178  // file does not exist...
179  fileId = H5Fcreate(qPrintable(fileName), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
180 
181  if (fileId < 0) {
182  printMessage(tr("File %1 could not be created").arg(fileName));
183  res = false;
184  }
185  } else if (H5Fis_hdf5(qPrintable(get_OutputPath())) <= 0) {
186  printMessage(tr("File %1 exists but is not an hdf file").arg(fileName));
187  res = false;
188  } else {
189  fileId = H5Fopen(qPrintable(fileName), H5F_ACC_RDWR, H5P_DEFAULT);
190 
191  if (fileId < 0) {
192  printMessage(tr("File %1 could not be opened").arg(fileName));
193  res = false;
194  }
195  }
196 
197  if (fileId > 0) {
198  // File exists and is hdf5 - does the dataset exist
199 
200  dsetId = H5Dopen(fileId, qPrintable(get_OutputDataset()), H5P_DEFAULT);
201 
202  if (dsetId >= 0) {
203  dspcId = H5Dget_space(dsetId);
204 
205  if (dspcId < 0) {
206  printMessage("Couldn't get dataspace of existing dataset");
207  res = false;
208  } else {
209  hsize_t dims[3];
210  int ndims = H5Sget_simple_extent_ndims(dspcId);
211 
212  if (ndims != 3) {
213  printMessage("Dataspace is not 3-dimensional");
214  res = false;
215  } else {
216  int ndims2 = H5Sget_simple_extent_dims(dspcId, dims, NULL);
217 
218  if (ndims2 != 3) {
219  printMessage("Couldnt get dataspace dimensions");
220  res = false;
221  } else {
222  if (dims[0] != (hsize_t) get_ZDimension() ||
223  dims[1] != (hsize_t) get_YDimension() ||
224  dims[2] != (hsize_t) get_XDimension()) {
225  printMessage("Dataspace dimensions do not match imported data");
226  res = false;
227  }
228  }
229  }
230  }
231  } else {
232  hsize_t dims[3];
233  dims[0] = get_ZDimension();
234  dims[1] = get_YDimension();
235  dims[2] = get_XDimension();
236 
237  dspcId = H5Screate_simple(3, dims, NULL);
238 
239  CctwIntVector3D cksz = get_ChunkSize();
240  int cmprs = get_Compression();
241 
242  plist = H5Pcreate(H5P_DATASET_CREATE);
243 
244  if (cksz.volume() > 0) {
245  hsize_t c[3];
246 
247  c[0] = cksz.z();
248  c[1] = cksz.y();
249  c[2] = cksz.x();
250 
251  if (H5Pset_chunk(plist, 3, c) < 0) {
252  printMessage("Failed to set chunk size");
253  return false;
254  }
255 
256  if (cmprs) {
257  if (H5Pset_deflate(plist, cmprs) < 0) {
258  printMessage("Set deflate failed");
259  return false;
260  }
261  }
262  }
263 
264  gplist = H5Pcreate(H5P_LINK_CREATE);
265 
266  if (H5Pset_create_intermediate_group(gplist, 1) < 0) {
267  printMessage(tr("Failed to set create intermediate groups"));
268  res = false;
269  } else {
270  dsetId = H5Dcreate(fileId,
271  qPrintable(get_OutputDataset()),
272  H5T_NATIVE_FLOAT,
273  dspcId,
274  gplist,
275  plist,
276  H5P_DEFAULT);
277  }
278  }
279 
280  if (dsetId < 0) {
281  printMessage(tr("Could not create or find dataset"));
282  res = false;
283  }
284  }
285 
286  if (plist >= 0) H5Pclose(plist);
287  if (gplist >= 0) H5Pclose(gplist);
288 
289  if (res == false) {
290  if (dspcId >= 0) H5Sclose(dspcId);
291  if (dsetId >= 0) H5Dclose(dsetId);
292  if (fileId >= 0) H5Fclose(fileId);
293  } else {
294  if (fileId < 0 || dsetId < 0 || dspcId < 0) {
295  printMessage(tr("Anomaly in CctwImporter::createOutputFile fileId=%1, dsetId=%2, dspcId=%3")
296  .arg(fileId).arg(dsetId).arg(dspcId));
297  }
298 
299  m_FileId = fileId;
300  m_DatasetId = dsetId;
301  m_DataspaceId = dspcId;
302  }
303 
304  return res;
305 }
306 
308 {
309  QcepMutexLocker lock(__FILE__, __LINE__, &m_OutputMutex);
310 
311  if (m_FileId >= 0) {
312  if (m_DataspaceId >= 0) {
313  H5Sclose(m_DataspaceId);
314  m_DataspaceId = -1;
315  }
316 
317  if (m_DatasetId >= 0) {
318  H5Dclose(m_DatasetId);
319  m_DatasetId = -1;
320  }
321 
322  H5Fclose(m_FileId);
323 
324  printMessage("Closed output file");
325 
326  m_FileId = -1;
327  }
328 }
329 
331 {
332  QcepMutexLocker lock(__FILE__, __LINE__, &m_OutputMutex);
333 
334  printMessage(tr("Writing output frame %1").arg(num));
335 
336  if (m_FileId >= 0) {
337  hid_t memspace_id;
338  hsize_t offset[3], count[3], stride[3], block[3];
339 
340  count[0] = 1;
341  count[1] = get_YDimension();
342  count[2] = get_XDimension();
343 
344  stride[0] = 1;
345  stride[1] = 1;
346  stride[2] = 1;
347 
348  block[0] = 1;
349  block[1] = 1;
350  block[2] = 1;
351 
352  offset[0] = num;
353  offset[1] = 0;
354  offset[2] = 0;
355 
356  memspace_id = H5Screate_simple(3, count, NULL);
357 
358  herr_t selerr = H5Sselect_hyperslab(m_DataspaceId, H5S_SELECT_SET, offset, stride, count, block);
359  herr_t wrterr = H5Dwrite(m_DatasetId, H5T_NATIVE_DOUBLE, memspace_id, m_DataspaceId, H5P_DEFAULT, img->data());
360 
361  if (selerr || wrterr) {
362  printMessage(tr("Error writing frame %1, selerr = %2, wrterr = %3").arg(num).arg(selerr).arg(wrterr));
363  }
364  }
365 }
366 
367 void CctwImporter::importDataFrame(int num, QString path)
368 {
369  m_BacklogSemaphore.release(1);
370 
371  if (m_Application && !m_Application->get_Halting()) {
372  if (path.length() > 0) {
373 
374  QcepImageData<double> m(QcepSettingsSaverWPtr(), 0, 0);
375 
376  if (m.readImage(path)) {
377  m.loadMetaData();
378 
379  printMessage(tr("Imported frame %1 from %2").arg(num).arg(path));
380 
381  m.subtractDark(m_DarkImage);
382 
383  set_XDimension(m.get_Width());
384  set_YDimension(m.get_Height());
385 
386  if (createOutputFile()) {
387  writeOutputFrame(num, &m);
388  } else {
389  m_Application->set_Halting(true);
390  }
391  }
392  }
393  }
394 
395  m_CompletionSemaphore.release(1);
396 
397  if (m_Application) {
398  m_Application->prop_Progress()->incValue(1);
400  }
401 }
402 
404 {
406 }
407 
408 void CctwImporter::allocateDataBuffer(hsize_t dimx, hsize_t dimy, hsize_t dimz)
409 {
410  m_InputBufferStride = dimx*dimy;
411  m_InputBufferSize = dimx*dimy*dimz;
412 
413  m_InputBuffer = new float[m_InputBufferSize];
414  m_InputBufferStart = 0;
415  m_InputBufferCount = 0;
416 }
417 
419 {
420  if (m_InputBuffer) {
421  delete [] m_InputBuffer;
422 
423  m_InputBuffer = 0;
424  m_InputBufferStart = 0;
425  m_InputBufferCount = 0;
426  m_InputBufferSize = 0;
428  }
429 }
430 
431 void CctwImporter::readDataFrameToBuffer(int i, int nb, QString path)
432 {
433  if (m_Application && !m_Application->get_Halting()) {
434  if (path.length() > 0) {
435 
436  QcepImageData<double> m(QcepSettingsSaverWPtr(), 0, 0);
437 
438  if (m.readImage(path)) {
439  m.loadMetaData();
440 
441  printMessage(tr("Imported frame %1 from %2").arg(i).arg(path));
442 
443  m.subtractDark(m_DarkImage);
444 
445  if (m_InputBuffer == NULL) {
446  set_XDimension(m.get_Width());
447  set_YDimension(m.get_Height());
448 
449  allocateDataBuffer(get_XDimension(), get_YDimension(), nb);
450 
451  if (!createOutputFile()) {
452  m_Application->set_Halting(true);
453  }
454  }
455 
456  hsize_t ibuf = i % nb;
457 
458  if (ibuf == 0) {
460  }
461 
462  double *frame = m.data();
463  float *dest = m_InputBuffer + ibuf*m_InputBufferStride;
464 
465  for (hsize_t i=0; i<m_InputBufferStride; i++) {
466  *dest++ = *frame++;
467  }
468 
469  m_InputBufferCount = ibuf+1;
470  }
471  }
472  }
473 
474  m_CompletionSemaphore.release(1);
475 
476  if (m_Application) {
477  m_Application->prop_Progress()->incValue(1);
479  }
480 }
481 
483 {
484  QcepMutexLocker lock(__FILE__, __LINE__, &m_OutputMutex);
485 
486  printMessage(tr("Writing output from frames %1 to %2")
487  .arg(m_InputBufferStart)
489 
490  if (m_FileId >= 0) {
491  hid_t memspace_id;
492  hsize_t offset[3], count[3], stride[3], block[3];
493 
494  count[0] = m_InputBufferCount;
495  count[1] = get_YDimension();
496  count[2] = get_XDimension();
497 
498  stride[0] = 1;
499  stride[1] = 1;
500  stride[2] = 1;
501 
502  block[0] = 1;
503  block[1] = 1;
504  block[2] = 1;
505 
506  offset[0] = m_InputBufferStart;
507  offset[1] = 0;
508  offset[2] = 0;
509 
510  memspace_id = H5Screate_simple(3, count, NULL);
511 
512  herr_t selerr = H5Sselect_hyperslab(m_DataspaceId, H5S_SELECT_SET, offset, stride, count, block);
513  herr_t wrterr = H5Dwrite(m_DatasetId, H5T_NATIVE_FLOAT, memspace_id, m_DataspaceId, H5P_DEFAULT, m_InputBuffer);
514 
515  if (selerr || wrterr) {
516  printMessage(tr("Error writing frames %1 to %2, selerr = %3, wrterr = %4")
517  .arg(m_InputBufferStart)
519  .arg(selerr)
520  .arg(wrterr));
521  }
522  }
523 
524  m_InputBufferStart = i;
525  m_InputBufferCount = 0;
526 }
527 
529 {
530  printMessage("Checking imported data...");
531 
532  loadDarkImage();
533 
534  if (get_CheckRigorously()) {
536  }
537 
538  if (get_CheckApproximately()) {
540  }
541 }
542 
544 {
545  CctwInputDataH5 data(get_OutputPath(), get_OutputDataset(), "h5import", this);
546 
547  printMessage("Checking imported data rigorously...");
548 }
549 
550 static int randomIndex(int n)
551 {
552  return qrand()%n;
553 }
554 
556 {
557  CctwInputDataH5 data(get_OutputPath(), get_OutputDataset(), "h5import", this);
558 
559  printMessage("Checking imported data approximately...");
560 
561  QTime startAt;
562  startAt.start();
563 
564  QStringList paths = get_ImagePaths();
565  QDir inp(get_ImageDirectory());
566  int n=0;
567 
568  for (int nz = 0; nz<5; nz++) {
569  QcepImageData<double> m(QcepSettingsSaverWPtr(), 0, 0);
570 
571  if (m.readImage(inp.filePath(paths[nz]))) {
572  m.loadMetaData();
573  m.subtractDark(m_DarkImage);
574 
575  for (int nx = 0; nx<5; nx++) {
576  for (int ny = 0; ny<5; ny++) {
577  double fromTiff = m.getImageData(nx, ny);
578  double fromHDF = data.readData(nx, ny, nz);
579 
580  printLine(tr("[%1,%2,%3] TF: %4, H5 %5")
581  .arg(nx).arg(ny).arg(nz).arg(fromTiff).arg(fromHDF));
582  }
583  }
584  }
585  }
586 
587  while (startAt.elapsed() < 60*1000 && !m_Application->get_Halting() && n < 100) {
588  int nz = randomIndex(data.dimensions().z());
589 
590  QcepImageData<double> m(QcepSettingsSaverWPtr(), 0, 0);
591 
592  if (m.readImage(inp.filePath(paths[nz]))) {
593  m.loadMetaData();
594 
595  m.subtractDark(m_DarkImage);
596 
597  for (int i=0; i<100 && !m_Application->get_Halting() && n < 100; i++) {
598  int nx = randomIndex(data.dimensions().x());
599  int ny = randomIndex(data.dimensions().y());
600 
601  double fromTiff = m.getImageData(nx, ny);
602  double fromHDF = data.readData(nx, ny, nz);
603  double fromHDFt = data.readData(nx, data.dimensions().y() - ny, nz);
604 
605  if (fromTiff != fromHDF) {
606  n++;
607  printMessage(tr("Mismatch at [%1,%2,%3]: %4 <=> %5, %6")
608  .arg(nx).arg(ny).arg(nz)
609  .arg(fromTiff).arg(fromHDF).arg(fromHDFt));
610  }
611  }
612  } else {
613  printMessage(tr("Failed to load image %1 [%2]")
614  .arg(nz).arg(paths[nz]));
615  }
616  }
617 
618  if (m_Application->get_Halting()) {
619  printMessage("Testing interrupted");
620  }
621 }
void readDataFrameToBuffer(int i, int nb, QString path)
QSemaphore m_CompletionSemaphore
Definition: cctwimporter.h:52
QMutex m_OutputMutex
Definition: cctwimporter.h:50
float * m_InputBuffer
Definition: cctwimporter.h:58
hid_t m_DataspaceId
Definition: cctwimporter.h:56
QSharedPointer< QcepImageData< double > > m_DarkImage
Definition: cctwimporter.h:64
hsize_t m_InputBufferSize
Definition: cctwimporter.h:61
QSemaphore m_BacklogSemaphore
Definition: cctwimporter.h:51
void writeOutputFrame(int num, QcepImageData< double > *img)
hid_t m_FileId
Definition: cctwimporter.h:54
void checkImportedData()
virtual void printMessage(QString msg, QDateTime dt=QDateTime::currentDateTime())
Definition: cctwobject.cpp:25
void checkImportedDataRigorously()
virtual ~CctwImporter()
virtual double readData(int dx, int dy, int dz)
CctwApplication * m_Application
Definition: cctwimporter.h:49
T x() const
Definition: cctwvector3d.h:17
void addWorkOutstanding(int amt)
CctwIntVector3D dimensions() const
void checkImportedDataApproximately()
void importData()
void loadDarkImage()
hid_t m_DatasetId
Definition: cctwimporter.h:55
void clearInputFiles()
hsize_t m_InputBufferStride
Definition: cctwimporter.h:62
void initializeDataBuffer()
void outputDataFromBuffer(int i)
bool createOutputFile()
void deleteDataBuffer()
T z() const
Definition: cctwvector3d.h:19
void workCompleted(int amt)
virtual void printLine(QString line)
Definition: cctwobject.cpp:14
void importDataFrame(int num, QString path)
int m_InputBufferCount
Definition: cctwimporter.h:60
void changeDirectory(QString path)
static int randomIndex(int n)
void closeOutputFile()
T volume() const
void appendInputFile(QString path)
CctwImporter(CctwApplication *application, QString name, QObject *parent=0)
Definition: cctwimporter.cpp:8
T y() const
Definition: cctwvector3d.h:18
void allocateDataBuffer(hsize_t dimx, hsize_t dimy, hsize_t dimz)
void appendMatchingFiles(QString pattern)
int m_InputBufferStart
Definition: cctwimporter.h:59