Xmipp  v3.23.11-Nereus
reconstruct_significant.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar S. Sorzano (coss@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
27 #include <algorithm>
28 #include "core/metadata_sql.h"
29 
30 // Define params
32 {
33  rank=0;
34  Nprocessors=1;
36  deltaAlpha2=0;
37 }
38 
40 {
41  //usage
42  addUsageLine("Generate 3D reconstructions from projections using random orientations");
43  //params
44  addParamsLine(" -i <md_file> : Metadata file with input projections");
45  addParamsLine(" [--numberOfVolumes <N=1>] : Number of volumes to reconstruct");
46  addParamsLine(" [--initvolumes <md_file=\"\">] : Set of initial volumes. If none is given, a single volume");
47  addParamsLine(" : is reconstructed with random angles assigned to the images");
48  addParamsLine(" [--initgallery <md_file=\"\">] : Gallery of projections from a single volume");
49  addParamsLine(" [--odir <outputDir=\".\">] : Output directory");
50  addParamsLine(" [--sym <symfile=c1>] : Enforce symmetry in projections");
51  addParamsLine(" [--iter <N=10>] : Number of iterations");
52  addParamsLine(" [--alpha0 <N=0.05>] : Initial significance");
53  addParamsLine(" [--alphaF <N=0.005>] : Final significance");
54  addParamsLine(" [--keepIntermediateVolumes] : Keep the volume of each iteration");
55  addParamsLine(" [--angularSampling <a=5>] : Angular sampling in degrees for generating the projection gallery");
56  addParamsLine(" [--maxShift <s=-1>] : Maximum shift allowed (+-this amount)");
57  addParamsLine(" [--minTilt <t=0>] : Minimum tilt angle");
58  addParamsLine(" [--maxTilt <t=90>] : Maximum tilt angle");
59  addParamsLine(" [--useImed] : Use Imed for weighting");
60  addParamsLine(" [--strictDirection] : Images not significant for a direction are also discarded");
61  addParamsLine(" [--angDistance <a=10>] : Angular distance");
62  addParamsLine(" [--dontApplyFisher] : Do not select directions using Fisher");
63  addParamsLine(" [--dontReconstruct] : Do not reconstruct");
64  addParamsLine(" [--useForValidation <numOrientationsPerParticle=10>] : Use the program for validation. This number defines the number of possible orientations per particle");
65  addParamsLine(" [--dontCheckMirrors] : Don't check mirrors in the alignment process");
66 
67 }
68 
69 // Read arguments ==========================================================
71 {
72  fnIn = getParam("-i");
73  fnDir = getParam("--odir");
74  fnSym = getParam("--sym");
75  fnInit = getParam("--initvolumes");
76  alpha0 = getDoubleParam("--alpha0");
77  alphaF = getDoubleParam("--alphaF");
78  Niter = getIntParam("--iter");
79  keepIntermediateVolumes = checkParam("--keepIntermediateVolumes");
80  angularSampling=getDoubleParam("--angularSampling");
81  maxShift=getDoubleParam("--maxShift");
82  tilt0=getDoubleParam("--minTilt");
83  tiltF=getDoubleParam("--maxTilt");
84  useImed=checkParam("--useImed");
85  strict=checkParam("--strictDirection");
86  angDistance=getDoubleParam("--angDistance");
87  Nvolumes=getIntParam("--numberOfVolumes");
88  applyFisher=checkParam("--dontApplyFisher");
89  fnFirstGallery=getParam("--initgallery");
90  doReconstruct=!checkParam("--dontReconstruct");
91  useForValidation=checkParam("--useForValidation");
92  numOrientationsPerParticle = getIntParam("--useForValidation");
93  dontCheckMirrors = checkParam("--dontCheckMirrors");
94 
95  if (!doReconstruct)
96  {
97  if (rank==0)
98  std::cout << "Setting iterations to 1 because of --dontReconstruct\n";
99  Niter=1; // Make sure that there is a single iteration
100  }
101 }
102 
103 // Show ====================================================================
105 {
106  if (verbose > 0)
107  {
108  std::cout << "Input metadata : " << fnIn << std::endl;
109  std::cout << "Output directory : " << fnDir << std::endl;
110  std::cout << "Initial significance : " << alpha0 << std::endl;
111  std::cout << "Final significance : " << alphaF << std::endl;
112  std::cout << "Number of iterations : " << Niter << std::endl;
113  std::cout << "Keep intermediate volumes : " << keepIntermediateVolumes << std::endl;
114  std::cout << "Angular sampling : " << angularSampling << std::endl;
115  std::cout << "Maximum shift : " << maxShift << std::endl;
116  std::cout << "Minimum tilt : " << tilt0 << std::endl;
117  std::cout << "Maximum tilt : " << tiltF << std::endl;
118  std::cout << "Use Imed : " << useImed << std::endl;
119  std::cout << "Angular distance : " << angDistance << std::endl;
120  std::cout << "Apply Fisher : " << applyFisher << std::endl;
121  std::cout << "Reconstruct : " << doReconstruct << std::endl;
122  std::cout << "useForValidation : " << useForValidation << std::endl;
123  std::cout << "dontCheckMirrors : " << dontCheckMirrors << std::endl;
124 
125 
126  if (fnSym != "")
127  std::cout << "Symmetry for projections : " << fnSym << std::endl;
128  if (fnFirstGallery=="")
129  {
130  if (fnInit !="")
131  std::cout << "Initial volume : " << fnInit << std::endl;
132  else
133  std::cout << "Number of volumes : " << Nvolumes << std::endl;
134  }
135  else
136  std::cout << "Gallery : " << fnFirstGallery << std::endl;
137 
138  if (useForValidation)
139  std::cout << " numOrientationsPerParticle : " << numOrientationsPerParticle << std::endl;
140  }
141 }
142 
143 // Image alignment ========================================================
144 //#define DEBUG
146 {
147  AlignmentAux aux;
148  CorrelationAux aux2;
150 
152  std::vector< Matrix2D<double> > allM;
153 
154  size_t Nvols=YSIZE(cc);
155  size_t Ndirs=XSIZE(cc);
156 
157  // Clear the previous assignment
158  for (size_t nvol=0; nvol<Nvols; ++nvol)
159  {
160  mdReconstructionPartial[nvol].clear();
162  }
163 
164  MultidimArray<double> imgcc(Nvols*Ndirs), imgimed(Nvols*Ndirs);
165  MultidimArray<double> cdfcc, cdfimed;
166  double one_alpha=1-currentAlpha-deltaAlpha2;
167 
168  FileName fnImg;
169  size_t nImg=0;
170  Image<double> I;
171  MultidimArray<double> mCurrentImageAligned, mGalleryProjection;
172  if (rank==0)
173  {
174  std::cout << "Current significance: " << one_alpha << std::endl;
175  std::cerr << "Aligning images ...\n";
177  }
178 
179  MultidimArray<double> ccVol(Nvols);
180  for (auto& row : mdIn)
181  {
182  if ((nImg+1)%Nprocessors==rank)
183  {
184  mdIn.getValue(MDL_IMAGE,fnImg, row.id());
185 #ifdef DEBUG
186  std::cout << "Processing: " << fnImg << std::endl;
187 #endif
188  I.read(fnImg);
189  MultidimArray<double> &mCurrentImage=I();
190  mCurrentImage.setXmippOrigin();
191  allM.clear();
192 
193  double bestCorr=-2, bestRot, bestTilt, bestImed=1e38, worstImed=-1e38;
194  Matrix2D<double> bestM;
195  int bestVolume=-1;
196 
197  // Compute all correlations
198  for (size_t nVolume=0; nVolume<Nvols; ++nVolume)
199  {
200  AlignmentTransforms *transforms=galleryTransforms[nVolume];
201  for (size_t nDir=0; nDir<Ndirs; ++nDir)
202  {
203  mCurrentImageAligned=mCurrentImage;
204  mGalleryProjection.aliasImageInStack(gallery[nVolume](),nDir);
205  mGalleryProjection.setXmippOrigin();
206  double corr;
207  if (! dontCheckMirrors)
208  corr=alignImagesConsideringMirrors(mGalleryProjection,transforms[nDir],
209  mCurrentImageAligned,M,aux,aux2,aux3,xmipp_transformation::DONT_WRAP);
210  else
211  corr = alignImages(mGalleryProjection, mCurrentImageAligned,
212  M, xmipp_transformation::DONT_WRAP);
213 
214 // double corr=alignImagesConsideringMirrors(mGalleryProjection,
215 // mCurrentImageAligned,M,aux,aux2,aux3,DONT_WRAP);
216  M=M.inv();
217  double scale, shiftX, shiftY, anglePsi;
218  bool flip;
219  transformationMatrix2Parameters2D(M,flip,scale,shiftX,shiftY,anglePsi);
220 
221  double imed=imedDistance(mGalleryProjection, mCurrentImageAligned);
222  if (maxShift>0 && (fabs(shiftX)>maxShift || fabs(shiftY)>maxShift))
223  {
224  corr/=3;
225  imed*=3;
226  }
227 
228 // //if (corr>0.99)
229 // //{
230 // //std::cout << prm.mdGallery[nVolume][nDir].fnImg << " corr= " << corr << " imed= " << imed << std::endl;
231 // //std::cout << "Matrix=" << M << std::endl;
232 // //Image<double> save;
233 // //save()=mGalleryProjection;
234 // //save.write("PPPgallery.xmp");
235 // //save()=mCurrentImage;
236 // //save.write("PPPcurrentImage.xmp");
237 // //save()=mCurrentImageAligned;
238 // //save.write("PPPcurrentImageAligned.xmp");
239 // //char c; std::cin >> c;
240 // //}
241 
242  DIRECT_A3D_ELEM(cc,nImg,nVolume,nDir)=corr;
243  // For the paper plot: std::cout << corr << " " << imed << std::endl;
244  size_t idx=nVolume*Ndirs+nDir;
245  DIRECT_A1D_ELEM(imgcc,idx)=corr;
246  DIRECT_A1D_ELEM(imgimed,idx)=imed;
247  allM.push_back(M);
248 
249  if (corr>bestCorr)
250  {
251  bestM=M;
252  bestCorr=corr;
253  bestVolume=(int)nVolume;
254  bestRot=mdGallery[nVolume][nDir].rot;
255  bestTilt=mdGallery[nVolume][nDir].tilt;
256  // std::cout << "nDir=" << nDir << " bestCorr=" << bestCorr << " imed=" << imed << " (bestImed=" << bestImed << ") M=" << M << std::endl;
257  }
258 
259  if (imed<bestImed)
260  bestImed=imed;
261  else if (imed>worstImed)
262  worstImed=imed;
263  }
264  }
265 
266  // Keep the best assignment for the projection matching
267  // Each process keeps a list of the images for each volume
268  MetaDataDb &mdProjectionMatching=mdReconstructionProjectionMatching[bestVolume];
269  double scale, shiftX, shiftY, anglePsi;
270  bool flip;
271  transformationMatrix2Parameters2D(bestM,flip,scale,shiftX,shiftY,anglePsi);
273  flip = false;
274 
275  if (maxShift<0 || (maxShift>0 && fabs(shiftX)<maxShift && fabs(shiftY)<maxShift))
276  {
277  size_t recId=mdProjectionMatching.addRow(dynamic_cast<MDRowSql&>(row));
278  mdProjectionMatching.setValue(MDL_ENABLED,1,recId);
279  mdProjectionMatching.setValue(MDL_MAXCC,bestCorr,recId);
280  mdProjectionMatching.setValue(MDL_ANGLE_ROT,bestRot,recId);
281  mdProjectionMatching.setValue(MDL_ANGLE_TILT,bestTilt,recId);
282  mdProjectionMatching.setValue(MDL_ANGLE_PSI,anglePsi,recId);
283  mdProjectionMatching.setValue(MDL_SHIFT_X,-shiftX,recId);
284  mdProjectionMatching.setValue(MDL_SHIFT_Y,-shiftY,recId);
285  mdProjectionMatching.setValue(MDL_FLIP,flip,recId);
286  }
287 
288  // Compute lower limit of correlation
289  double rl=bestCorr*one_alpha;
290  double z=0.5*log((1+rl)/(1-rl));
291  double zl=z-2.96*sqrt(1.0/MULTIDIM_SIZE(mCurrentImage));
292  double ccl=tanh(zl);
293 
294  // Compute the cumulative distributions
295  imgcc.cumlativeDensityFunction(cdfcc);
296  imgimed.cumlativeDensityFunction(cdfimed);
297 
298  // Check if force 1 volume
299  size_t firstVolume=0;
300  size_t lastVolume=Nvols-1;
301 
302  // Get the best images
303  for (size_t nVolume=firstVolume; nVolume<=lastVolume; ++nVolume)
304  {
305  MetaDataDb &mdPartial=mdReconstructionPartial[nVolume];
306  for (size_t nDir=0; nDir<Ndirs; ++nDir)
307  {
308  size_t idx=nVolume*Ndirs+nDir;
309  double cdfccthis=DIRECT_A1D_ELEM(cdfcc,idx);
310  double cdfimedthis=DIRECT_A1D_ELEM(cdfimed,idx);
311  double cc=DIRECT_A1D_ELEM(imgcc,idx);
312  // bool condition=!useImed || (useImed && cdfimedthis<=currentAlpha);
313 // if (cc>ccl)
314 // std::cout << "Image " << nImg << " " << fnImg << " qualifies by Fisher to dir=" << nDir << std::endl;
315 // if (!(cdfccthis>=one_alpha) && cc>ccl)
316 // std::cout << "Image " << nImg << " " << fnImg << " does not qualify by correlation percentile to " << nDir << " -> " << cdfccthis << " " << one_alpha << std::endl;
317 // if (!condition && cc>ccl)
318 // std::cout << "Image " << nImg << " " << fnImg << " does not qualify by imed percentile to " << nDir << " -> " << cdfimedthis << " " << currentAlpha<< std::endl;
319  bool condition=true;
320  condition=condition && ((applyFisher && cc>=ccl) || !applyFisher);
321  condition=condition && cdfccthis>=one_alpha;
322  if (condition)
323  {
324  // std::cout << fnImg << " is selected for dir=" << nDir << std::endl;
325  double imed=DIRECT_A1D_ELEM(imgimed,idx);
326  transformationMatrix2Parameters2D(allM[nVolume*Ndirs+nDir],flip,scale,shiftX,shiftY,anglePsi);
328  flip = false;
329 
330  if (maxShift>0)
331  if (fabs(shiftX)>maxShift || fabs(shiftY)>maxShift)
332  continue;
333  if (flip)
334  shiftX*=-1;
335 
336  double thisWeight=cdfccthis*(cc/bestCorr);
337  // COSS: To promote sparsity in the volume assignment: sum_i(cc_i^p)/sum_i(cc_i)*cc_i^p/cc_i
338  if (useImed)
339  thisWeight*=(1-cdfimedthis)*(bestImed/imed);
340  DIRECT_A3D_ELEM(weight,nImg,nVolume,nDir)=thisWeight;
341  double angleRot=mdGallery[nVolume][nDir].rot;
342  double angleTilt=mdGallery[nVolume][nDir].tilt;
343  #ifdef DEBUG
344  std::cout << " Getting Gallery: " << mdGallery[nVolume][nDir].fnImg
345  << " corr=" << cc << " imed=" << imed << " bestImed=" << bestImed << " weight=" << thisWeight << " rot=" << angleRot
346  << " tilt=" << angleTilt << std::endl
347  << " weight by corr=" << cdfccthis*(cc/bestCorr) << " weight by imed=" << (1-cdfimedthis)*(bestImed/imed) << std::endl
348  << "Matrix=" << allM[nVolume*Ndirs+nDir] << std::endl
349  << "shiftX=" << shiftX << " shiftY=" << shiftY << std::endl;
350  #endif
351 
352  size_t recId=mdPartial.addRow(dynamic_cast<MDRowSql&>(row));
353  mdPartial.setValue(MDL_ENABLED,1,recId);
354  mdPartial.setValue(MDL_MAXCC,cc,recId);
355  mdPartial.setValue(MDL_COST,imed,recId);
356  mdPartial.setValue(MDL_ANGLE_ROT,angleRot,recId);
357  mdPartial.setValue(MDL_ANGLE_TILT,angleTilt,recId);
358  mdPartial.setValue(MDL_ANGLE_PSI,anglePsi,recId);
359  mdPartial.setValue(MDL_SHIFT_X,-shiftX,recId);
360  mdPartial.setValue(MDL_SHIFT_Y,-shiftY,recId);
361  mdPartial.setValue(MDL_FLIP,flip,recId);
362  mdPartial.setValue(MDL_IMAGE_IDX,(size_t)nImg,recId);
363  mdPartial.setValue(MDL_REF,(int)nDir,recId);
364  mdPartial.setValue(MDL_REF3D,(int)nVolume,recId);
365  mdPartial.setValue(MDL_WEIGHT,thisWeight,recId);
366  mdPartial.setValue(MDL_WEIGHT_SIGNIFICANT,thisWeight,recId);
367  }
368  }
369  }
370 #ifdef DEBUG
371  std::cout << "Press any key" << std::endl;
372  char c; std::cin >> c;
373 #endif
374  }
375 
376  if (rank==0)
377  progress_bar(nImg+1);
378  nImg++;
379  }
380  if (rank==0)
381  progress_bar(mdIn.size());
382 }
383 #undef DEBUG
384 
385 // Main routine ------------------------------------------------------------
387 {
388  if (rank==0)
389  show();
390  produceSideinfo();
391 
392  /*currentAlpha=alpha0;
393  double deltaAlpha;
394  if (Niter>1)
395  deltaAlpha=(alphaF-alpha0)/(Niter-1);
396  else
397  deltaAlpha=0;
398 */
399  MetaDataVec mdAux;
400  size_t Nimgs=mdIn.size();
401  Image<double> save;
402  MultidimArray<double> ccdir, cdfccdir;
403  std::vector<double> ccdirNeighbourhood;
404  ccdirNeighbourhood.resize(10*Nimgs);
405  bool emptyVolumes=false;
406  Matrix1D<double> dir1, dir2;
407  for (iter=1; iter<=Niter; iter++)
408  {
409  if (rank==0)
410  std::cout << "\nIteration " << iter << std::endl;
411  // Generate projections from the different volumes
413  if (useForValidation)
415 
417  double deltaAlpha;
418  if (Niter>1)
419  deltaAlpha=(alphaF-alpha0)/(Niter-1);
420  else
421  deltaAlpha=0;
422 
423  size_t Nvols=mdGallery.size();
424  size_t Ndirs=mdGallery[0].size();
425  cc.initZeros(Nimgs,Nvols,Ndirs);
426  weight=cc;
427  double oneAlpha=1-currentAlpha-deltaAlpha2;
428 
429  // Align the input images to the projections
431  synchronize();
432  gatherAlignment();
433 
434  // Reweight according to each direction
435  if (rank==0)
436  {
437  std::cerr << "Readjusting weights ..." << std::endl;
438  init_progress_bar(Nvols);
439  for (size_t nVolume=0; nVolume<Nvols; ++nVolume)
440  {
441  for (size_t nDir=0; nDir<Ndirs; ++nDir)
442  {
443  // Look for the best correlation for this direction
444  double bestCorr=-2;
445  ccdirNeighbourhood.clear();
446  for (size_t nImg=0; nImg<Nimgs; ++nImg)
447  {
448  double ccimg=DIRECT_A3D_ELEM(cc,nImg,nVolume,nDir);
449  ccdirNeighbourhood.push_back(ccimg);
450  if (ccimg>bestCorr)
451  bestCorr=ccimg;
452  }
453 
454  // Look in the neighbourhood
455  GalleryImage &g1= mdGallery[nVolume][nDir];
456  for (size_t nDir2=0; nDir2<Ndirs; ++nDir2)
457  {
458  if (nDir!=nDir2)
459  {
460  GalleryImage &g2= mdGallery[nVolume][nDir2];
461  double ang=Euler_distanceBetweenAngleSets(g1.rot,g1.tilt,0.0,g2.rot,g2.tilt,0.0,true);
462  if (ang<angDistance)
463  {
464  for (size_t nImg=0; nImg<Nimgs; ++nImg)
465  {
466  double ccimg=DIRECT_A3D_ELEM(cc,nImg,nVolume,nDir);
467  ccdirNeighbourhood.push_back(ccimg);
468  if (ccimg>bestCorr)
469  bestCorr=ccimg;
470  }
471  }
472  }
473  }
474 
475  ccdir=ccdirNeighbourhood;
476  ccdir.cumlativeDensityFunction(cdfccdir);
477 
478  // Reweight all images for this direction
479  double iBestCorr=1.0/bestCorr;
480  for (size_t nImg=0; nImg<Nimgs; ++nImg)
481  {
482  double ccimg=DIRECT_A3D_ELEM(cc,nImg,nVolume,nDir);
483  double cdfThis=DIRECT_A1D_ELEM(cdfccdir,nImg);
484  if ((cdfThis>=oneAlpha || !strict) && DIRECT_A3D_ELEM(weight,nImg,nVolume,nDir)>0)
485  {
486  // std::cout << "Neighborhood " << nDir << " accepts image " << nImg << " with weight " << DIRECT_A3D_ELEM(weight,nImg,nVolume,nDir) << "*" << ccimg << "*" << iBestCorr << "*" << cdfThis << "=" << DIRECT_A3D_ELEM(weight,nImg,nVolume,nDir)*ccimg*iBestCorr*cdfThis << std::endl;
487  DIRECT_A3D_ELEM(weight,nImg,nVolume,nDir)*=ccimg*iBestCorr*cdfThis;
488  }
489  else
490  DIRECT_A3D_ELEM(weight,nImg,nVolume,nDir)=0;
491  }
492  }
493  progress_bar(nVolume);
494  }
495  progress_bar(Nvols);
496 
497  // Write the corresponding angular metadata
498  for (size_t nVolume=0; nVolume<(size_t)Nvolumes; ++nVolume)
499  {
500  MetaDataDb &mdReconstruction=mdReconstructionPartial[nVolume];
501  // Readjust weights with direction weights
502  for (size_t objId : mdReconstruction.ids())
503  {
504  size_t nImg;
505  int nVol, nDir;
506  mdReconstruction.getValue(MDL_IMAGE_IDX,nImg,objId);
507  mdReconstruction.getValue(MDL_REF,nDir,objId);
508  mdReconstruction.getValue(MDL_REF3D,nVol,objId);
509  mdReconstruction.setValue(MDL_WEIGHT,DIRECT_A3D_ELEM(weight,nImg,nVol,nDir),objId);
510  mdReconstruction.setValue(MDL_WEIGHT_SIGNIFICANT,DIRECT_A3D_ELEM(weight,nImg,nVol,nDir),objId);
511  //if (DIRECT_A3D_ELEM(weight,nImg,nVol,nDir)==0)
512  // std::cout << "Direction " << nDir << " does not accept img " << nImg << std::endl;
513  }
514 
515  // Remove zero-weight images
516  mdAux.clear();
517  if (mdReconstruction.size()>0)
518  mdAux.importObjects(mdReconstruction,MDValueGT(MDL_WEIGHT,0.0));
519 
520  String fnAngles=formatString("%s/angles_iter%03d_%02d.xmd",fnDir.c_str(),iter,nVolume);
521  if (mdAux.size()>0)
522  mdAux.write(fnAngles);
523  else
524  {
525  std::cout << formatString("%s/angles_iter%03d_%02d.xmd is empty. Not written.",fnDir.c_str(),iter,nVolume) << std::endl;
526  emptyVolumes=true;
527  }
528 
530  if (mdPM.size()>0 && fileExists(fnAngles.c_str()))
531  {
532  String fnImages=formatString("%s/images_iter%03d_%02d.xmd",fnDir.c_str(),iter,nVolume);
533  mdPM.write(fnImages);
534 
535  // Remove from mdPM those images that do not participate in angles
536  String fnAux=formatString("%s/aux_iter%03d_%02d.xmd",fnDir.c_str(),iter,nVolume);
537  // Take only the image name from angles.xmd
538  String cmd=(String)"xmipp_metadata_utilities -i "+fnAngles+" --operate keep_column image -o "+fnAux;
539  if (system(cmd.c_str())!=0)
540  REPORT_ERROR(ERR_MD,(String)"Cannot execute "+cmd);
541  // Remove duplicated images
542  cmd=(String)"xmipp_metadata_utilities -i "+fnAux+" --operate remove_duplicates image";
543  if (system(cmd.c_str())!=0)
544  REPORT_ERROR(ERR_MD,(String)"Cannot execute "+cmd);
545  // Intersect with images.xmd
546  String fnImagesSignificant=formatString("%s/images_significant_iter%03d_%02d.xmd",fnDir.c_str(),iter,nVolume);
547  cmd=(String)"xmipp_metadata_utilities -i "+fnImages+" --set intersection "+fnAux+" image image -o "+fnImagesSignificant;
548  if (system(cmd.c_str())!=0)
549  REPORT_ERROR(ERR_MD,(String)"Cannot execute "+cmd);
550  deleteFile(fnAux);
551  }
552  else
553  std::cout << formatString("%s/images_iter%03d_%02d.xmd empty. Not written.",fnDir.c_str(),iter,nVolume) << std::endl;
554  deleteFile(formatString("%s/gallery_iter%03d_%02d_sampling.xmd",fnDir.c_str(),iter,nVolume));
555  deleteFile(formatString("%s/gallery_iter%03d_%02d.doc",fnDir.c_str(),iter,nVolume));
556  deleteFile(formatString("%s/gallery_iter%03d_%02d.stk",fnDir.c_str(),iter,nVolume));
557  if (iter>=1 && !keepIntermediateVolumes)
558  {
559  deleteFile(formatString("%s/volume_iter%03d_%02d.vol",fnDir.c_str(),iter-1,nVolume));
560  deleteFile(formatString("%s/images_iter%03d_%02d.xmd",fnDir.c_str(),iter-1,nVolume));
561  deleteFile(formatString("%s/angles_iter%03d_%02d.xmd",fnDir.c_str(),iter-1,nVolume));
562  deleteFile(formatString("%s/images_significant_iter%03d_%02d.xmd",fnDir.c_str(),iter-1,nVolume));
563  }
564  }
565 
566  if (verbose>=2)
567  {
568  save()=cc;
569  save.write(formatString("%s/cc_iter%03d.vol",fnDir.c_str(),iter));
570  save()=weight;
571  save.write(formatString("%s/weight_iter%03d.vol",fnDir.c_str(),iter));
572  }
573  }
574  synchronize();
575 
576  // Reconstruct
577  if (doReconstruct)
579  else
580  break;
581 
582  currentAlpha+=deltaAlpha;
583 
584  if (emptyVolumes)
585  break;
586  }
587 }
588 
590 {
591  if (rank==0)
592  std::cerr << "Reconstructing volumes ..." << std::endl;
593  MetaDataVec MD;
594  for (size_t nVolume=0; nVolume<(size_t)Nvolumes; ++nVolume)
595  {
596  if ((nVolume+1)%Nprocessors!=rank)
597  continue;
598 
599  FileName fnAngles=formatString("%s/angles_iter%03d_%02d.xmd",fnDir.c_str(),iter,nVolume);
600  if (!fnAngles.exists())
601  continue;
602  MD.read(fnAngles);
603  std::cout << "Volume " << nVolume << ": number of images=" << MD.size() << std::endl;
604  FileName fnVolume=formatString("%s/volume_iter%03d_%02d.vol",fnDir.c_str(),iter,nVolume);
605  String args=formatString("-i %s -o %s --sym %s --weight -v 0",fnAngles.c_str(),fnVolume.c_str(),fnSym.c_str());
606  String cmd=(String)"xmipp_reconstruct_fourier "+args;
607  std::cout << cmd << std::endl;
608  if (system(cmd.c_str())==-1)
609  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot open shell");
610 
611  if (fnSym!="c1")
612  {
613  args=formatString("-i %s --sym %s -v 0",fnVolume.c_str(),fnSym.c_str());
614  cmd=(String)"xmipp_transform_symmetrize "+args;
615  std::cout << cmd << std::endl;
616  if (system(cmd.c_str())==-1)
617  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot open shell");
618  }
619 
620  args=formatString("-i %s --mask circular -%d -v 0",fnVolume.c_str(),Xdim/2);
621  cmd=(String)"xmipp_transform_mask "+args;
622  std::cout << cmd << std::endl;
623  if (system(cmd.c_str())==-1)
624  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot open shell");
625  }
626 }
627 
629 {
630  FileName fnGallery, fnGalleryMetaData;
631  if (iter>1 || fnFirstGallery=="")
632  {
633  FileName fnVol, fnAngles;
634  // Generate projections
635  for (int n=0; n<Nvolumes; n++)
636  {
637  if ((n+1)%Nprocessors!=rank)
638  continue;
639  fnVol=formatString("%s/volume_iter%03d_%02d.vol",fnDir.c_str(),iter-1,n);
640  fnGallery=formatString("%s/gallery_iter%03d_%02d.stk",fnDir.c_str(),iter,n);
641  fnAngles=formatString("%s/angles_iter%03d_%02d.xmd",fnDir.c_str(),iter-1,n);
642  fnGalleryMetaData=formatString("%s/gallery_iter%03d_%02d.doc",fnDir.c_str(),iter,n);
643  String args=formatString("-i %s -o %s --sampling_rate %f --sym %s --compute_neighbors --angular_distance -1 --experimental_images %s --min_tilt_angle %f --max_tilt_angle %f -v 0",
644  fnVol.c_str(),fnGallery.c_str(),angularSampling,fnSym.c_str(),fnAngles.c_str(),tilt0,tiltF);
645 
646  String cmd=(String)"xmipp_angular_project_library "+args;
647  if (system(cmd.c_str())==-1)
648  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot open shell");
649  }
650  synchronize();
651  }
652 
653  // Read projection galleries
654  std::vector<GalleryImage> galleryNames;
655  mdGallery.clear();
656 
657  CorrelationAux aux;
658  AlignmentAux aux2;
659  MultidimArray<double> mGalleryProjection;
660  for (int n=0; n<Nvolumes; n++)
661  {
662  mdGallery.push_back(galleryNames);
663  if (iter>1 || fnFirstGallery=="")
664  {
665  fnGalleryMetaData=formatString("%s/gallery_iter%03d_%02d.doc",fnDir.c_str(),iter,n);
666  fnGallery=formatString("%s/gallery_iter%03d_%02d.stk",fnDir.c_str(),iter,n);
667  }
668  else
669  {
670  fnGalleryMetaData=fnFirstGallery;
671  fnGallery=fnFirstGallery.replaceExtension("stk");
672  }
673  MetaDataVec mdAux(fnGalleryMetaData);
674  galleryNames.clear();
675  for (size_t objId : mdAux.ids())
676  {
677  GalleryImage I;
678  mdAux.getValue(MDL_IMAGE,I.fnImg,objId);
679  mdAux.getValue(MDL_ANGLE_ROT,I.rot,objId);
680  mdAux.getValue(MDL_ANGLE_TILT,I.tilt,objId);
681  mdGallery[n].push_back(I);
682  }
683  gallery[n].read(fnGallery);
684 
685  // Calculate transforms of this gallery
686  size_t kmax=NSIZE(gallery[n]());
687  if (galleryTransforms[n]==nullptr)
688  {
689  delete galleryTransforms[n];
691  }
693  for (size_t k=0; k<kmax; ++k)
694  {
695  mGalleryProjection.aliasImageInStack(gallery[n](),k);
696  mGalleryProjection.setXmippOrigin();
697  aux.transformer1.FourierTransform((MultidimArray<double> &)mGalleryProjection, transforms[k].FFTI, true);
698  polarFourierTransform<true>(mGalleryProjection, transforms[k].polarFourierI, false,
699  XSIZE(mGalleryProjection) / 5, XSIZE(mGalleryProjection) / 2, aux2.plans, 1);
700  }
701  }
702 }
703 
705 {
706 
707  auto number_of_projections = (double)mdGallery[0].size();
708 /*
709  double angDist[] = {0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0};
710  double numWithOutSymm[] = {165016, 41258, 18338, 10318, 6600, 4586, 3367, 2586, 2042, 1652, 1367, 1148, 977, 843, 732, 643, 569, 510, 460, 412, 340, 288, 245, 211, 184, 161, 146};
711  SymList SL;
712  SL.readSymmetryFile(fnSym);
713  size_t minIndex = 0;
714  double tmp = 1e3;
715  double numProjects = 0;
716  for (int idx = 0; idx < 27; idx++)
717  {
718  if ( std::abs(angularSampling-angDist[idx]) < tmp)
719  {
720  minIndex = idx;
721  numProjects = (numWithOutSymm[idx]/((2*(SL.symsNo()+1))));
722  tmp = std::abs(angularSampling-angDist[idx]);
723  }
724  }
725  angularSampling = angDist[minIndex];
726 */
727 
728  alpha0 = numOrientationsPerParticle/number_of_projections;
729  alphaF = alpha0;
730  deltaAlpha2 = 1/(2*number_of_projections);
731 
732  if (rank==0)
733  {
734  std::cout << " Changing angular sampling to " << angularSampling << std::endl;
735  std::cout << " Number of projections taking into account angular sampling and symmetry " << number_of_projections << std::endl;
736  std::cout << " changing alpha0 to " << alpha0 << std::endl;
737  }
738 
739 }
740 
742 {
743  mdIn.read(fnIn);
745 
746  mdIn.fillConstant(MDL_MAXCC,"0.0");
753 
754  size_t Ydim,Zdim,Ndim;
755  getImageSize(mdIn,Xdim,Ydim,Zdim,Ndim);
756 
757  // Adjust alpha
758  if ( (fnSym!="c1") && !useForValidation )
759  {
760  SymList SL;
762  alpha0*=SL.true_symNo;
763  alphaF*=SL.true_symNo;
764  if (alpha0>1)
765  REPORT_ERROR(ERR_ARG_INCORRECT,"Alpha values are too large: reduce the error such that the error times the symmetry number is smaller than 1");
766  }
767  // If there is not any input volume, create a random one
768  if (fnFirstGallery=="")
769  {
770  bool deleteInit=false;
771  if (fnInit=="")
772  {
773  deleteInit=true;
774  MetaDataVec mdAux;
775  for (int n=0; n<Nvolumes; ++n)
776  {
777  fnInit=fnDir+"/volume_random.xmd";
778  if (rank==0)
779  {
780  MetaDataVec mdRandom;
781  mdRandom=mdIn;
782  for (size_t objId : mdRandom.ids())
783  {
784  mdRandom.setValue(MDL_ANGLE_ROT,rnd_unif(0,360),objId);
785  mdRandom.setValue(MDL_ANGLE_TILT,rnd_unif(0,180),objId);
786  mdRandom.setValue(MDL_ANGLE_PSI,rnd_unif(0,360),objId);
787  mdRandom.setValue(MDL_SHIFT_X,0.0,objId);
788  mdRandom.setValue(MDL_SHIFT_Y,0.0,objId);
789  }
790  FileName fnAngles=fnDir+formatString("/angles_random_%02d.xmd",n);
791  FileName fnVolume=fnDir+formatString("/volume_random_%02d.vol",n);
792  mdRandom.write(fnAngles);
793  String args=formatString("-i %s -o %s --sym %s -v 0",fnAngles.c_str(),fnVolume.c_str(),fnSym.c_str());
794  String cmd=(String)"xmipp_reconstruct_fourier "+args;
795  if (system(cmd.c_str())==-1)
796  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot open shell");
798  deleteFile(fnAngles);
799 
800  // Symmetrize with many different possibilities to have a spherical volume
801  args=formatString("-i %s --sym i1 --spline 1 -v 0",fnVolume.c_str());
802  cmd=(String)"xmipp_transform_symmetrize "+args;
803  if (system(cmd.c_str())==-1)
804  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot open shell");
805 
806  args=formatString("-i %s --sym i3 --spline 1 -v 0",fnVolume.c_str());
807  if (system(cmd.c_str())==-1)
808  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot open shell");
809 
810  args=formatString("-i %s --sym i2 --spline 1 -v 0",fnVolume.c_str());
811  if (system(cmd.c_str())==-1)
812  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot open shell");
813  deleteFile(fnAngles);
814  mdAux.setValue(MDL_IMAGE,fnVolume,mdAux.addObject());
815  }
816  }
817  if (rank==0)
818  mdAux.write(fnInit);
819  synchronize();
820  }
821 
822  // Copy all input values as iteration 0 volumes
823  MetaDataVec mdInit;
824  mdInit.read(fnInit);
825  FileName fnVol;
826  Image<double> V;
827  int idx=0;
828  for (size_t objId : mdInit.ids())
829  {
830  if (rank==0)
831  {
832  mdInit.getValue(MDL_IMAGE,fnVol,objId);
833  V.read(fnVol);
834  fnVol=formatString("%s/volume_iter000_%02d.vol",fnDir.c_str(),idx);
835  V.write(fnVol);
836  mdInit.setValue(MDL_IMAGE,fnVol,objId);
837  }
838  idx++;
839  }
840  Nvolumes=(int)mdInit.size();
841 
842  iter=0;
843  synchronize();
844  if (deleteInit && rank==0)
846  }
847  else
848  Nvolumes=1;
849  synchronize();
850 
851  // Copy all input values as iteration 0 volumes
852  FileName fnAngles;
853  Image<double> galleryDummy;
854  MetaDataDb mdPartial, mdProjMatch;
855  for (int idx=0; idx<Nvolumes; ++idx)
856  {
857  if (rank==0)
858  {
859  fnAngles=formatString("%s/angles_iter000_%02d.xmd",fnDir.c_str(),idx);
860  mdIn.write(fnAngles);
861  }
862  gallery.push_back(galleryDummy);
863  galleryTransforms.push_back(nullptr);
864  mdReconstructionPartial.push_back(mdPartial);
865  mdReconstructionProjectionMatching.push_back(mdProjMatch);
866  }
867 
868  iter=0;
869  synchronize();
870 }
#define NSIZE(v)
Just to locate unclassified errors.
Definition: xmipp_error.h:192
void init_progress_bar(long total)
Rotation angle of an image (double,degrees)
#define YSIZE(v)
FourierTransformer transformer1
Definition: xmipp_fftw.h:555
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
void cumlativeDensityFunction(MultidimArray< double > &cdf)
double getDoubleParam(const char *param, int arg=0)
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)
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
FileName replaceExtension(const String &newExt) const
std::vector< Image< double > > gallery
doublereal * c
#define MULTIDIM_SIZE(v)
Index of an image within a list (size_t)
void sqrt(Image< double > &op)
void aliasImageInStack(const MultidimArray< T > &m, size_t select_image)
bool getValue(MDObject &mdValueOut, size_t id) const override
virtual void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const =0
Tilting angle of an image (double,degrees)
int readSymmetryFile(FileName fn_sym, double accuracy=SYM_ACCURACY)
Definition: symmetries.cpp:33
Shift for the image in the X axis (double)
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)
Polar_fftw_plans * plans
Definition: filters.h:514
void getImageSize(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
Special label to be used when gathering MDs in MpiMetadataPrograms.
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
virtual IdIteratorProxy< false > ids()
void defineParams()
Read arguments from command line.
size_t size() const override
void deleteFile(const char *line)
Definition: tools.cpp:280
Is this image enabled? (int [-1 or 1])
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
virtual void synchronize()
Synchronize with other processors.
void fillConstant(MDLabel label, const String &value) override
void alignImagesToGallery()
Align images to gallery projections.
double rnd_unif()
void clear() override
#define DIRECT_A1D_ELEM(v, i)
void produceSideinfo()
Produce side info: fill arrays with relevant transformation matrices.
Weight due to Angular significance.
void log(Image< double > &op)
const char * getParam(const char *param, int arg=0)
void generateProjections()
Generate projections from the current volume.
void reconstructCurrent()
Reconstruct current volume.
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
size_t addRow(const MDRow &row) override
Cost for the image (double)
Incorrect argument received.
Definition: xmipp_error.h:113
void importObjects(const MetaData &md, const std::vector< size_t > &objectsToAdd, bool doClear=true) override
Flip the image? (bool)
double imedDistance(const MultidimArray< double > &I1, const MultidimArray< double > &I2)
Definition: filters.cpp:1269
#define XSIZE(v)
void progress_bar(long rlen)
std::vector< MetaDataDb > mdReconstructionProjectionMatching
T Euler_distanceBetweenAngleSets(T rot1, T tilt1, T psi1, T rot2, T tilt2, T psi2, bool only_projdir)
Definition: geometry.cpp:681
MetaData error.
Definition: xmipp_error.h:154
double z
MultidimArray< double > weight
Maximum cross-correlation for the image (double)
int true_symNo
Definition: symmetries.h:153
int verbose
Verbosity level.
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const override
virtual size_t size() const =0
virtual void gatherAlignment()
Gather alignment.
bool exists() const
#define DIRECT_A3D_ELEM(v, k, i, j)
size_t size() const override
void FourierTransform(T &v, T1 &V, bool getCopy=true)
Definition: xmipp_fftw.h:166
3D Class to which the image belongs (int)
template void polarFourierTransform< true >(MultidimArray< double > const &, Polar< double > &, Polar< std::complex< double > > &, bool, int, int, Polar_fftw_plans *&, int)
bool getValue(MDObject &mdValueOut, size_t id) const override
Class to which the image belongs (int)
bool setValue(const MDObject &mdValueIn, size_t id) override
Definition: metadata_db.cpp:90
std::vector< AlignmentTransforms *> galleryTransforms
virtual void removeDisabled()
std::string String
Definition: xmipp_strings.h:34
bool fileExists(const char *filename)
String formatString(const char *format,...)
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=NULL, bool decomposeStack=true) override
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)
Polar< std::complex< double > > polarFourierI
Definition: filters.h:525
Shift for the image in the Y axis (double)
std::vector< std::vector< GalleryImage > > mdGallery
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
unsigned int randomize_random_generator()
virtual void readParams()
Read arguments from command line.
int getIntParam(const char *param, int arg=0)
double alignImagesConsideringMirrors(const MultidimArray< double > &Iref, const AlignmentTransforms &IrefTransforms, MultidimArray< double > &I, Matrix2D< double > &M, AlignmentAux &aux, CorrelationAux &aux2, RotationalCorrelationAux &aux3, bool wrap, const MultidimArray< int > *mask)
Definition: filters.cpp:2150
ProgReconstructSignificant()
Empty constructor.
int * n
Name of an image (std::string)
std::vector< MetaDataDb > mdReconstructionPartial
void addParamsLine(const String &line)
< Score 4 for volumes