7 #include <QtConcurrentRun>
10 #include "qcepmutexlocker.h"
13 #if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
17 #ifdef WANT_ANALYSIS_COMMANDS
18 #include "qcepimagedataformattiff.h"
19 #include "qcepimagedata.h"
26 QString name, QObject *parent) :
28 m_Application(application),
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")
93 if (f.open(QFile::WriteOnly | QFile::Truncate)) {
98 for (
int i=0; i<nchunk; i++) {
105 for (
int j=0; j<n; j++) {
108 s << i <<
"\t" << o << endl;
120 if (f.open(QFile::ReadOnly)) {
136 QString
subset = get_Subset();
138 if (subset.length() == 0) {
149 QRegExp r(
"(\\d+)/(\\d+)");
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;
158 printMessage(tr(
"Subset matched : index = %1 of %2").arg(index).arg(nsubs));
161 int szx = chunks.
x(), szy = chunks.
y(), szz = chunks.
z();
165 .arg(szx).arg(szy).arg(szz).arg(szx*szy*szz));
168 for (
int dx=1; dx<=szx; dx++) {
169 int nx = (szx + dx - 1)/dx;
177 for (
int dy=1; dy <= szy; dy++) {
178 int ny = (szy + dy - 1)/dy;
185 for (
int dz=1; dz <= szz; dz++) {
186 int nz = (szz + dz - 1)/dz;
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));
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);
212 if (newmax < bestmax) {
213 bestdx = dx; bestnx = nx;
214 bestdy = dy; bestny = ny;
215 bestdz = dz; bestnz = nz;
228 printMessage(tr(
"Best subdivision found: %1,%2,%3 - total %4")
229 .arg(bestdx).arg(bestdy).arg(bestdz).arg(bestnx*bestny*bestnz));
232 if ((index >= nbest) || (index < 0)) {
234 printMessage(tr(
"Skipping subset %1 of %2").arg(index).arg(nbest));
241 zstride = bestnx*bestny;
255 int x0 = x*bestdx, x1 = x0+bestdx;
256 int y0 = y*bestdy, y1 = y0+bestdy;
257 int z0 = z*bestdz, z1 = z0+bestdz;
259 if (x1 > chunks.
x()) x1 = chunks.
x();
260 if (y1 > chunks.
y()) y1 = chunks.
y();
261 if (z1 > chunks.
z()) z1 = chunks.
z();
264 printMessage(tr(
"Subset %1 : [%2..%3) [%4..%5) [%6..%7)")
266 .arg(x0).arg(x1).arg(y0).arg(y1).arg(z0).arg(z1));
287 QMap<int, CctwDataChunk*> outputChunks;
301 printMessage(tr(
"Discrepancy between numbers of merged chunks : dependencyCount() = %1, chunks.count() = %2")
313 printMessage(tr(
"Could not read chunk: %1").arg(chunkId));
320 QMap<int, CctwDataChunk*> &outputChunks)
326 printMessage(tr(
"Transforming chunk data: %1").arg(chunkId));
329 QcepDoubleVector anglesvec =
m_InputData->get_Angles();
330 QcepDoubleVector weightsvec=
m_InputData->get_Weights();
334 int nMask = maskvec.count();
335 int nAngs = anglesvec.count();
336 int nWgts = weightsvec.count();
338 const int *mask = maskvec.constData();
339 const double *angs = anglesvec.constData();
340 const double *wgts = weightsvec.constData();
342 if (nMask <= 0) mask = NULL;
343 if (nAngs <= 0) angs = NULL;
344 if (nWgts <= 0) wgts = NULL;
347 tr(
"transform-%1").arg(chunkId),
357 int lastChunkIndex = -1;
359 int osx = get_OversampleX();
360 int osy = get_OversampleY();
361 int osz = get_OversampleZ();
363 int nused = 0, nskipped = 0;
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;
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());
373 if ((angs==NULL || angle==angle) &&
374 (wgts==NULL || weight > 0)) {
376 if (wgts==NULL) weight = 1;
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++) {
385 if (mask == NULL || mask[(globalpix.
y())*dims.
x() + globalpix.
x()] == 0) {
388 for (
int ox=0; ox<osx; ox++) {
390 CctwDoubleVector3D xfmcoord =
transform.forward(coords);
397 if (opchunk != lastChunkIndex) {
399 lastChunkIndex = opchunk;
401 if (!outputChunks.contains(lastChunkIndex)) {
408 tr(
"chunk-%1").arg(lastChunkIndex), NULL);
415 outputChunks[lastChunkIndex] = chunk;
418 lastChunk = outputChunks[lastChunkIndex];
422 int ox = oprelat.
x(), oy = oprelat.
y(), oz = oprelat.
z();
423 int ix = iprelat.
x(), iy = iprelat.
y(), iz = iprelat.
z();
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;
431 lastChunk->setData(ox, oy, oz, oval+ival);
432 lastChunk->setWeight(ox, oy, oz, owgt+iwgt);
448 printMessage(tr(
"Transform chunk data: %1: done. Time %2 s, %3 output chunks, %4 allocated, used %5, skipped %6")
450 .arg(time.elapsed()/1000.0,5)
451 .arg(outputChunks.count())
458 m_Skipped.incValue(nskipped);
463 QVector < QFuture < void > > futures;
482 if (
m_InputData -> beginTransform(
true, get_TransformOptions())) {
483 if (
m_OutputData -> beginTransform(
false, get_TransformOptions())) {
492 QVector < int > inputChunks;
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++) {
502 for (
int i=0; i<n; i++) {
505 if (!inputChunks.contains(ckidx)) {
506 inputChunks.append(ckidx);
515 printMessage(tr(
"%1 chunks of input data needed").arg(inputChunks.count()));
518 if ((get_TransformOptions() & 2)) {
520 printMessage(
"Sorting input chunk list into input order");
523 qSort(inputChunks.begin(), inputChunks.end());
530 foreach(
int ckidx, inputChunks) {
535 if ((get_TransformOptions() & 1) == 0) {
543 foreach (QFuture<void> f, futures) {
550 set_WallTime(startAt.elapsed()/1000.0);
565 printMessage(tr(
"Transform complete after %1 sec, %2 chunks still allocated")
569 printMessage(tr(
"%1 pixels skipped by mask").arg(get_Skipped()));
575 QVector < QFuture < void > > futures;
610 printMessage(tr(
"Input Dimensions %1, Output Dimensions %2")
613 printMessage(tr(
"Input Chunk Size %1, Output Chunk Size %2")
616 printMessage(tr(
"Input Chunk Count %1, Output Chunk Count %2")
619 printMessage(tr(
"Input HDF Chunk Size %1, Output HDF Chunk Size %2")
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++) {
646 foreach (QFuture<void> f, futures) {
653 msec = startAt.elapsed();
670 printMessage(tr(
"Transform complete after %1 msec, %2 chunks still allocated")
674 printMessage(tr(
"%1 pixels skipped by mask").arg(get_Skipped()));
682 for (
int i = 0; i<chunks; i++) {
687 printMessage(tr(
"Anomaly in chunk [%1] : deps %2, merge %3")
694 printMessage(tr(
"Chunk [%1] still has allocated data").arg(i));
698 printMessage(tr(
"Chunk [%1] still has allocated weights").arg(i));
706 QcepDoubleVector anglesvec =
m_InputData->get_Angles();
707 double *angs = (anglesvec.count()<=0 ? NULL : anglesvec.data());
713 int lastChunkIndex = -1;
717 QList<int> outputChunks;
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++) {
730 CctwDoubleVector3D xfmcoord =
transform.forward(coords);
736 if (opchunk != lastChunkIndex) {
737 lastChunkIndex = opchunk;
739 if (!outputChunks.contains(lastChunkIndex)) {
740 outputChunks.append(opchunk);
750 foreach(
int chk, outputChunks) {
763 QList<CctwIntVector3D> res;
765 foreach(
int dep, deps) {
777 set_UseDependencies(use);
786 #ifdef WANT_ANALYSIS_COMMANDS
788 void CctwTransformer::inputProject(QString path,
int axes)
793 void CctwTransformer::outputProject(QString path,
int axes)
798 void CctwTransformer::projectDatasetChunk(
CctwChunkedData *data,
int i,
int axes)
807 int cx = chStart.
x(),
829 double mindata = chunk->
data(0,0,0);
830 double maxdata = mindata;
831 double minwgt = chunk->
weight(0,0,0);
832 double maxwgt = minwgt;
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);
840 if (data < mindata) mindata = data;
841 if (data > maxdata) maxdata = data;
842 if (wgt < minwgt) minwgt = wgt;
843 if (wgt > maxwgt) maxwgt = wgt;
847 imgx->addValue(y,z,data);
848 wgtx->addValue(y,z,wgt);
852 imgy->addValue(x,z,data);
853 wgty->addValue(x,z,wgt);
857 imgz->addValue(x,y,data);
858 wgtz->addValue(x,y,wgt);
860 }
else if (data != 0){
861 printMessage(tr(
"Wgt: %1, Data %2").arg(wgt).arg(data));
868 QcepMutexLocker lock(__FILE__, __LINE__, &
m_LockX);
877 QcepMutexLocker lock(__FILE__, __LINE__, &
m_LockX);
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));
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));
900 QcepMutexLocker lock(__FILE__, __LINE__, &
m_LockY);
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));
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));
923 QcepMutexLocker lock(__FILE__, __LINE__, &
m_LockZ);
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));
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));
945 data->releaseChunkData(i);
955 void CctwTransformer::projectDataset(QString path,
CctwChunkedData *data,
int axes)
958 QVector < QFuture < void > > futures;
972 QcepImageDataFormatTiff<double> fmt(
"TIFF");
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++) {
1058 QtConcurrent::run(
this, &CctwTransformer::projectDatasetChunk, data, n, axes));
1065 foreach (QFuture<void> f, futures) {
1066 f.waitForFinished();
1073 QcepMutexLocker lock(__FILE__, __LINE__, &
m_LockX);
1076 for (
int y=0; y<(
m_ImageX->get_Height()); y++) {
1077 for (
int x=0; x<(
m_ImageX->get_Width()); x++) {
1079 double wgt = m_WeightX->value(x,y);
1090 fmt.saveFile(path+
".x.tif",
m_ImageX,
false);
1098 QcepMutexLocker lock(__FILE__, __LINE__, &
m_LockY);
1101 for (
int y=0; y<(
m_ImageY->get_Height()); y++) {
1102 for (
int x=0; x<(
m_ImageY->get_Width()); x++) {
1104 double wgt = m_WeightY->value(x,y);
1115 fmt.saveFile(path+
".y.tif",
m_ImageY,
false);
1123 QcepMutexLocker lock(__FILE__, __LINE__, &
m_LockZ);
1126 for (
int y=0; y<(
m_ImageZ->get_Height()); y++) {
1127 for (
int x=0; x<(
m_ImageZ->get_Width()); x++) {
1129 double wgt = m_WeightZ->value(x,y);
1140 fmt.saveFile(path+
".z.tif",
m_ImageZ,
false);
1147 set_WallTime(startAt.elapsed()/1000.0);
1149 printMessage(tr(
"Projection complete after %1 sec, Min %2, Max %3, MinW %4, MaxW %5")
int dependencyCount() const
CctwIntVector3D chunkIndexFromNumber(int n)
CctwIntVector3D chunkStart(int n)
void releaseChunkData(int n)
CctwIntVector3D chunkSize()
CctwDataChunk * chunk(int n)
bool containsChunk(int ix, int iy, int iz)
void addDependency(int f, int t)
CctwIntVector3D dimensions
bool openInputFile(bool quietly=false)
CctwIntVector3D chunkCount
virtual void printMessage(QString msg, QDateTime dt=QDateTime::currentDateTime())
void mergeChunk(CctwDataChunk *chunk)
CctwChunkedData::MergeDataType weight(int lx, int ly, int lz)
static int allocatedChunkCount()
int dependency(int n) const
void addWorkOutstanding(int amt)
int chunkContaining(CctwIntVector3D pixelCoord)
CctwChunkedData::MergeDataType * weightsPointer()
virtual void readSettings(QSettings *set, QString section)
bool containsPixel(CctwIntVector3D pixelCoord)
CctwIntVector3D chunkStart()
void workCompleted(int amt)
CctwVector3D< int > CctwIntVector3D
CctwIntVector3D chunkSize
CctwChunkedData::MergeDataType * dataPointer()
static void resetAllocationLimits(int nmax)
virtual void writeSettings(QSettings *set, QString section)
CctwChunkedData::MergeDataType data(int lx, int ly, int lz)
int chunkNumberFromIndex(CctwIntVector3D chunkIdx)
CctwVector3D< double > CctwDoubleVector3D
CctwDataChunk * readChunk(int n)
CctwCrystalCoordinateParameters * parameters() const