Xmipp  v3.23.11-Nereus
mpi_classify_FTTRI.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar Sanchez Sorzano coss@cnb.csic.es (2012)
4  * Wang Xia wangxia@lsec.cc.ac.cn
5  * Guoliang Xu xuguo@lsec.cc.ac.cn
6  *
7  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22  * 02111-1307 USA
23  *
24  * All comments concerning this program package may be sent to the
25  * e-mail address 'xmipp@cnb.csic.es'
26  ***************************************************************************/
27 
28 #include <algorithm>
29 #include "mpi_classify_FTTRI.h"
31 #include "core/transformations.h"
32 #include "core/xmipp_fftw.h"
34 #include "data/filters.h"
35 
36 // Empty constructor =======================================================
38 {
39  node = std::make_unique<MpiNode>(argc, argv);
40  if (!node->isMaster())
41  verbose=0;
42  taskDistributor=nullptr;
43 }
44 
45 // Read arguments ==========================================================
47 {
48  fnIn = getParam("-i");
49  fnRoot = getParam("--oroot");
50  pad = getDoubleParam("--padding");
51  fmax = getDoubleParam("--maxfreq");
52  zoom = getDoubleParam("--zoom");
53  sigma1 = getDoubleParam("--sigma1");
54  sigma2 = getDoubleParam("--sigma2");
55  nref = getIntParam("--nref");
56  nMinImages = getIntParam("--nmin");
57  Niter = getIntParam("--iter");
58  doPhase = checkParam("--doPhase");
59 }
60 
61 // Show ====================================================================
63 {
64  if (!verbose)
65  return;
66  std::cout
67  << "Input file: " << fnIn << std::endl
68  << "Output root: " << fnRoot << std::endl
69  << "Padding: " << pad << std::endl
70  << "MaxFreq: " << fmax << std::endl
71  << "Zoom: " << zoom << std::endl
72  << "Sigma1: " << sigma1 << std::endl
73  << "Sigma2: " << sigma2 << std::endl
74  << "N.Classes: " << nref << std::endl
75  << "N.Minimum: " << nMinImages << std::endl
76  << "Iterations: " << Niter << std::endl
77  << "Do phase: " << doPhase << std::endl
78  ;
79 }
80 
81 // usage ===================================================================
83 {
84  addUsageLine("Classify in 2D using Fourier Transform based Translational and Rotational Invariants");
85  addParamsLine(" -i <infile> : Metadata or stack with input images");
86  addParamsLine(" --oroot <rootname> : Rootname for output files");
87  addParamsLine(" --nref <n> : Desired number of classes");
88  addParamsLine(" [--padding <p=4>] : Padding factor (it can be a non-integer factor");
89  addParamsLine(" [--maxfreq <f=0.25>] : Maximum frequency for the spectrum classification");
90  addParamsLine(" : Supply -1 for automatic estimation");
91  addParamsLine(" [--zoom <f=1>] : Perform polar transformation with this zoom factor (>=1) at low frequencies");
92  addParamsLine(" : Log-polar corresponds to an approximate factor of 2.8");
93  addParamsLine(" [--nmin <n=5>] : Minimum number of images in a class to be considered as such");
94  addParamsLine(" [--iter <n=10>] : Number of iterations for FRTTI classfication.");
95  addParamsLine(" : At each iteration, those classes whose size");
96  addParamsLine(" : is smaller than nmin are removed from the classification");
97  addParamsLine(" [--sigma1+ <s=0.707>] : First weight in the FTTRI, see paper for documentation");
98  addParamsLine(" [--sigma2+ <s=1.5>] : Second weight in the FTTRI, see paper for documentation");
99  addParamsLine(" [--doPhase] : Do also an amplitude and phase classification");
100  addExampleLine("mpirun -np 4 `which xmipp_mpi_classify_FTTRI` -i images.xmd --oroot class --nref 64");
101 }
102 
103 // Produce side info =====================================================
105 {
106  mdIn.read(fnIn);
107 
108  // Get input size
109  size_t zdim, ydim, xdim, ndim;
110  getImageSize(mdIn, xdim, ydim, zdim, ndim);
111  if (node->isMaster())
112  {
113  if (zdim!=1)
114  REPORT_ERROR(ERR_MULTIDIM_DIM,"This program is only intended for images, not volumes");
115  if (xdim!=ydim)
116  REPORT_ERROR(ERR_MULTIDIM_DIM,"This program is only intended for squared images");
117  }
118  padXdim=(int)(pad*xdim);
119  Rmax=(size_t)floor(fmax*padXdim);
120 
121  size_t blockSize=mdIn.size()/(5*node->size);
122  if (blockSize==0)
123  blockSize=1;
125  taskDistributor = new MpiTaskDistributor(mdIn.size(), blockSize, node);
126  fnFTTRI=fnRoot+"_FTTRI.mrcs";
127  FTTRIXdim=(int)((Rmax+1)*0.35);
128  FTTRIYdim=(int)((Rmax+1)*0.55);
129  if (node->isMaster())
130  {
131  // Create output mask
132  Image<int> mask;
133  mask().initZeros(xdim,xdim);
134  mask().setXmippOrigin();
135  double R2=0.25*xdim*xdim;
136  MultidimArray<int> &mMask=mask();
138  if (i*i+j*j<R2)
139  A2D_ELEM(mMask,i,j)=1;
140  mask.write(fnRoot+"_mask.mrc");
141 
142  // Create output FTTRI
143 #ifndef FTTRI_ALREADY_COMPUTED
144 
145  if (fileExists(fnFTTRI))
146  fnFTTRI.deleteFile();
148 #endif
149 
150  }
151  node->barrierWait();
152 }
153 
155 {
156  if (verbose && node->rank==0)
157  std::cerr << "Computing FTTRI ...\n";
158 
159  // Read mask
160  Image<int> mask;
161  mask.read(fnRoot+"_mask.mrc");
162  MultidimArray<int> &mMask=mask();
163  mMask.setXmippOrigin();
164 
165  // Compute weights
166  Matrix1D<double> R, weight1, weight2;
167 
168  // Process all images
169  size_t Nimgs=mdIn.size();
170  if (verbose && node->rank==0)
171  init_progress_bar(Nimgs);
172  size_t first, last;
173  FileName fnImg;
174  MultidimArray<double> padI(padXdim,padXdim), magFTI, filteredMagFTI, polarFilteredMagFTI, magFTpolarFilteredMagFTI;
175  padI.setXmippOrigin();
176  Image<double> I, avgMagFTI, centralMagFTpolarFilteredMagFTI;
177  avgMagFTI().initZeros(padI);
178  MultidimArray< std::complex<double> > FTI, FTpolarFilteredMagFTI;
179  FourierTransformer transformer1, transformer2;
180  while (taskDistributor->getTasks(first, last))
181  for (size_t idx=first; idx<=last; ++idx)
182  {
183  if (verbose && node->rank==0)
184  progress_bar(idx);
185  mdIn.getValue(MDL_IMAGE,fnImg,imgsId[idx]);
186  I.read(fnImg);
187  I().setXmippOrigin();
188  MultidimArray<double> &mI=I();
189 
190  // Mask input images
192  if (!DIRECT_MULTIDIM_ELEM(mMask,n))
193  DIRECT_MULTIDIM_ELEM(mI,n)=0.0;
194 
195  // Pad input images
198 
199  // Compute full Fourier transform and its magnitude
200  transformer1.completeFourierTransform(padI,FTI);
201  FFT_magnitude(FTI,magFTI);
202  CenterFFT(magFTI,true);
203  magFTI.window(filteredMagFTI,
208 
209  // Now express it in polar coordinates and apply weight
210  image_convertCartesianToPolar_ZoomAtCenter(filteredMagFTI, polarFilteredMagFTI, R, zoom, 3, Rmax/2, Rmax, 0, PI, Rmax);
211  if (VEC_XSIZE(weight1)==0)
212  {
213  weight1.resizeNoCopy(R);
214  weight2.resizeNoCopy(R);
216  {
217  VEC_ELEM(weight1,i)=pow(VEC_ELEM(R,i),sigma1);
218  VEC_ELEM(weight2,i)=pow((Rmax-VEC_ELEM(R,i)),sigma2);
219  }
220  }
221  FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(polarFilteredMagFTI)
222  A2D_ELEM(polarFilteredMagFTI,i,j)*=VEC_ELEM(weight1,j);
223 
224  // And take new Fourier transform
225  transformer2.completeFourierTransform(polarFilteredMagFTI,FTpolarFilteredMagFTI);
226  FFT_magnitude(FTpolarFilteredMagFTI,magFTpolarFilteredMagFTI);
227  CenterFFT(magFTpolarFilteredMagFTI,true);
228  FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(magFTpolarFilteredMagFTI)
229  A2D_ELEM(magFTpolarFilteredMagFTI,i,j)*=VEC_ELEM(weight2,j);
230  magFTpolarFilteredMagFTI.setXmippOrigin();
231  magFTpolarFilteredMagFTI.window(centralMagFTpolarFilteredMagFTI(),
234  centralMagFTpolarFilteredMagFTI().rangeAdjust(1,255);
235  centralMagFTpolarFilteredMagFTI().selfLog10();
236  centralMagFTpolarFilteredMagFTI.write(fnFTTRI,idx+1,true,WRITE_REPLACE);
237  }
239  if (verbose && node->rank==0)
240  progress_bar(Nimgs);
241 }
242 
244 {
245  if (node->isMaster())
246  {
247  dMin=1e3;
248  dMax=-1;
249  MultidimArray<int> perm;
250  int N=mdIn.size();
251  randomPermutation(N,perm);
252  N=XMIPP_MIN(N,50);
253  std::vector< MultidimArray<double> > fttri;
254  Image<double> aux;
255  FileName fn;
256  for(int i=0; i<N; i++)
257  {
258  fn.compose(A1D_ELEM(perm,i)+1,fnFTTRI);
259  aux.read(fn);
260  fttri.push_back(aux());
261  }
262 
263  int idx=0;
264  for(int i=0; i<N-1; i++)
265  {
266  const MultidimArray<double> &fttri_i=fttri[i];
267  for(int j=i+1; j<N; j++, idx++)
268  {
269  const MultidimArray<double> &fttri_j=fttri[j];
270  double d=fttri_distance(fttri_i,fttri_j);
271  dMin=std::min(d,dMin);
272  dMax=std::max(d,dMax);
273  }
274  }
275  if (verbose)
276  std::cout << "Initial epsilon range: [" << dMin << "," << dMax << "]\n";
277  }
278 }
279 
281  const MultidimArray<double> &fttri_j)
282 {
283  double retval=0;
284  const size_t unroll=4;
285  size_t nmax=unroll*(MULTIDIM_SIZE(fttri_i)/unroll);
286  double* ptrI=nullptr;
287  double* ptrJ=nullptr;
288  size_t n;
289  for (n=0, ptrI=MULTIDIM_ARRAY(fttri_i),ptrJ=MULTIDIM_ARRAY(fttri_j);
290  n<nmax; n+=unroll, ptrI+=unroll, ptrJ+=unroll)
291  {
292  double diff0=*ptrI-*ptrJ;
293  retval+=diff0*diff0;
294  double diff1=*(ptrI+1)-*(ptrJ+1);
295  retval+=diff1*diff1;
296  double diff2=*(ptrI+1)-*(ptrJ+1);
297  retval+=diff2*diff2;
298  double diff3=*(ptrI+1)-*(ptrJ+1);
299  retval+=diff3*diff3;
300  }
301  for (n=nmax, ptrI=MULTIDIM_ARRAY(fttri_i)+nmax, ptrJ=MULTIDIM_ARRAY(fttri_j)+nmax;
302  n<MULTIDIM_SIZE(fttri_i); ++n, ++ptrI, ++ptrJ)
303  {
304  double diff0=*ptrI-*ptrJ;
305  retval+=diff0*diff0;
306  }
307  return retval/(MULTIDIM_SIZE(fttri_i));
308 }
309 
310 // Epsilon classifcation ==================================================
312  size_t &currentPointer, size_t remaining)
313 {
314  // Now the master selects the first class at random
315  if (node->isMaster())
316  {
317  // Move current pointer to next not assigned image
318  while (VEC_ELEM(notAssigned,currentPointer)==0)
319  currentPointer=(currentPointer+1)%VEC_XSIZE(notAssigned);
320 
321  // Now skip some non empty
322  auto skip=(size_t) (remaining*rnd_unif());
323  while (skip>0)
324  {
325  currentPointer=(currentPointer+1)%VEC_XSIZE(notAssigned);
326  // Adjust to next not assigned image
327  while (VEC_ELEM(notAssigned,currentPointer)==0)
328  currentPointer=(currentPointer+1)%VEC_XSIZE(notAssigned);
329  --skip;
330  }
331  }
332  MPI_Bcast(&currentPointer, 1, MPI_LONG, 0, MPI_COMM_WORLD);
333 }
334 
335 void receiveListFromRank(std::vector<size_t> &listToKeepIt, int rank)
336 {
337  MPI_Status status;
338  Matrix1D<size_t> aux;
339  size_t length;
340  MPI_Recv(&length, 1, MPI_LONG, rank, 0, MPI_COMM_WORLD, &status);
341  aux.resize(length);
342  MPI_Recv(&(VEC_ELEM(aux,0)), length, MPI_LONG, rank, 0, MPI_COMM_WORLD, &status);
344  listToKeepIt.push_back(VEC_ELEM(aux,i));
345 }
346 
347 void sendListToRank(std::vector<size_t> &listToSend, int rank)
348 {
349  Matrix1D<size_t> aux;
350  aux.resizeNoCopy(listToSend.size());
352  VEC_ELEM(aux,i)=listToSend[i];
353  MPI_Send(&(VEC_XSIZE(aux)), 1, MPI_LONG, rank, 0, MPI_COMM_WORLD);
354  MPI_Send(&(VEC_ELEM(aux,0)), VEC_XSIZE(aux), MPI_LONG, rank, 0, MPI_COMM_WORLD);
355 }
356 
358 {
359  epsilonClasses.clear();
361  auto remaining=(size_t)notAssigned.sum();
362  size_t currentPointer=0;
363  EpsilonClass newClass;
364  FileName fnSeed, fnCandidate;
365  Image<double> fttriSeed, fftriCandidate;
366  std::vector<size_t> inNewClass;
367 
368  while (remaining>0)
369  {
370  // Select new class at random
371  skipRandomNumberOfUnassignedClasses(currentPointer,remaining);
372  fnSeed.compose(currentPointer+1,fnFTTRI);
373  fttriSeed.read(fnSeed);
374  MultidimArray<double> &mfftriSeed=fttriSeed();
375  if (node->isMaster())
376  inNewClass.push_back(currentPointer);
377  VEC_ELEM(notAssigned,currentPointer)=0;
378 
379  // Check if any of the unassigned images belongs to this class
381  if (VEC_ELEM(notAssigned,i)==1 && (i+1)%node->size==node->rank)
382  {
383  fnCandidate.compose(i+1,fnFTTRI);
384  fftriCandidate.read(fnCandidate);
385  double distance=fttri_distance(mfftriSeed,fftriCandidate());
386  if (distance<=epsilon)
387  inNewClass.push_back(i);
388  }
389 
390  // Synchronize lists
391  if (node->isMaster())
392  {
393  // Receive all new elements
394  for (size_t rank=1; rank<node->size; rank++)
395  receiveListFromRank(inNewClass,rank);
396  // And redistribute the new list
397  for (size_t rank=1; rank<node->size; rank++)
398  sendListToRank(inNewClass,rank);
399  }
400  else
401  {
402  // Send my own new elements
403  sendListToRank(inNewClass,0);
404  // Receive the whole list of new elements
405  receiveListFromRank(inNewClass,0);
406  }
407 
408  // Update internal structures
409  size_t imax=inNewClass.size();
410  for (size_t i=0; i<imax; ++i)
411  VEC_ELEM(notAssigned,inNewClass[i])=0;
412  remaining=(size_t)notAssigned.sum();
413  if (node->isMaster())
414  {
415  newClass.memberIdx=inNewClass;
416  epsilonClasses.push_back(newClass);
417  }
418  inNewClass.clear();
419  }
420 }
421 
423 {
424  MPI_Bcast(&epsilon, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); // Workers are waiting at searchOptimalEpsilon
425  epsilonClassification(epsilon);
426  size_t retval=epsilonClasses.size();
427  double objective=fabs(retval-nref);
428  if (objective<bestObjective)
429  {
430  bestObjective=objective;
433  }
434  std::cout << "Trying " << epsilon << " -> " << retval << std::endl;
435  return retval;
436 }
437 
439 {
440  if (node->isMaster())
441  {
442  std::cerr << "Computing epsilon classification ..." << std::endl;
443  bestEpsilon=-1;
444  bestObjective=1e38;
445  double epsilonLeft=dMin;
446  double epsilonRight=dMax;
447  size_t Nleft=wrapperFitness(epsilonLeft);
448  size_t Nright=wrapperFitness(epsilonRight);
449  if (Nleft!=nref && Nright!=nref)
450  {
451  size_t Ndivisions=0;
452  do
453  {
454  // Adjust margins
455  if (nref>Nleft)
456  {
457  epsilonRight=epsilonLeft;
458  Nright=Nleft;
459  epsilonLeft*=0.9;
460  Nleft=wrapperFitness(epsilonLeft);
461  if (Nleft==0)
462  break;
463  }
464  else if (nref<Nright)
465  {
466  epsilonLeft=epsilonRight;
467  Nleft=Nright;
468  epsilonRight*=1.1;
469  Nright=wrapperFitness(epsilonRight);
470  if (Nright==0)
471  break;
472  }
473  else
474  {
475  // Interval is correct, look in the middle
476  double epsilonCentral=0.5*(epsilonLeft+epsilonRight);
477  size_t Ncentral=wrapperFitness(epsilonCentral);
478  Ndivisions++;
479  if (Ncentral==nref || Ndivisions==10)
480  break;
481  if (Ncentral>nref)
482  {
483  Nleft=Ncentral;
484  epsilonLeft=epsilonCentral;
485  }
486  else
487  {
488  Nright=Ncentral;
489  epsilonRight=epsilonCentral;
490  }
491  }
492  }
493  while (1);
494  }
495  double finalize=-1e6;
496  MPI_Bcast(&finalize, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
497  }
498  else
499  {
500  // Wait for orders from the master
501  while (1)
502  {
503  double epsilon;
504  MPI_Bcast(&epsilon, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
505  if (epsilon>-5e5)
506  epsilonClassification(epsilon);
507  else
508  break;
509  }
510  }
511 }
512 
513 // Remove small classes
515 {
516  bool operator()(EpsilonClass const& rpStart, EpsilonClass const& rpEnd)
517  {
518  return rpStart.memberIdx.size() > rpEnd.memberIdx.size();
519  }
520 };
521 
523 {
524  if (node->isMaster())
525  {
527 
528  std::vector< EpsilonClass > goodEpsilonClasses;
529  size_t imax=bestEpsilonClasses.size();
530  size_t imagesRemoved=0;
531  size_t classesRemoved=0;
532  imax=XMIPP_MIN(imax,nref);
533  for (size_t i=0; i<imax; i++)
534  {
535  const std::vector<size_t> class_i=bestEpsilonClasses[i].memberIdx;
536  size_t nmax=class_i.size();
537  if (nmax>=nMinImages)
538  goodEpsilonClasses.push_back(bestEpsilonClasses[i]);
539  else
540  {
541  imagesRemoved+=nmax;
542  classesRemoved++;
543  for (size_t n=0; n<nmax; ++n)
544  VEC_ELEM(notAssigned0,class_i[n])=0;
545  }
546  }
547  if (imagesRemoved>0)
548  std::cout << "Removal of " << imagesRemoved << " images from "
549  << classesRemoved << " classes for being in too small classes\n";
550  bestEpsilonClasses=goodEpsilonClasses;
551  }
552  MPI_Bcast(MATRIX1D_ARRAY(notAssigned0), VEC_XSIZE(notAssigned0), MPI_CHAR, 0, MPI_COMM_WORLD);
553 }
554 
555 // Split classes ==========================================================
557  const EpsilonClass &class_i, bool FTTRI)
558 {
559  Image<double> candidate;
560  FileName fnCandidate;
561  int nmax=class_i.memberIdx.size();
562  double maxDistance;
563  if (FTTRI)
564  maxDistance=-1;
565  else
566  maxDistance=1;
567  int nMaxDistance=-1;
568  const std::vector<size_t> &class_i_members=class_i.memberIdx;
569  double d;
571  AlignmentAux aux;
572  CorrelationAux aux2;
574  for (int n=0; n<nmax; n++)
575  {
576  if (FTTRI)
577  fnCandidate.compose(class_i_members[n]+1,fnFTTRI);
578  else
579  mdIn.getValue(MDL_IMAGE,fnCandidate,imgsId[class_i_members[n]]);
580  candidate.read(fnCandidate);
581  candidate().setXmippOrigin();
582  if (FTTRI)
583  d=fttri_distance(seed,candidate());
584  else
585  d=alignImages(seed,candidate(),M,xmipp_transformation::WRAP,aux,aux2,aux3);
586  if ((d>maxDistance && FTTRI) || (d<maxDistance && !FTTRI))
587  {
588  maxDistance=d;
589  nMaxDistance=n;
590  }
591  }
592  return nMaxDistance;
593 }
594 
596 {
597  if (node->isMaster())
598  {
599  std::cerr << "Splitting large classes ..." << std::endl;
600  Image<double> seed1, seed2, candidate;
601  MultidimArray<double> candidateCopy;
602  FileName fnSeed, fnCandidate;
603  EpsilonClass c1, c2;
606  AlignmentAux aux;
607  CorrelationAux aux2;
609  while (bestEpsilonClasses.size()!=nref)
610  {
611  EpsilonClass &class_0=bestEpsilonClasses[0];
612  std::vector<size_t> &class_0_members=class_0.memberIdx;
613  if (class_0_members.size()<nMinImages)
614  break;
615 
616  // Find the image that is farthest from the center
617  if (FTTRI)
618  fnSeed.compose(class_0_members[0]+1,fnFTTRI);
619  else
620  mdIn.getValue(MDL_IMAGE,fnSeed,imgsId[class_0_members[0]]);
621  seed1.read(fnSeed);
622  seed1().setXmippOrigin();
623  int n1=findFarthest(seed1(),class_0,FTTRI);
624  if (FTTRI)
625  fnSeed.compose(class_0_members[n1]+1,fnFTTRI);
626  else
627  mdIn.getValue(MDL_IMAGE,fnSeed,imgsId[class_0_members[n1]]);
628  seed1.read(fnSeed);
629  seed1().setXmippOrigin();
630 
631  // Now find the one that is farthest from i1
632  int n2=findFarthest(seed1(),class_0,FTTRI);
633  if (FTTRI)
634  fnSeed.compose(class_0_members[n2]+1,fnFTTRI);
635  else
636  mdIn.getValue(MDL_IMAGE,fnSeed,imgsId[class_0_members[n2]]);
637  seed2.read(fnSeed);
638  seed2().setXmippOrigin();
639 
640  // Now split
641  c1.memberIdx.clear();
642  c2.memberIdx.clear();
643  c1.memberIdx.push_back(class_0_members[n1]);
644  c2.memberIdx.push_back(class_0_members[n2]);
645  int nmax=class_0_members.size();
646  const MultidimArray<double> &mSeed1=seed1();
647  const MultidimArray<double> &mSeed2=seed2();
648  for (int n=0; n<nmax; ++n)
649  {
650  if (n==n1 || n==n2)
651  continue;
652  size_t trueIdx=class_0_members[n];
653  if (FTTRI)
654  fnCandidate.compose(trueIdx+1,fnFTTRI);
655  else
656  mdIn.getValue(MDL_IMAGE,fnCandidate,imgsId[trueIdx]);
657  candidate.read(fnCandidate);
658  if (FTTRI)
659  {
660  const MultidimArray<double> &mCandidate=candidate();
661  double d1=fttri_distance(mSeed1,mCandidate);
662  double d2=fttri_distance(mSeed2,mCandidate);
663  if (d1<d2)
664  c1.memberIdx.push_back(trueIdx);
665  else
666  c2.memberIdx.push_back(trueIdx);
667  }
668  else
669  {
670  candidate().setXmippOrigin();
671  candidateCopy=candidate();
672  double d1=alignImages(mSeed1,candidate(),M,xmipp_transformation::WRAP,aux,aux2,aux3);
673  double d2=alignImages(mSeed2,candidateCopy,M,xmipp_transformation::WRAP,aux,aux2,aux3);
674  if (d1>d2)
675  c1.memberIdx.push_back(trueIdx);
676  else
677  c2.memberIdx.push_back(trueIdx);
678  }
679  }
680  bestEpsilonClasses.erase(bestEpsilonClasses.begin());
681  if (c1.memberIdx.size()>nMinImages)
682  bestEpsilonClasses.push_back(c1);
683  if (c2.memberIdx.size()>nMinImages)
684  bestEpsilonClasses.push_back(c2);
686  }
687  // Broadcast the best classes
688  for (size_t i=0; i<nref; ++i)
689  {
690  int classSize=bestEpsilonClasses[i].memberIdx.size();
691  MPI_Bcast(&classSize, 1, MPI_INT, 0, MPI_COMM_WORLD);
692  MPI_Bcast(&(bestEpsilonClasses[i].memberIdx[0]), classSize, MPI_LONG, 0, MPI_COMM_WORLD);
693  }
694  }
695  else
696  {
697  // Receive the best classes
698  bestEpsilonClasses.clear();
699  size_t classSize;
700  size_t buffer[50000];
701  EpsilonClass C;
702  for (size_t i=0; i<nref; ++i)
703  {
704  MPI_Bcast(&classSize, 1, MPI_INT, 0, MPI_COMM_WORLD);
705  MPI_Bcast(buffer, classSize, MPI_LONG, 0, MPI_COMM_WORLD);
706  C.memberIdx.clear();
707  for (size_t n=0; n<classSize; ++n)
708  C.memberIdx.push_back(buffer[n]);
709  bestEpsilonClasses.push_back(C);
710  }
711  }
712 }
713 
714 // Compute centroids =======================================================
716 {
717  FileName fnCentroids, fnCandidate;
718  if (FTTRI)
719  fnCentroids=fnRoot+"_FTTRI_centroids.mrcs";
720  else
721  fnCentroids=fnRoot+"_image_centroids.mrcs";
722  if (node->isMaster())
723  {
724  std::cerr << "Computing class centroids ..." << std::endl;
725  if (FTTRI)
727  else
728  {
729  size_t Xdim, Ydim, Zdim, Ndim;
730  getImageSize(mdIn, Xdim, Ydim, Zdim, Ndim);
731  createEmptyFile(fnCentroids,Xdim,Ydim,1,nref,true,WRITE_OVERWRITE);
732  }
733  }
734  node->barrierWait();
735 
736  Image<double> centroid, candidate;
737  if (node->isMaster())
739  Image<int> mask;
740  if (FTTRI)
741  {
742  centroid().resizeNoCopy(FTTRIYdim,1+LAST_XMIPP_INDEX(FTTRIXdim));
745  }
746  else
747  {
748  mask.read(fnRoot+"_mask.mrc");
749  centroid().resizeNoCopy(mask());
750  }
751  MultidimArray<double> &mCentroid=centroid();
752  MultidimArray<int> &mMask=mask();
753  MultidimArray<double> intraclassDistance, sortedDistance;
754  MetaDataVec MDclass;
755  for (size_t i=0; i<nref; i++)
756  if (((i+1)%node->size)==node->rank)
757  {
758  const std::vector<size_t> &class_i=bestEpsilonClasses[i].memberIdx;
759  size_t nmax=class_i.size();
760  mCentroid.initZeros();
761 
762  if (nmax!=0)
763  {
764  if (!FTTRI)
765  MDclass.clear();
766  for (size_t n=0; n<nmax; n++)
767  {
768  size_t trueIdx=class_i[n];
769  if (FTTRI)
770  {
771  fnCandidate.compose(trueIdx+1,fnFTTRI);
772  candidate.read(fnCandidate);
773  mCentroid+=candidate();
774  }
775  else
776  {
777  mdIn.getValue(MDL_IMAGE,fnCandidate,imgsId[trueIdx]);
778  MDclass.setValue(MDL_IMAGE,fnCandidate,MDclass.addObject());
779  }
780  }
781  if (FTTRI)
782  {
783  mCentroid/=(double)nmax;
784 
785  // Compute now class epsilon
786  intraclassDistance.resizeNoCopy(nmax);
787  for (size_t n=0; n<nmax; n++)
788  {
789  size_t trueIdx=class_i[n];
790  fnCandidate.compose(trueIdx+1,fnFTTRI);
791  candidate.read(fnCandidate);
792  A1D_ELEM(intraclassDistance,n)=fttri_distance(mCentroid,candidate());
793  }
794  intraclassDistance.sort(sortedDistance);
795  int idxLimit=std::min((size_t)floor(nmax*0.8),nmax-1);
796  double limit=A1D_ELEM(sortedDistance,idxLimit);
797  VEC_ELEM(classEpsilon,i)=A1D_ELEM(intraclassDistance,nmax-1);
798 
799  // Robust estimate of the class centroid
800  mCentroid.initZeros();
801  double nactual=0;
802  for (size_t n=0; n<nmax; n++)
803  {
804  if (A1D_ELEM(intraclassDistance,n)>limit)
805  continue;
806  size_t trueIdx=class_i[n];
807  fnCandidate.compose(trueIdx+1,fnFTTRI);
808  candidate.read(fnCandidate);
809  mCentroid+=candidate();
810  nactual++;
811  }
812  mCentroid/=nactual;
813  }
814  else
815  {
816  alignSetOfImages(MDclass,mCentroid,5,false);
818  if (!DIRECT_MULTIDIM_ELEM(mMask,n))
819  DIRECT_MULTIDIM_ELEM(mCentroid,n)=0.0;
820  }
821  }
822 
823  // Write new centroid
824  centroid.write(fnCentroids,i+1,true,WRITE_REPLACE);
825  if (node->isMaster())
826  progress_bar(i);
827  }
828  if (node->isMaster())
829  progress_bar(nref);
830  if (FTTRI)
831  {
832  MPI_Allreduce(MPI_IN_PLACE, &(VEC_ELEM(classEpsilon,0)), nref, MPI_DOUBLE,
833  MPI_MAX, MPI_COMM_WORLD);
835  if (node->isMaster())
836  std::cerr << "Maximum epsilon: " << epsilonMax << std::endl;
837  }
838 }
839 
840 // Compute class neighbours ================================================
842 {
843  if (node->isMaster())
844  std::cerr << "Computing class neighbours ..." << std::endl;
845  MultidimArray<double> *ptrCentroids=nullptr;
846  if (FTTRI)
847  {
848  fttriCentroids.read(fnRoot+"_FTTRI_centroids.mrcs");
849  ptrCentroids=&fttriCentroids();
850  }
851  else
852  {
853  imageCentroids.read(fnRoot+"_image_centroids.mrcs");
854  ptrCentroids=&imageCentroids();
855  }
856  const MultidimArray<double> &mCentroids=*ptrCentroids;
857  for (size_t i1=0; i1<nref; ++i1)
858  bestEpsilonClasses[i1].neighbours.clear();
859 
860  MultidimArray<double> centroid_i1, centroid_i2, centroid_i2p;
861  if (FTTRI)
862  {
863  double limit=2*epsilonMax;
864  for (size_t i1=0; i1<nref-1; ++i1)
865  {
866  centroid_i1.aliasImageInStack(mCentroids,i1);
867  for (size_t i2=i1+1; i2<nref; ++i2)
868  {
869  centroid_i2.aliasImageInStack(mCentroids,i2);
870  double d=fttri_distance(centroid_i1,centroid_i2);
871  if (d<limit)
872  {
873  bestEpsilonClasses[i1].neighbours.push_back(i2);
874  bestEpsilonClasses[i2].neighbours.push_back(i1);
875  }
876  }
877  }
878  }
879  else
880  {
881  MultidimArray<double> corr(nref,nref);
883  AlignmentAux aux;
884  CorrelationAux aux2;
886  corr.initConstant(-1);
887  int count=0;
888  if (node->isMaster())
889  init_progress_bar(nref);
890  for (size_t i1=0; i1<nref-1; ++i1)
891  {
892  centroid_i1.aliasImageInStack(mCentroids,i1);
893  centroid_i1.setXmippOrigin();
894  for (size_t i2=i1+1; i2<nref; ++i2, ++count)
895  {
896  if (((count+1)%node->size)==node->rank)
897  {
898  centroid_i2p.aliasImageInStack(mCentroids,i2);
899  centroid_i2p.setXmippOrigin();
900  centroid_i2=centroid_i2p;
901  A2D_ELEM(corr,i2,i1)=A2D_ELEM(corr,i1,i2)=alignImages(centroid_i1,centroid_i2,M,xmipp_transformation::WRAP,aux,aux2,aux3);
902  }
903  }
904  if (node->isMaster())
905  progress_bar(i1);
906  }
907  MPI_Allreduce(MPI_IN_PLACE, MULTIDIM_ARRAY(corr), nref*nref, MPI_DOUBLE,
908  MPI_MAX, MPI_COMM_WORLD);
909  if (node->isMaster())
910  progress_bar(nref);
911 
912  // For each class compute new neighbours
913  MultidimArray<double> corrRow;
914  MultidimArray<int> idx;
915  const int Kneighbours=2;
916  for (size_t i1=0; i1<nref; ++i1)
917  {
918  corr.getRow(i1,corrRow);
919  corrRow.indexSort(idx);
920  std::vector<int> &neighbours_i=bestEpsilonClasses[i1].neighbours;
921  for (int k = 0; k < Kneighbours; k++)
922  neighbours_i.push_back(idx(nref - k - 1) - 1);
923  }
924  }
925 }
926 
928 {
929  Matrix1D<short int> newAssignment;
930  newAssignment.resizeNoCopy(mdIn.size());
931  newAssignment.initConstant(-1);
932 
933  if (node->isMaster())
934  {
935  std::cerr << "Reassigning images to classes ..." << std::endl;
937  }
938 
939  MultidimArray<double> *ptrCentroids=nullptr;
940  if (FTTRI)
941  ptrCentroids=&fttriCentroids();
942  else
943  ptrCentroids=&imageCentroids();
944  const MultidimArray<double> &mCentroids=*ptrCentroids;
945 
946  Image<double> candidate;
947  FileName fnCandidate;
948  MultidimArray<double> own_class, neighbour, candidateCopy;
949  size_t changes=0;
950  AlignmentAux aux;
951  CorrelationAux aux2;
954  for (size_t i=0; i<nref; i++)
955  if (((i+1)%node->size)==node->rank)
956  {
957  std::vector<size_t> &class_i=bestEpsilonClasses[i].memberIdx;
958  std::vector<int> &neighbours_i=bestEpsilonClasses[i].neighbours;
959  int nmax=class_i.size();
960  int neighMax=neighbours_i.size();
961  own_class.aliasImageInStack(mCentroids,i);
962  own_class.setXmippOrigin();
963  for (int n=0; n<nmax; ++n)
964  {
965  // Get image n
966  int trueIdx=class_i[n];
967  if (FTTRI)
968  fnCandidate.compose(trueIdx+1,fnFTTRI);
969  else
970  mdIn.getValue(MDL_IMAGE,fnCandidate,imgsId[trueIdx]);
971  candidate.read(fnCandidate);
972  candidate().setXmippOrigin();
973 
974  // Compare to its own class
975  const MultidimArray<double> &mCandidate=candidate();
976  double bestD;
977  if (FTTRI)
978  bestD=fttri_distance(own_class,mCandidate);
979  else
980  {
981  candidateCopy=candidate();
982  bestD=alignImages(own_class,candidateCopy,M,xmipp_transformation::WRAP,aux,aux2,aux3);
983  }
984  VEC_ELEM(newAssignment,trueIdx)=i;
985 
986  // Now compare to the rest of neighbours
987  bool alreadyChanged=false;
988  for (int neigh=0; neigh<neighMax; neigh++)
989  {
990  int neighbourIdx=neighbours_i[neigh];
991  neighbour.aliasImageInStack(mCentroids,neighbourIdx);
992  neighbour.setXmippOrigin();
993  double d;
994  if (FTTRI)
995  d=fttri_distance(neighbour,mCandidate);
996  else
997  {
998  candidateCopy=candidate();
999  d=alignImages(neighbour,candidateCopy,M,xmipp_transformation::WRAP,aux,aux2,aux3);
1000  }
1001  if ((d<bestD && FTTRI) || (d>bestD && !FTTRI))
1002  {
1003  bestD=d;
1004  VEC_ELEM(newAssignment,trueIdx)=neighbourIdx;
1005  if (!alreadyChanged)
1006  {
1007  ++changes;
1008  alreadyChanged=true;
1009  }
1010  }
1011  }
1012  }
1013  if (node->isMaster())
1014  progress_bar(i);
1015  }
1016 
1017  // Share assignments
1018  MPI_Allreduce(MPI_IN_PLACE, &(VEC_ELEM(newAssignment,0)), VEC_XSIZE(newAssignment), MPI_SHORT,
1019  MPI_MAX, MPI_COMM_WORLD);
1020  MPI_Allreduce(MPI_IN_PLACE, &changes, 1, MPI_LONG, MPI_SUM, MPI_COMM_WORLD);
1021  if (node->isMaster())
1022  {
1023  progress_bar(nref);
1024  std::cerr << "Number of images changed: " << changes << std::endl;
1025  }
1026 
1027  // Create new best classes
1028  std::vector<EpsilonClass> newBestEpsilonClasses;
1029  newBestEpsilonClasses.resize(nref);
1030  FOR_ALL_ELEMENTS_IN_MATRIX1D(newAssignment)
1031  if (VEC_ELEM(newAssignment,i)>=0)
1032  newBestEpsilonClasses[VEC_ELEM(newAssignment,i)].memberIdx.push_back(i);
1033  bestEpsilonClasses=newBestEpsilonClasses;
1034  return changes;
1035 }
1036 
1037 // Write results ==========================================================
1039 {
1040  int imax=bestEpsilonClasses.size();
1041  MetaDataVec MDclass, MDsummary;
1042  FileName fnImg, fnCandidate;
1043  FileName fnClasses=fnRoot+"_classes.xmd";
1044  if (fnClasses.exists())
1045  fnClasses.deleteFile();
1046 
1047  // Sort each class
1048  Image<double> candidate;
1051  MultidimArray<int> idx;
1052  Matrix2D<double> M;
1053  AlignmentAux aux;
1054  CorrelationAux aux2;
1056  for (int i=0; i<imax; i++)
1057  {
1058  MDclass.clear();
1059  const std::vector<size_t> &class_i=bestEpsilonClasses[i].memberIdx;
1060  size_t nmax=class_i.size();
1061 
1062  // Write this class in summary
1063  size_t id=MDsummary.addObject();
1064  MDsummary.setValue(MDL_REF, i+1, id);
1065  MDsummary.setValue(MDL_CLASS_COUNT,nmax,id);
1067 
1068  // Measure the distance of each class and sort
1069  if (FTTRI)
1070  {
1071  centroid.aliasImageInStack(fttriCentroids(),i);
1072  distance.resizeNoCopy(nmax);
1073  for (size_t n=0; n<nmax; n++)
1074  {
1075  fnCandidate.compose(class_i[n]+1,fnFTTRI);
1076  candidate.read(fnCandidate);
1077  A1D_ELEM(distance,n)=fttri_distance(centroid,candidate());
1078  }
1079  }
1080  else
1081  {
1082  centroid.aliasImageInStack(imageCentroids(),i);
1083  centroid.setXmippOrigin();
1084  distance.resizeNoCopy(nmax);
1085  for (size_t n=0; n<nmax; n++)
1086  {
1087  int trueIdx=class_i[n];
1088  mdIn.getValue(MDL_IMAGE,fnCandidate,imgsId[trueIdx]);
1089  candidate.read(fnCandidate);
1090  candidate().setXmippOrigin();
1091  A1D_ELEM(distance,n)=1-alignImages(centroid,candidate(),M,xmipp_transformation::WRAP,aux,aux2,aux3);
1092  }
1093  }
1094  distance.indexSort(idx);
1095 
1096  // Write the class
1097  MDRowVec row;
1098  for (size_t n=0; n<nmax; n++)
1099  {
1100  int trueIdx=A1D_ELEM(idx,n)-1;
1101  size_t trueId=imgsId[class_i[trueIdx]];
1102  mdIn.getRow(row,trueId);
1103  size_t idClass=MDclass.addRow(row);
1104  MDclass.setValue(MDL_COST,A1D_ELEM(distance,trueIdx),idClass);
1105  MDclass.setValue(MDL_REF,i+1,idClass);
1106  mdIn.setValue(MDL_REF,i+1,trueId);
1107  }
1108  MDclass.write(formatString("class%06d_images@%s",i+1,fnClasses.c_str()),MD_APPEND);
1109  }
1110  MDsummary.write(formatString("classes@%s",fnClasses.c_str()),MD_APPEND);
1111  mdIn.write(fnRoot+"_images.xmd");
1112 }
1113 
1114 // Align images within classes ============================================
1116 {
1117  FileName fnCentroids, fnCandidate;
1118  fnCentroids=fnRoot+"_image_centroids.mrcs";
1119  if (node->isMaster())
1120  {
1121  std::cerr << "Aligning images within class ..." << std::endl;
1122  size_t Xdim, Ydim, Zdim, Ndim;
1123  getImageSize(mdIn, Xdim, Ydim, Zdim, Ndim);
1124  createEmptyFile(fnCentroids,Xdim,Ydim,1,nref,true,WRITE_OVERWRITE);
1125  }
1126  node->barrierWait();
1127 
1128  Image<double> centroid, candidate;
1129  if (node->isMaster())
1131  Image<int> mask;
1132  mask.read(fnRoot+"_mask.mrc");
1133  centroid().resizeNoCopy(mask());
1134 
1135  MultidimArray<double> &mCentroid=centroid();
1136  MultidimArray<int> &mMask=mask();
1137  MetaDataVec MDclass, MDaux;
1138  Matrix2D<double> M;
1139  MDRowVec row;
1140  for (size_t i=0; i<nref; i++)
1141  if (((i+1)%node->size)==node->rank)
1142  {
1143  const std::vector<size_t> &class_i=bestEpsilonClasses[i].memberIdx;
1144  size_t nmax=class_i.size();
1145  mCentroid.initZeros();
1146 
1147  if (nmax!=0)
1148  {
1149  MDclass.clear();
1150  for (size_t n=0; n<nmax; n++)
1151  {
1152  size_t trueIdx=class_i[n];
1153  size_t trueId=imgsId[trueIdx];
1154  mdIn.getRow(row,trueId);
1155  MDclass.addRow(row);
1156  }
1157 
1158  // Create centroid
1159  alignSetOfImages(MDclass,mCentroid,5,false);
1161  if (!DIRECT_MULTIDIM_ELEM(mMask,n))
1162  DIRECT_MULTIDIM_ELEM(mCentroid,n)=0.0;
1163 
1164  // Align images within class to centroid
1165  for (size_t objId : MDclass.ids())
1166  {
1167  MDclass.getValue(MDL_IMAGE,fnCandidate,objId);
1168  candidate.read(fnCandidate);
1169  candidate().setXmippOrigin();
1170  double corr=alignImages(mCentroid,candidate(),M);
1171  bool flip;
1172  double scale, shiftx, shifty, psi;
1173  transformationMatrix2Parameters2D(M, flip, scale, shiftx, shifty, psi);
1174  MDclass.setValue(MDL_SHIFT_X, shiftx, objId);
1175  MDclass.setValue(MDL_SHIFT_Y, shifty, objId);
1176  MDclass.setValue(MDL_ANGLE_PSI, psi, objId);
1177  MDclass.setValue(MDL_MAXCC, corr, objId);
1178  }
1179  }
1180 
1181  // Write new centroid
1182  centroid.write(fnCentroids,i+1,true,WRITE_REPLACE);
1183  MDaux.sort(MDclass,MDL_MAXCC,false);
1184  MDaux.write(formatString("%s_class%06d.xmd",fnRoot.c_str(),i+1));
1185  if (node->isMaster())
1186  progress_bar(i);
1187  }
1188  node->barrierWait();
1189  if (node->isMaster())
1190  {
1191  progress_bar(nref);
1192  FileName fnClasses=fnRoot+"_classes.xmd", fnClass;
1193  for (size_t i=0; i<nref; i++)
1194  {
1195  fnClass=formatString("%s_class%06d.xmd",fnRoot.c_str(),i+1);
1196  MDclass.read(fnClass);
1197  MDclass.write(formatString("class%06d_images@%s",i+1,fnClasses.c_str()),MD_APPEND);
1198  fnClass.deleteFile();
1199  }
1200 
1201  MetaDataVec MDsummary;
1202  FileName classesBlock=(String)"classes@"+fnClasses;
1203  MDsummary.read(classesBlock);
1204  int nref=1;
1205  FileName fnRef;
1206  for (size_t objId : MDsummary.ids())
1207  {
1208  fnRef.compose(nref++,fnCentroids);
1209  MDsummary.setValue(MDL_IMAGE,fnRef,objId);
1210  }
1211  MDsummary.write(classesBlock,MD_APPEND);
1212  }
1213 }
1214 
1215 // Run ====================================================================
1217 {
1218  show();
1219  produceSideInfo();
1220 #ifndef FTTRI_ALREADY_COMPUTED
1221 
1222  produceFTTRI();
1223 #endif
1224 
1228 
1230  if (node->isMaster())
1231  std::cout << "Final epsilon: " << bestEpsilon << "\n";
1233 
1234  // Amplitude classification
1235  if (node->isMaster())
1236  std::cout << std::endl << "Amplitude classification ..." << std::endl;
1237  for (int n=0; n<Niter; n++)
1238  {
1239  if (node->isMaster())
1240  std::cout << std::endl << "Iteration " << n << std::endl;
1241  splitLargeClasses(true);
1242  computeClassCentroids(true);
1243  computeClassNeighbours(true);
1246  }
1247 
1248  computeClassCentroids(true);
1249  if (node->isMaster())
1250  writeResults(true);
1251 
1252  // Amplitude and phase classification
1253  if (doPhase)
1254  {
1255  if (node->isMaster())
1256  std::cout << std::endl << "Amplitude and phase classification ..." << std::endl;
1257  for (int n=0; n<Niter; n++)
1258  {
1259  if (node->isMaster())
1260  std::cout << std::endl << "Iteration " << n << std::endl;
1261  splitLargeClasses(false);
1262  computeClassCentroids(false);
1263  computeClassNeighbours(false);
1264  reassignImagesToClasses(false);
1266  }
1267  if (node->isMaster())
1268  writeResults(false);
1269  }
1270 
1271  // Align images within classes
1272  node->barrierWait();
1274 
1275 }
double sigma1
First weight.
double zoom
Zoom factor for polar conversion.
void init_progress_bar(long total)
void removeSmallClasses()
Remove small classes.
void skipRandomNumberOfUnassignedClasses(size_t &currentPointer, size_t remaining)
Skip random number of unassigned classes.
int * nmax
void min(Image< double > &op1, const Image< double > &op2)
void searchOptimalEpsilon()
Search for optimal epsilon.
#define A2D_ELEM(v, i, j)
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
double pad
Padding factor.
void sort(const MetaDataVec &MDin, const MDLabel sortLabel, bool asc=true, int limit=-1, int offset=0)
double getDoubleParam(const char *param, int arg=0)
void sendListToRank(std::vector< size_t > &listToSend, int rank)
__host__ __device__ float2 floor(const float2 v)
int Niter
Number of iterations.
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
void transformationMatrix2Parameters2D(const Matrix2D< T > &A, bool &flip, T &scale, T &shiftX, T &shiftY, T &psi)
void image_convertCartesianToPolar_ZoomAtCenter(const MultidimArray< double > &in, MultidimArray< double > &out, Matrix1D< double > &R, double zoomFactor, double Rmin, double Rmax, int NRSteps, float angMin, double angMax, int NAngSteps)
Definition: polar.cpp:276
double alignImages(const MultidimArray< double > &Iref, const AlignmentTransforms &IrefTransforms, MultidimArray< double > &I, Matrix2D< double > &M, bool wrap, AlignmentAux &aux, CorrelationAux &aux2, RotationalCorrelationAux &aux3)
Definition: filters.cpp:2047
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
point centroid(const std::vector< point > &pts)
Definition: point.cpp:397
void sort(MultidimArray< T > &result) const
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
void produceFTTRI()
Produce invariants.
#define MULTIDIM_SIZE(v)
void resizeNoCopy(const MultidimArray< T1 > &v)
void computeClassNeighbours(bool FTTRI)
Compute centroid neighbours.
double fmax
Maximum frequency (normalized to 0.5)
void aliasImageInStack(const MultidimArray< T > &m, size_t select_image)
HBITMAP buffer
Definition: svm-toy.cpp:37
std::shared_ptr< MpiNode > node
Shift for the image in the X axis (double)
bool getTasks(size_t &first, size_t &last)
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
void estimateEpsilonInitialRange()
Estimate first epsilon range.
#define A1D_ELEM(v, i)
void getImageSize(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
std::vector< size_t > memberIdx
#define MULTIDIM_ARRAY(v)
void compose(const String &str, const size_t no, const String &ext="")
Special label to be used when gathering MDs in MpiMetadataPrograms.
void initConstant(T val)
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
size_t Rmax
Maximum frequency in pixels.
virtual IdIteratorProxy< false > ids()
std::unique_ptr< MDRow > getRow(size_t id) override
size_t size() const override
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
size_t addRow(const MDRow &row) override
doublereal * d
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
void randomPermutation(int N, MultidimArray< int > &result)
size_t nMinImages
Minimum number of images in a class.
std::vector< size_t > imgsId
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
double rnd_unif()
void clear() override
glob_log first
#define FOR_ALL_ELEMENTS_IN_MATRIX1D(v)
Definition: matrix1d.h:72
int argc
Original command line arguments.
Definition: xmipp_program.h:86
Image< double > fttriCentroids
Matrix1D< unsigned char > notAssigned
void writeResults(bool FTTRI)
void window(MultidimArray< T1 > &result, int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T1 init_value=0) const
Matrix1D< double > classEpsilon
const char * getParam(const char *param, int arg=0)
size_t wrapperFitness(double epsilon)
Function to optimize.
T computeMax() const
Definition: matrix1d.cpp:558
MpiTaskDistributor * taskDistributor
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
double fttri_distance(const MultidimArray< double > &fttri_i, const MultidimArray< double > &fttri_j)
Distance between two invariants.
Cost for the image (double)
void readParams()
Read argument from command line.
void findObjects(std::vector< size_t > &objectsOut, const MDQuery &query) const override
void receiveListFromRank(std::vector< size_t > &listToKeepIt, int rank)
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
void alignSetOfImages(MetaData &MD, MultidimArray< double > &Iavg, int Niter, bool considerMirror)
Definition: filters.cpp:2199
void progress_bar(long rlen)
void max(Image< double > &op1, const Image< double > &op2)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
const char ** argv
Definition: xmipp_program.h:87
size_t nref
Desired number of classes.
#define DIRECT_MULTIDIM_ELEM(v, n)
void addExampleLine(const char *example, bool verbatim=true)
FileName fnRoot
Output rootname.
__host__ __device__ float length(float2 v)
double sum(bool average=false) const
Definition: matrix1d.cpp:652
Maximum cross-correlation for the image (double)
void createEmptyFile(const FileName &filename, int xdim, int ydim, int Zdim, size_t select_img, bool isStack, int mode, int _swapWrite, const MDRowVec *md)
int verbose
Verbosity level.
bool operator()(EpsilonClass const &rpStart, EpsilonClass const &rpEnd)
bool exists() const
void sort(struct DCEL_T *dcel)
Definition: sorting.cpp:18
std::vector< EpsilonClass > bestEpsilonClasses
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
FileName fnIn
Input selfile.
#define j
void deleteFile() const
void getRow(size_t i, MultidimArray< T > &v) const
bool getValue(MDObject &mdValueOut, size_t id) const override
Class to which the image belongs (int)
TYPE distance(struct Point_T *p, struct Point_T *q)
Definition: point.cpp:28
bool doPhase
Do phase optimization.
#define MATRIX1D_ARRAY(v)
Definition: matrix1d.h:58
Number of images assigned to the same class as this image.
size_t reassignImagesToClasses(bool FTTRI)
Reassign images to image classes.
#define FIRST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:439
Matrix1D< unsigned char > notAssigned0
void defineParams()
Usage.
std::string String
Definition: xmipp_strings.h:34
double psi(const double x)
void produceSideInfo()
Produce side info.
bool fileExists(const char *filename)
String formatString(const char *format,...)
void splitLargeClasses(bool FTTRI)
Split large classes.
void completeFourierTransform(T &v, T1 &V)
Definition: xmipp_fftw.h:315
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458
bool checkParam(const char *param)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
Average intraclass distance (double)
Image< double > imageCentroids
void epsilonClassification(double epsilon)
Epsilon classification.
Shift for the image in the Y axis (double)
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
void computeClassCentroids(bool FTTRI)
#define LAST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:448
#define PI
Definition: tools.h:43
int getIntParam(const char *param, int arg=0)
int findFarthest(const MultidimArray< double > &seed, const EpsilonClass &class_i, bool FTTRI)
void FFT_magnitude(const MultidimArray< std::complex< double > > &v, MultidimArray< double > &mag)
Definition: xmipp_fftw.cpp:393
double epsilon
void initConstant(T val)
Definition: matrix1d.cpp:83
int * n
Name of an image (std::string)
ProgClassifyFTTRI(int argc, char **argv)
Empty constructor.
void indexSort(MultidimArray< int > &indx) const
std::vector< EpsilonClass > epsilonClasses
void addParamsLine(const String &line)
double sigma2
Second weight.