cctw  0.2.1
cctwtransformer.cpp
Go to the documentation of this file.
1 #include "cctwtransformer.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include "cctwmatrix3x3.h"
6 #include "cctwapplication.h"
7 #include <QtConcurrentRun>
8 #include "cctwthread.h"
9 #include "cctwdatachunk.h"
10 #include "qcepmutexlocker.h"
11 #include <QFile>
12 
13 #if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
14 #include <QUrlQuery>
15 #endif
16 
17 #ifdef WANT_ANALYSIS_COMMANDS
18 #include "qcepimagedataformattiff.h"
19 #include "qcepimagedata.h"
20 #endif
21 
23  CctwChunkedData *input,
24  CctwChunkedData *output,
26  /*int osx, int osy, int osz, */QString name, QObject *parent) :
27  CctwObject(name, parent),
28  m_Application(application),
29  m_InputData(input),
30  m_OutputData(output),
31  m_Transform(xform),
32 // m_OversampleX(osx),
33 // m_OversampleY(osy),
34 // m_OversampleZ(osz),
35  m_ImageX(NULL),
36  m_ImageY(NULL),
37  m_ImageZ(NULL),
38  m_WeightX(NULL),
39  m_WeightY(NULL),
40  m_WeightZ(NULL),
41  m_WallTime(QcepSettingsSaverWPtr(), this, "wallTime", 0, "Wall Time of last command"),
42  m_BlocksLimit(m_Application->saver(), this, "blocksLimit", 1000, "Blocks Limit"),
43  m_TransformOptions(m_Application->saver(), this, "transformOptions", 0, "Transform Options"),
44  m_OversampleX(m_Application->saver(), this, "oversampleX", 1, "Oversampling along X"),
45  m_OversampleY(m_Application->saver(), this, "oversampleY", 1, "Oversampling along Y"),
46  m_OversampleZ(m_Application->saver(), this, "oversampleZ", 1, "Oversampling along Z"),
47  m_ProjectX(m_Application->saver(), this, "projectX", true, "Project along X"),
48  m_ProjectY(m_Application->saver(), this, "projectY", true, "Project along Y"),
49  m_ProjectZ(m_Application->saver(), this, "projectZ", true, "Project along Z"),
50  m_ProjectDestination(m_Application->saver(), this, "projectDestination", "", "Output path for projected images"),
51  m_Normalization(m_Application->saver(), this, "normalization", 1, "Normalize output data?"),
52  m_Compression(m_Application->saver(), this, "compression", 2, "Compression level for output data"),
53  m_Subset(QcepSettingsSaverWPtr(), this, "subset", "", "Subset specifier"),
54  m_UseDependencies(QcepSettingsSaverWPtr(), this, "useDependencies", 0, "Use dependencies in transform"),
55  m_Skipped(QcepSettingsSaverWPtr(), this, "skipped", 0, "Number of skipped pixels")
56 {
57 }
58 
60 {
61 }
62 
63 void CctwTransformer::writeSettings(QSettings *set, QString section)
64 {
65  CctwObject::writeSettings(set, section);
66 }
67 
68 void CctwTransformer::readSettings(QSettings *set, QString section)
69 {
70  CctwObject::readSettings(set, section);
71 }
72 
74 {
75  if (m_Application && !m_Application->get_Halting()) {
77  }
78 
79  if (m_Application) {
80  m_Application->prop_Progress()->incValue(1);
82  int nchunks = m_InputData->chunkCount().volume();
83 
84 // m_Application->printMessage(tr("Chunk %1/%2 transform complete").arg(n).arg(nchunks));
85  }
86 }
87 
88 
90 {
91  QFile f(path);
92 
93  if (f.open(QFile::WriteOnly | QFile::Truncate)) {
94  QTextStream s(&f);
95 
96  int nchunk = m_InputData->chunkCount().volume();
97 
98  for (int i=0; i<nchunk; i++) {
99  CctwDataChunk *chunk = m_InputData->chunk(i);
100 
101  chunk->sortDependencies();
102 
103  int n = chunk->dependencyCount();
104 
105  for (int j=0; j<n; j++) {
106  int o = chunk->dependency(j);
107 
108  s << i << "\t" << o << endl;
109  }
110  }
111  }
112 }
113 
115 {
117 
118  QFile f(path);
119 
120  if (f.open(QFile::ReadOnly)) {
121  QTextStream s(&f);
122  int i,o;
123 
124  while (!s.atEnd()) {
125  s >> i >> o;
126 
127  addDependency(i, o);
128  }
129  }
130 }
131 
133 {
134  if (data == NULL) data = m_InputData;
135 
136  QString subset = get_Subset();
137 
138  if (subset.length() == 0) {
140  m_SubsetEnd = data->chunkCount();
141 
142  return true;
143  } else {
145  m_SubsetEnd = CctwIntVector3D(0,0,0);
146 
147  CctwIntVector3D chunks = data->chunkCount();
148 
149  QRegExp r("(\\d+)/(\\d+)");
150 
151  if (r.exactMatch(subset)) {
152  int index = r.cap(1).toInt();
153  int nsubs = r.cap(2).toInt();
154  int nbest = 0, bestdx = 0, bestdy = 0, bestdz = 0;
155  int bestnx = 0, bestny = 0, bestnz = 0;
156 
157  if (m_Application->get_Verbosity() >= 2) {
158  printMessage(tr("Subset matched : index = %1 of %2").arg(index).arg(nsubs));
159  }
160 
161  int szx = chunks.x(), szy = chunks.y(), szz = chunks.z();
162 
163  if (m_Application->get_Verbosity() >= 2) {
164  printMessage(tr("Size %1,%2,%3 - total %4")
165  .arg(szx).arg(szy).arg(szz).arg(szx*szy*szz));
166  }
167 
168  for (int dx=1; dx<=szx; dx++) {
169  int nx = (szx + dx - 1)/dx;
170 
171  if (m_Application->get_Verbosity() >= 3) {
172  printMessage(tr("DX:%1:NX:%2").arg(dx).arg(nx));
173  }
174 
175  if (nx > 0) {
176 
177  for (int dy=1; dy <= szy; dy++) {
178  int ny = (szy + dy - 1)/dy;
179 
180  if (m_Application->get_Verbosity() >= 3) {
181  printMessage(tr("DY:%1:NY:%2").arg(dy).arg(ny));
182  }
183 
184  if (ny > 0) {
185  for (int dz=1; dz <= szz; dz++) {
186  int nz = (szz + dz - 1)/dz;
187 
188  if (m_Application->get_Verbosity() >= 3) {
189  printMessage(tr("DZ:%1:NZ:%2").arg(dz).arg(nz));
190  }
191 
192  if (nz > 0) {
193  int ntot = nx*ny*nz;
194 
195  if (m_Application->get_Verbosity() >= 3) {
196  printMessage(tr("SZ:%1,%2,%3; NUM:%4,%5,%6; NSUB:%7; NTOT:%8; NBEST:%9")
197  .arg(dx).arg(dy).arg(dz)
198  .arg(nx).arg(ny).arg(nz)
199  .arg(nsubs).arg(ntot).arg(nbest));
200  }
201 
202  if (ntot <= nsubs) {
203  if (ntot > nbest) {
204  nbest = ntot;
205  bestdx = dx; bestnx = nx;
206  bestdy = dy; bestny = ny;
207  bestdz = dz; bestnz = nz;
208  } else if (ntot == nbest) {
209  int bestmax = qMax(qMax(bestdx,bestdy),bestdz);
210  int newmax = qMax(qMax(dx,dy),dz);
211 
212  if (newmax < bestmax) {
213  bestdx = dx; bestnx = nx;
214  bestdy = dy; bestny = ny;
215  bestdz = dz; bestnz = nz;
216  }
217  }
218  }
219  }
220  }
221  }
222  }
223  }
224  }
225 
226  if (nbest > 0) {
227  if (m_Application->get_Verbosity() >= 2) {
228  printMessage(tr("Best subdivision found: %1,%2,%3 - total %4")
229  .arg(bestdx).arg(bestdy).arg(bestdz).arg(bestnx*bestny*bestnz));
230  }
231 
232  if ((index >= nbest) || (index < 0)) {
233  if (m_Application->get_Verbosity() >= 2) {
234  printMessage(tr("Skipping subset %1 of %2").arg(index).arg(nbest));
235  }
236  return false;
237  } else {
238  // for (int index=0; index<nbest; index++) {
239  int xstride = 1,
240  ystride = bestnx,
241  zstride = bestnx*bestny;
242 
243  int n = index;
244 
245  int z = n / zstride;
246 
247  n %= zstride;
248 
249  int y = n / ystride;
250 
251  n %= ystride;
252 
253  int x = n / xstride;
254 
255  int x0 = x*bestdx, x1 = x0+bestdx;
256  int y0 = y*bestdy, y1 = y0+bestdy;
257  int z0 = z*bestdz, z1 = z0+bestdz;
258 
259  if (x1 > chunks.x()) x1 = chunks.x();
260  if (y1 > chunks.y()) y1 = chunks.y();
261  if (z1 > chunks.z()) z1 = chunks.z();
262 
263  if (m_Application->get_Verbosity() >= 2) {
264  printMessage(tr("Subset %1 : [%2..%3) [%4..%5) [%6..%7)")
265  .arg(index)
266  .arg(x0).arg(x1).arg(y0).arg(y1).arg(z0).arg(z1));
267  }
268 
269  m_SubsetStart = CctwIntVector3D(x0,y0,z0);
270  m_SubsetEnd = CctwIntVector3D(x1,y1,z1);
271 
272  return true;
273  }
274  }
275  } else {
276  printMessage("Subset mismatch");
277  return false;
278  }
279  }
280 
281  return false;
282 }
283 
285 {
286  CctwDataChunk *inputChunk = m_InputData->readChunk(chunkId);
287  QMap<int, CctwDataChunk*> outputChunks;
288 
289  if (inputChunk) {
290 
291  transformChunkData(chunkId, inputChunk, outputChunks);
292 
293  inputChunk->deallocateData();
294  inputChunk->deallocateWeights();
295 
296 // printMessage(tr("Need to merge %1 output chunks from input chunk [%2]")
297 // .arg(outputChunks.count())
298 // .arg(chunkId));
299 
300  if (inputChunk->dependencyCount() && inputChunk->dependencyCount() != outputChunks.count()) {
301  printMessage(tr("Discrepancy between numbers of merged chunks : dependencyCount() = %1, chunks.count() = %2")
302  .arg(inputChunk->dependencyCount()).arg(outputChunks.count()));
303  }
304 
305  foreach(CctwDataChunk *outputChunk, outputChunks) {
306  m_OutputData->mergeChunk(outputChunk);
307 
308  delete outputChunk;
309  }
310 
311  m_InputData->releaseChunkData(chunkId);
312  } else {
313  printMessage(tr("Could not read chunk: %1").arg(chunkId));
314 // exit(1);
315  }
316 }
317 
319  CctwDataChunk *inputChunk,
320  QMap<int, CctwDataChunk*> &outputChunks)
321 {
322  QTime time;
323  time.start();
324 
325  if (m_Application->get_Verbosity() >= 3) {
326  printMessage(tr("Transforming chunk data: %1").arg(chunkId));
327  }
328 
329  QcepDoubleVector anglesvec = m_InputData->get_Angles();
330  QcepDoubleVector weightsvec= m_InputData->get_Weights();
331  QcepIntVector maskvec = m_InputData->get_Mask();
333 
334  int nMask = maskvec.count();
335  int nAngs = anglesvec.count();
336  int nWgts = weightsvec.count();
337 
338  const int *mask = maskvec.constData();
339  const double *angs = anglesvec.constData();
340  const double *wgts = weightsvec.constData();
341 
342  if (nMask <= 0) mask = NULL;
343  if (nAngs <= 0) angs = NULL;
344  if (nWgts <= 0) wgts = NULL;
345 
347  tr("transform-%1").arg(chunkId),
348  angs,
349  NULL);
350 
351  CctwDataChunk *lastChunk = NULL;
352 
353  CctwIntVector3D chStart = inputChunk->chunkStart();
354  CctwIntVector3D chSize = inputChunk->chunkSize();
355  CctwDoubleVector3D dblStart(chStart.x(), chStart.y(), chStart.z());
356 
357  int lastChunkIndex = -1;
358 
359  int osx = get_OversampleX();
360  int osy = get_OversampleY();
361  int osz = get_OversampleZ();
362 
363  int nused = 0, nskipped = 0;
364 
365  double osxstp = osx >= 1 ? 1.0/osx : 0;
366  double osystp = osy >= 1 ? 1.0/osy : 0;
367  double oszstp = osz >= 1 ? 1.0/osz : 0;
368 
369  for (int z=0; z<chSize.z(); z++) {
370  double angle = anglesvec.value(z+chStart.z());
371  double weight = weightsvec.value(z+chStart.z());
372 
373  if ((angs==NULL || angle==angle) &&
374  (wgts==NULL || weight > 0)) {
375 
376  if (wgts==NULL) weight = 1;
377 
378  for (int oz=0; oz<osz; oz++) {
379  for (int y=0; y<chSize.y(); y++) {
380  for (int oy=0; oy<osy; oy++) {
381  for (int x=0; x<chSize.x(); x++) {
382  CctwIntVector3D globalpix(chStart + CctwIntVector3D(x,y,z));
383 
384 
385  if (mask == NULL || mask[(globalpix.y())*dims.x() + globalpix.x()] == 0) {
386  nused++;
387  CctwIntVector3D iprelat(x,y,z);
388  for (int ox=0; ox<osx; ox++) {
389  CctwDoubleVector3D coords = dblStart+CctwDoubleVector3D(x+ox*osxstp, y+oy*osystp, z+oz*oszstp);
390  CctwDoubleVector3D xfmcoord = transform.forward(coords);
391  CctwIntVector3D pixels(xfmcoord);
392 
393  if (m_OutputData->containsPixel(pixels)) {
394  int opchunk = m_OutputData->chunkContaining(pixels);
395  CctwIntVector3D oprelat = pixels - m_OutputData->chunkStart(opchunk);
396 
397  if (opchunk != lastChunkIndex) {
398 
399  lastChunkIndex = opchunk;
400 
401  if (!outputChunks.contains(lastChunkIndex)) {
402  // printMessage(tr("Input Chunk [%1,%2,%3] -> Output Chunk [%4,%5,%6]")
403  // .arg(idx.x()).arg(idx.y()).arg(idx.z())
404  // .arg(opchunk.x()).arg(opchunk.y()).arg(opchunk.z()));
405 
406  CctwDataChunk *chunk =
407  new CctwDataChunk(m_OutputData, lastChunkIndex,
408  tr("chunk-%1").arg(lastChunkIndex), NULL);
409 
410  if (chunk) {
411  chunk->allocateData();
412  chunk->allocateWeights();
413  }
414 
415  outputChunks[lastChunkIndex] = chunk;
416  }
417 
418  lastChunk = outputChunks[lastChunkIndex];
419  }
420 
421  if (lastChunk) {
422  int ox = oprelat.x(), oy = oprelat.y(), oz = oprelat.z();
423  int ix = iprelat.x(), iy = iprelat.y(), iz = iprelat.z();
424 
425  double oval = lastChunk->data(ox, oy, oz);
426  double owgt = lastChunk->weight(ox, oy, oz);
427  double ival = inputChunk->data(ix, iy, iz);
428  double iwgt = inputChunk->weight(ix, iy, iz)*weight;
429 
430  if (iwgt != 0) {
431  lastChunk->setData(ox, oy, oz, oval+ival);
432  lastChunk->setWeight(ox, oy, oz, owgt+iwgt);
433  }
434  }
435  }
436  }
437  } else {
438  nskipped++;
439  }
440  }
441  }
442  }
443  }
444  }
445  }
446 
447  if (m_Application->get_Verbosity() >= 3) {
448  printMessage(tr("Transform chunk data: %1: done. Time %2 s, %3 output chunks, %4 allocated, used %5, skipped %6")
449  .arg(chunkId)
450  .arg(time.elapsed()/1000.0,5)
451  .arg(outputChunks.count())
453  .arg(nused)
454  .arg(nskipped)
455  );
456  }
457 
458  m_Skipped.incValue(nskipped);
459 }
460 
462 {
463  QVector < QFuture < void > > futures;
464 
465  if (m_Application) {
467  m_Application->set_Progress(0);
468  m_Application->set_Halting(false);
469  m_Application->set_ExitStatus(0);
470  }
471 
472  QTime startAt;
473 
474  startAt.start();
475 
476  set_Skipped(0);
477 
478  if (m_Application->get_Verbosity() >= 0) {
479  printMessage("Starting Transform");
480  }
481 
482  if (m_InputData -> beginTransform(true, get_TransformOptions())) {
483  if (m_OutputData -> beginTransform(false, get_TransformOptions())) {
484 
485  m_InputData -> clearMergeCounters();
486  m_OutputData -> clearMergeCounters();
487 
488  CctwDataChunk::resetAllocationLimits(get_BlocksLimit());
489 
491 
492  QVector < int > inputChunks;
493 
494  for (int z=0; z<chunks.z(); z++) {
495  for (int y=0; y<chunks.y(); y++) {
496  for (int x=0; x<chunks.x(); x++) {
498 
499  if (chunk) {
500  int n = chunk->dependencyCount();
501 
502  for (int i=0; i<n; i++) {
503  int ckidx = chunk->dependency(i);
504 
505  if (!inputChunks.contains(ckidx)) {
506  inputChunks.append(ckidx);
507  }
508  }
509  }
510  }
511  }
512  }
513 
514  if (m_Application->get_Verbosity() >= 2) {
515  printMessage(tr("%1 chunks of input data needed").arg(inputChunks.count()));
516  }
517 
518  if ((get_TransformOptions() & 2)) {
519  if (m_Application->get_Verbosity() >= 2) {
520  printMessage("Sorting input chunk list into input order");
521  }
522 
523  qSort(inputChunks.begin(), inputChunks.end());
524  }
525 
526  if (m_Application) {
527  m_Application->set_ProgressLimit(inputChunks.count());
528  }
529 
530  foreach(int ckidx, inputChunks) {
531  if (m_Application) {
533  }
534 
535  if ((get_TransformOptions() & 1) == 0) {
536  futures.append(
537  QtConcurrent::run(this, &CctwTransformer::runTransformChunkNumber, ckidx));
538  } else {
540  }
541  }
542 
543  foreach (QFuture<void> f, futures) {
544  f.waitForFinished();
545  if (m_Application) {
546  m_Application->processEvents();
547  }
548  }
549 
550  set_WallTime(startAt.elapsed()/1000.0);
551 
552  m_OutputData -> endTransform();
553  } else {
554  printMessage("Failed to open output data");
555  m_Application->set_ExitStatus(1);
556  }
557 
558  m_InputData -> endTransform();
559  } else {
560  printMessage("Failed to open input data");
561  m_Application->set_ExitStatus(1);
562  }
563 
564  if (m_Application->get_Verbosity() >= 0) {
565  printMessage(tr("Transform complete after %1 sec, %2 chunks still allocated")
566  .arg(get_WallTime())
568 
569  printMessage(tr("%1 pixels skipped by mask").arg(get_Skipped()));
570  }
571 }
572 
574 {
575  QVector < QFuture < void > > futures;
576 
577  if (m_Application) {
579  m_Application->set_Progress(0);
580  m_Application->set_Halting(false);
581  m_Application->set_ExitStatus(0);
582  }
583 
584  int msec;
585 
586  if (m_InputData -> beginTransform(true, 0)) {
587  if (m_OutputData -> beginTransform(false, 0)) {
588 
589  parseSubset();
590 
591  CctwIntVector3D chunkStart = m_SubsetStart;
592  CctwIntVector3D chunkEnd = m_SubsetEnd;
593  CctwIntVector3D nChunks = chunkEnd - chunkStart;
594 
595  if (m_Application) {
596  m_Application->set_ProgressLimit(nChunks.volume());
597  }
598 
599  QTime startAt;
600 
601  startAt.start();
602 
603  set_Skipped(0);
604 
605  if (m_Application->get_Verbosity() >= 0) {
606  printMessage("Starting Transform");
607  }
608 
609  if (m_Application->get_Verbosity() >= 2) {
610  printMessage(tr("Input Dimensions %1, Output Dimensions %2")
611  .arg(m_InputData->dimensions().toString())
612  .arg(m_OutputData->dimensions().toString()));
613  printMessage(tr("Input Chunk Size %1, Output Chunk Size %2")
614  .arg(m_InputData->chunkSize().toString())
615  .arg(m_OutputData->chunkSize().toString()));
616  printMessage(tr("Input Chunk Count %1, Output Chunk Count %2")
617  .arg(m_InputData->chunkCount().toString())
618  .arg(m_OutputData->chunkCount().toString()));
619  printMessage(tr("Input HDF Chunk Size %1, Output HDF Chunk Size %2")
620  .arg(m_InputData->get_HDFChunkSize().toString())
621  .arg(m_OutputData->get_HDFChunkSize().toString()));
622  }
623 
624  for (int z=chunkStart.z(); z<chunkEnd.z(); z++) {
625  for (int y=chunkStart.y(); y<chunkEnd.y(); y++) {
626  for (int x=chunkStart.x(); x<chunkEnd.x(); x++) {
627  if (m_Application && m_Application->get_Halting()) {
628  goto abort;
629  } else {
630  CctwIntVector3D idx(x,y,z);
631 
632  int n = m_InputData->chunkNumberFromIndex(idx);
633 
634  if (m_Application) {
636  }
637 
638  futures.append(
639  QtConcurrent::run(this, &CctwTransformer::runTransformChunkNumber, n));
640  }
641  }
642  }
643  }
644 
645 abort:
646  foreach (QFuture<void> f, futures) {
647  f.waitForFinished();
648  if (m_Application) {
649  m_Application->processEvents();
650  }
651  }
652 
653  msec = startAt.elapsed();
654 
655  m_OutputData -> flushOutputFile();
656 
657  m_OutputData -> endTransform();
658  } else {
659  printMessage("Failed to open output data");
660  m_Application->set_ExitStatus(1);
661  }
662 
663  m_InputData -> endTransform();
664  } else {
665  printMessage("Failed to open input data");
666  m_Application->set_ExitStatus(1);
667  }
668 
669  if (m_Application->get_Verbosity() >= 0) {
670  printMessage(tr("Transform complete after %1 msec, %2 chunks still allocated")
671  .arg(msec)
673 
674  printMessage(tr("%1 pixels skipped by mask").arg(get_Skipped()));
675  }
676 }
677 
679 {
680  int chunks = m_OutputData->chunkCount().volume();
681 
682  for (int i = 0; i<chunks; i++) {
683  CctwDataChunk *chunk = m_OutputData->chunk(i);
684 
685  if (chunk) {
686  if (chunk->dependencyCount() != chunk->mergeCount()) {
687  printMessage(tr("Anomaly in chunk [%1] : deps %2, merge %3")
688  .arg(i)
689  .arg(chunk->dependencyCount())
690  .arg(chunk->mergeCount()));
691  }
692 
693  if (chunk->dataPointer()) {
694  printMessage(tr("Chunk [%1] still has allocated data").arg(i));
695  }
696 
697  if (chunk->weightsPointer()) {
698  printMessage(tr("Chunk [%1] still has allocated weights").arg(i));
699  }
700  }
701  }
702 }
703 
705 {
706  QcepDoubleVector anglesvec = m_InputData->get_Angles();
707  double *angs = (anglesvec.count()<=0 ? NULL : anglesvec.data());
708 
709  CctwCrystalCoordinateTransform transform(m_Application->parameters(), tr("transform-%1").arg(n), angs, NULL);
710 
712 
713  int lastChunkIndex = -1;
714 
715  CctwDataChunk *chunk = m_InputData->chunk(n);
716 
717  QList<int> outputChunks;
718  QcepIntList result;
719 
720  if (chunk) {
721  CctwIntVector3D chStart = chunk->chunkStart();
722  CctwIntVector3D chSize = chunk->chunkSize();
723  CctwDoubleVector3D dblStart(chStart.x(), chStart.y(), chStart.z());
724 
725  if (m_InputData->containsChunk(idx.x(), idx.y(), idx.z())) {
726  for (int z=0; z<chSize.z(); z++) {
727  for (int y=0; y<chSize.y(); y++) {
728  for (int x=0; x<chSize.x(); x++) {
729  CctwDoubleVector3D coords = dblStart+CctwDoubleVector3D(x,y,z);
730  CctwDoubleVector3D xfmcoord = transform.forward(coords);
731  CctwIntVector3D pixels(xfmcoord);
732 
733  if (m_OutputData->containsPixel(pixels)) {
734  int opchunk = m_OutputData->chunkContaining(pixels);
735 
736  if (opchunk != lastChunkIndex) {
737  lastChunkIndex = opchunk;
738 
739  if (!outputChunks.contains(lastChunkIndex)) {
740  outputChunks.append(opchunk);
741  }
742  }
743  }
744  }
745  }
746  }
747  }
748  }
749 
750  foreach(int chk, outputChunks) {
751  result.append(chk);
752  }
753 
754  qSort(result);
755 
756  return result;
757 }
758 
759 QList<CctwIntVector3D> CctwTransformer::dependencies(int cx, int cy, int cz)
760 {
761  QcepIntList deps = dependencies(m_InputData->chunkNumberFromIndex(CctwIntVector3D(cx,cy,cz)));
762 
763  QList<CctwIntVector3D> res;
764 
765  foreach(int dep, deps) {
766  res.append(m_OutputData->chunkIndexFromNumber(dep));
767  }
768 
769  return res;
770 }
771 
773 {
776 
777  set_UseDependencies(use);
778 }
779 
781 {
782  m_InputData->addDependency(f, t);
784 }
785 
786 #ifdef WANT_ANALYSIS_COMMANDS
787 
788 void CctwTransformer::inputProject(QString path, int axes)
789 {
790  projectDataset(path, m_InputData, axes);
791 }
792 
793 void CctwTransformer::outputProject(QString path, int axes)
794 {
795  projectDataset(path, m_OutputData, axes);
796 }
797 
798 void CctwTransformer::projectDatasetChunk(CctwChunkedData *data, int i, int axes)
799 {
800  if (m_Application && !m_Application->get_Halting()) {
801  CctwDataChunk *chunk = data->readChunk(i);
802 
803  if (chunk) {
804  CctwIntVector3D chStart = chunk->chunkStart();
805  CctwIntVector3D chSize = chunk->chunkSize();
806 
807  int cx = chStart.x(),
808  cy = chStart.y(),
809  cz = chStart.z();
810 
811  QcepImageData<double> *imgx = NULL, *imgy = NULL, *imgz = NULL;
812  QcepImageData<double> *wgtx = NULL, *wgty = NULL, *wgtz = NULL;
813 
814  if (axes & 1) {
815  imgx = new QcepImageData<double>(QcepSettingsSaverWPtr(), chSize.y(), chSize.z());
816  wgtx = new QcepImageData<double>(QcepSettingsSaverWPtr(), chSize.y(), chSize.z());
817  }
818 
819  if (axes & 2) {
820  imgy = new QcepImageData<double>(QcepSettingsSaverWPtr(), chSize.x(), chSize.z());
821  wgty = new QcepImageData<double>(QcepSettingsSaverWPtr(), chSize.x(), chSize.z());
822  }
823 
824  if (axes & 4) {
825  imgz = new QcepImageData<double>(QcepSettingsSaverWPtr(), chSize.x(), chSize.y());
826  wgtz = new QcepImageData<double>(QcepSettingsSaverWPtr(), chSize.x(), chSize.y());
827  }
828 
829  double mindata = chunk->data(0,0,0);
830  double maxdata = mindata;
831  double minwgt = chunk->weight(0,0,0);
832  double maxwgt = minwgt;
833 
834  for (int z=0; z<chSize.z(); z++) {
835  for (int y=0; y<chSize.y(); y++) {
836  for (int x=0; x<chSize.x(); x++) {
837  double data = chunk->data(x,y,z);
838  double wgt = chunk->weight(x,y,z);
839 
840  if (data < mindata) mindata = data;
841  if (data > maxdata) maxdata = data;
842  if (wgt < minwgt) minwgt = wgt;
843  if (wgt > maxwgt) maxwgt = wgt;
844 
845  if (wgt > 0) {
846  if (imgx) {
847  imgx->addValue(y,z,data);
848  wgtx->addValue(y,z,wgt);
849  }
850 
851  if (imgy) {
852  imgy->addValue(x,z,data);
853  wgty->addValue(x,z,wgt);
854  }
855 
856  if (imgz) {
857  imgz->addValue(x,y,data);
858  wgtz->addValue(x,y,wgt);
859  }
860  } else if (data != 0){
861  printMessage(tr("Wgt: %1, Data %2").arg(wgt).arg(data));
862  }
863  }
864  }
865  }
866 
867  {
868  QcepMutexLocker lock(__FILE__, __LINE__, &m_LockX);
869 
870  if (minwgt < m_MinWeight) m_MinWeight = minwgt;
871  if (maxwgt > m_MaxWeight) m_MaxWeight = maxwgt;
872  if (mindata < m_MinData) m_MinData = mindata;
873  if (maxdata > m_MaxData) m_MaxData = maxdata;
874  }
875 
876  if (axes & 1) {
877  QcepMutexLocker lock(__FILE__, __LINE__, &m_LockX);
878 
879  if (m_ImageX && imgx) {
880  for (int z=0; z<chSize.z(); z++) {
881  for (int y=0; y<chSize.y(); y++) {
882  m_ImageX->addValue(cy+y, cz+z, imgx->value(y,z));
883  }
884  }
885  }
886 
887  if (m_WeightX && wgtx) {
888  for (int z=0; z<chSize.z(); z++) {
889  for (int y=0; y<chSize.y(); y++) {
890  m_WeightX->addValue(cy+y, cz+z, wgtx->value(y,z));
891  }
892  }
893  }
894 
895  delete imgx;
896  delete wgtx;
897  }
898 
899  if (axes & 2) {
900  QcepMutexLocker lock(__FILE__, __LINE__, &m_LockY);
901 
902  if (m_ImageY && imgy) {
903  for (int z=0; z<chSize.z(); z++) {
904  for (int x=0; x<chSize.x(); x++) {
905  m_ImageY->addValue(cx+x, cz+z, imgy->value(x,z));
906  }
907  }
908  }
909 
910  if (m_WeightY && wgty) {
911  for (int z=0; z<chSize.z(); z++) {
912  for (int x=0; x<chSize.x(); x++) {
913  m_WeightY->addValue(cx+x, cz+z, wgty->value(x,z));
914  }
915  }
916  }
917 
918  delete imgy;
919  delete wgty;
920  }
921 
922  if (axes & 4) {
923  QcepMutexLocker lock(__FILE__, __LINE__, &m_LockZ);
924 
925  if (m_ImageZ && imgz) {
926  for (int y=0; y<chSize.y(); y++) {
927  for (int x=0; x<chSize.x(); x++) {
928  m_ImageZ->addValue(cx+x, cy+y, imgz->value(x,y));
929  }
930  }
931  }
932 
933  if (m_WeightZ && wgtz) {
934  for (int y=0; y<chSize.y(); y++) {
935  for (int x=0; x<chSize.x(); x++) {
936  m_WeightZ->addValue(cx+x, cy+y, wgtz->value(x,y));
937  }
938  }
939  }
940 
941  delete imgz;
942  delete wgtz;
943  }
944 
945  data->releaseChunkData(i);
946  }
947  }
948 
949  if (m_Application) {
950  m_Application->prop_Progress()->incValue(1);
952  }
953 }
954 
955 void CctwTransformer::projectDataset(QString path, CctwChunkedData *data, int axes)
956 {
957  if (data && data->openInputFile()) {
958  QVector < QFuture < void > > futures;
959 
960  if (m_Application) {
962  m_Application->set_Progress(0);
963  m_Application->set_Halting(false);
964  }
965 
966  QTime startAt;
967 
968  startAt.start();
969 
970  printMessage("Starting Projection");
971 
972  QcepImageDataFormatTiff<double> fmt("TIFF");
973 
974  CctwIntVector3D dims = data->dimensions();
975 
976  m_MinData = INFINITY;
977  m_MaxData = -INFINITY;
978  m_MinWeight = INFINITY;
979  m_MaxWeight = -INFINITY;
980 
981  int px = axes & 1,
982  py = axes & 2,
983  pz = axes & 4;
984 
985  delete m_ImageX;
986  delete m_WeightX;
987  delete m_ImageY;
988  delete m_WeightY;
989  delete m_ImageZ;
990  delete m_WeightZ;
991 
992  if (px) {
993  m_ImageX = new QcepImageData<double>(QcepSettingsSaverWPtr(), dims.y(), dims.z());
994  m_WeightX = new QcepImageData<double>(QcepSettingsSaverWPtr(), dims.y(), dims.z());
995  } else {
996  m_ImageX = NULL;
997  m_WeightX = NULL;
998  }
999 
1000  if (py) {
1001  m_ImageY = new QcepImageData<double>(QcepSettingsSaverWPtr(), dims.x(), dims.z());
1002  m_WeightY = new QcepImageData<double>(QcepSettingsSaverWPtr(), dims.x(), dims.z());
1003  } else {
1004  m_ImageY = NULL;
1005  m_WeightY = NULL;
1006  }
1007 
1008  if (pz) {
1009  m_ImageZ = new QcepImageData<double>(QcepSettingsSaverWPtr(), dims.x(), dims.y());
1010  m_WeightZ = new QcepImageData<double>(QcepSettingsSaverWPtr(), dims.x(), dims.y());
1011  } else {
1012  m_ImageZ = NULL;
1013  m_WeightZ = NULL;
1014  }
1015 
1016 // int nc = data->chunkCount().volume();
1017 
1018 // if (m_Application) {
1019 // m_Application->set_ProgressLimit(nc);
1020 // }
1021 
1022 // for (int i=0; i<nc; i++) {
1023 // if (m_Application) {
1024 // if (m_Application->get_Halting()) break;
1025 
1026 // m_Application->addWorkOutstanding(1);
1027 // }
1028 
1029 // futures.append(
1030 // QtConcurrent::run(this, &CctwTransformer::projectDatasetChunk, data, i, axes));
1031 // }
1032 
1033  parseSubset(data);
1034 
1035  CctwIntVector3D chunkStart = m_SubsetStart;
1036  CctwIntVector3D chunkEnd = m_SubsetEnd;
1037  CctwIntVector3D nChunks = chunkEnd - chunkStart;
1038 
1039  if (m_Application) {
1040  m_Application->set_ProgressLimit(nChunks.volume());
1041  }
1042 
1043  for (int z=chunkStart.z(); z<chunkEnd.z(); z++) {
1044  for (int y=chunkStart.y(); y<chunkEnd.y(); y++) {
1045  for (int x=chunkStart.x(); x<chunkEnd.x(); x++) {
1046  if (m_Application && m_Application->get_Halting()) {
1047  goto abort;
1048  } else {
1049  CctwIntVector3D idx(x,y,z);
1050 
1051  int n = data->chunkNumberFromIndex(idx);
1052 
1053  if (m_Application) {
1055  }
1056 
1057  futures.append(
1058  QtConcurrent::run(this, &CctwTransformer::projectDatasetChunk, data, n, axes));
1059  }
1060  }
1061  }
1062  }
1063 
1064 abort:
1065  foreach (QFuture<void> f, futures) {
1066  f.waitForFinished();
1067  if (m_Application) {
1068  m_Application->processEvents();
1069  }
1070  }
1071 
1072  if (m_ImageX) {
1073  QcepMutexLocker lock(__FILE__, __LINE__, &m_LockX);
1074 
1075  if (m_WeightX) {
1076  for (int y=0; y<(m_ImageX->get_Height()); y++) {
1077  for (int x=0; x<(m_ImageX->get_Width()); x++) {
1078  double val = m_ImageX->value(x,y);
1079  double wgt = m_WeightX->value(x,y);
1080 
1081  if (wgt > 0) {
1082  m_ImageX->setValue(x,y, val/wgt);
1083  } else {
1084  m_ImageX->setValue(x,y, val);
1085  }
1086  }
1087  }
1088  }
1089 
1090  fmt.saveFile(path+".x.tif", m_ImageX, false);
1091  delete m_ImageX;
1092  delete m_WeightX;
1093  m_ImageX = NULL;
1094  m_WeightX = NULL;
1095  }
1096 
1097  if (m_ImageY) {
1098  QcepMutexLocker lock(__FILE__, __LINE__, &m_LockY);
1099 
1100  if (m_WeightY) {
1101  for (int y=0; y<(m_ImageY->get_Height()); y++) {
1102  for (int x=0; x<(m_ImageY->get_Width()); x++) {
1103  double val = m_ImageY->value(x,y);
1104  double wgt = m_WeightY->value(x,y);
1105 
1106  if (wgt > 0) {
1107  m_ImageY->setValue(x,y, val/wgt);
1108  } else {
1109  m_ImageY->setValue(x,y, val);
1110  }
1111  }
1112  }
1113  }
1114 
1115  fmt.saveFile(path+".y.tif", m_ImageY, false);
1116  delete m_ImageY;
1117  delete m_WeightY;
1118  m_ImageY = NULL;
1119  m_WeightY = NULL;
1120  }
1121 
1122  if (m_ImageZ) {
1123  QcepMutexLocker lock(__FILE__, __LINE__, &m_LockZ);
1124 
1125  if (m_WeightZ) {
1126  for (int y=0; y<(m_ImageZ->get_Height()); y++) {
1127  for (int x=0; x<(m_ImageZ->get_Width()); x++) {
1128  double val = m_ImageZ->value(x,y);
1129  double wgt = m_WeightZ->value(x,y);
1130 
1131  if (wgt > 0) {
1132  m_ImageZ->setValue(x,y, val/wgt);
1133  } else {
1134  m_ImageZ->setValue(x,y, val);
1135  }
1136  }
1137  }
1138  }
1139 
1140  fmt.saveFile(path+".z.tif", m_ImageZ, false);
1141  delete m_ImageZ;
1142  delete m_WeightZ;
1143  m_ImageZ = NULL;
1144  m_WeightZ = NULL;
1145  }
1146 
1147  set_WallTime(startAt.elapsed()/1000.0);
1148 
1149  printMessage(tr("Projection complete after %1 sec, Min %2, Max %3, MinW %4, MaxW %5")
1150  .arg(get_WallTime()).arg(m_MinData).arg(m_MaxData).arg(m_MinWeight).arg(m_MaxWeight));
1151  }
1152 }
1153 
1154 #endif
int dependencyCount() const
CctwIntVector3D chunkIndexFromNumber(int n)
CctwIntVector3D chunkStart(int n)
void releaseChunkData(int n)
void saveDependencies(QString path)
CctwIntVector3D chunkSize()
CctwDataChunk * chunk(int n)
QcepImageData< double > * m_WeightZ
CctwTransformer(CctwApplication *application, CctwChunkedData *input, CctwChunkedData *output, CctwTransformInterface *xform, QString name, QObject *parent)
virtual void writeSettings(QSettings *set, QString section)
bool containsChunk(int ix, int iy, int iz)
CctwIntVector3D m_SubsetStart
QString toString()
void runTransformChunkNumber(int n)
void addDependency(int f, int t)
CctwIntVector3D dimensions
virtual void readSettings(QSettings *set, QString section)
QcepImageData< double > * m_ImageY
bool parseSubset(CctwChunkedData *data=NULL)
QcepIntList dependencies(int n)
QcepImageData< double > * m_WeightX
bool openInputFile(bool quietly=false)
CctwIntVector3D chunkCount
virtual void printMessage(QString msg, QDateTime dt=QDateTime::currentDateTime())
Definition: cctwobject.cpp:25
void mergeChunk(CctwDataChunk *chunk)
CctwIntVector3D m_SubsetEnd
CctwChunkedData::MergeDataType weight(int lx, int ly, int lz)
void transformChunkData(int chunkId, CctwDataChunk *inputChunk, QMap< int, CctwDataChunk * > &outputChunks)
T x() const
Definition: cctwvector3d.h:17
static int allocatedChunkCount()
int dependency(int n) const
void addWorkOutstanding(int amt)
int chunkContaining(CctwIntVector3D pixelCoord)
void transformChunkNumber(int chunkId)
CctwChunkedData::MergeDataType * weightsPointer()
void addDependency(int f, int t)
void sortDependencies()
CctwApplication * m_Application
virtual void readSettings(QSettings *set, QString section)
Definition: cctwobject.cpp:52
bool containsPixel(CctwIntVector3D pixelCoord)
CctwIntVector3D chunkStart()
T z() const
Definition: cctwvector3d.h:19
void workCompleted(int amt)
CctwVector3D< int > CctwIntVector3D
Definition: cctwvector3d.h:70
QcepImageData< double > * m_WeightY
CctwIntVector3D chunkSize
QcepImageData< double > * m_ImageZ
void loadDependencies(QString path)
CctwChunkedData::MergeDataType * dataPointer()
static void resetAllocationLimits(int nmax)
virtual ~CctwTransformer()
virtual void writeSettings(QSettings *set, QString section)
Definition: cctwobject.cpp:39
CctwChunkedData * m_OutputData
T volume() const
QcepImageData< double > * m_ImageX
void clearDependencies(int use)
CctwChunkedData * m_InputData
CctwChunkedData::MergeDataType data(int lx, int ly, int lz)
int chunkNumberFromIndex(CctwIntVector3D chunkIdx)
T y() const
Definition: cctwvector3d.h:18
CctwVector3D< double > CctwDoubleVector3D
Definition: cctwvector3d.h:71
CctwDataChunk * readChunk(int n)
CctwCrystalCoordinateParameters * parameters() const