Xmipp  v3.23.11-Nereus
mlf_align2d.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Sjors Scheres scheres@cnb.csic.es (2007)
4  *
5  * Unidad de Bioinformatica del 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 #include "mlf_align2d.h"
26 #include "core/metadata_sql.h"
27 #include "core/transformations.h"
28 
29 // Constructor ===============================================
30 ProgMLF2D::ProgMLF2D(int nr_vols, int rank, int size)
31 {
32  defaultRoot = "mlf2d";
33  if (nr_vols == 0)
34  {
35  do_ML3D = false;
36  this->nr_vols = 1;
37  refs_per_class = 1;
38  }
39  else
40  do_ML3D = true;
41 
42  this->rank = rank;
43  this->size = size;
44 }
45 
47 {
49  prog->addParamsLine("[--no_ctf] : do not use any CTF correction, you should provide sampling rate");
50  prog->addParamsLine(" requires --sampling_rate;");
51  //prog->addParamsLine(" : by defaut the CTF info is read from input images metadata");
52  prog->addParamsLine(" [--sampling_rate <Ts>] : If provided, this sampling rate will overwrites the one in the ctf file");
53 }
54 
55 void ProgMLF2D::defineAdditionalParams(XmippProgram * prog, const char * sectionLine)
56 {
57  ML2DBaseProgram::defineAdditionalParams(prog, sectionLine);
58  //even more additional params
59  prog->addParamsLine(" [ --search_shift <int=3>] : Limited translational searches (in pixels) ");
60  prog->addParamsLine(" [ --reduce_snr <factor=1> ] : Use a value smaller than one to decrease the estimated SSNRs ");
61  prog->addParamsLine(" [ --not_phase_flipped ] : Use this if the experimental images have not been phase flipped ");
62  prog->addParamsLine(" [ --ctf_affected_refs ] : Use this if the references (-ref) are not CTF-deconvoluted ");
63  prog->addParamsLine(" [ --limit_resolution <first_high=0> <high=0> <low=999>]: Exclude frequencies from P-calculations (in Ang)");
64  prog->addParamsLine(" : First value is highest frequency during first iteration.");
65  prog->addParamsLine(" : Second is the highest in following iterations and third is lowest");
66  prog->addParamsLine(" [ --fix_high <float=-1>] : ");
67  prog->addParamsLine(" [ --include_allfreqs ] ");
68 }
69 
70 // Fourier mode usage ==============================================================
72 {
73  //add usage
74 
75  //params
76  defaultRoot = "mlf2d";
77  allowRestart = true;
78  allowIEM = false;
79  defineBasicParams(this);
80  defineAdditionalParams(this, "==+ Additional options ==");
81  //hidden params
82  defineHiddenParams(this);
83  addParamsLine(" [--var_psi]");
84  addParamsLine(" [--var_trans]");
85  addParamsLine(" [--kstest]");
86  addParamsLine(" [--iter_histogram <int=-1>]");
87 }
88 
89 // Read arguments ==========================================================
91 {
92 
93  // Generate new command line for restart procedure
94  cline = "";
95  int argc2 = 0;
96  char ** argv2 = nullptr;
97 
98  double restart_offset = 0;
99  FileName restart_imgmd, restart_refmd;
100  int restart_iter = 0;
101  int restart_seed = 0;
102 
103 
104  do_restart = checkParam("--restart");
105  if (do_restart)
106  {
107  MetaDataVec MDrestart;
108  char *copy = nullptr;
109 
110  MDrestart.read(getParameter(argc, argv, "--restart"));
111  cline = MDrestart.getComment();
112  size_t id = MDrestart.firstRowId();
113  MDrestart.getValue(MDL_SIGMAOFFSET, restart_offset, id);
114  MDrestart.getValue(MDL_IMGMD, restart_imgmd, id);
115  MDrestart.getValue(MDL_REFMD, restart_refmd, id);
116  MDrestart.getValue(MDL_ITER, restart_iter, id);
117  MDrestart.getValue(MDL_RANDOMSEED, restart_seed, id);
118  //MDrestart.getValue(MDL_SIGMANOISE, restart_noise);
119  generateCommandLine(cline, argc2, argv2, copy);
120  }
121  else
122  {
123  // no restart, just copy argc to argc2 and argv to argv2
124  argc2 = argc;
125  argv2 = (char **)argv;
126  for (int i = 1; i < argc2; i++)
127  {
128  cline = cline + (String)argv2[i] + " ";
129  }
130  }
131  // Number of threads
132  threads = getIntParam("--thr");
133 
134  // Main parameters
135  model.n_ref = getIntParam("--nref");
136  fn_ref = getParam("--ref");
137  fn_img = getParam("-i");
138  bool a = checkParam("--no_ctf");
139  do_ctf_correction = !a;//checkParam("--no_ctf");
140 
141  sampling = checkParam("--sampling_rate") ? getDoubleParam("--sampling_rate") : -1;
142  fn_root = getParam("--oroot");
143  search_shift = getIntParam("--search_shift");
144  psi_step = getDoubleParam("--psi_step");
145  do_mirror = checkParam("--mirror");
146  ini_highres_limit = getIntParam("--limit_resolution", 0);
147  highres_limit = getIntParam("--limit_resolution", 1);
148  lowres_limit = getIntParam("--limit_resolution", 2);
149  phase_flipped = !checkParam("--not_phase_flipped");
150  reduce_snr = getDoubleParam("--reduce_snr");
151  first_iter_noctf = checkParam("--ctf_affected_refs");
152 
153  // Less common stuff
154  Niter = getIntParam("--iter");
155  istart = do_ML3D ? 1 : getIntParam("--restart");
156  sigma_offset = getDoubleParam("--offset");
157  eps = getDoubleParam("--eps");
158  fn_frac = getParam("--frac");
159  fix_fractions = checkParam("--fix_fractions");
160  fix_sigma_offset = checkParam("--fix_sigma_offset");
161  fix_sigma_noise = checkParam("--fix_sigma_noise");
162  C_fast = getDoubleParam("-C");
163  //fn_doc = getParam("--doc");
164  do_include_allfreqs = checkParam("--include_allfreqs");
165  fix_high = getDoubleParam("--fix_high");
166 
167  search_rot = getDoubleParam("--search_rot");
168 
169  // Hidden arguments
170  debug = getIntParam("--debug");
171  do_variable_psi = checkParam("--var_psi");
172  do_variable_trans = checkParam("--var_trans");
173  do_norm = checkParam("--norm");
174  do_student = checkParam("--student");
175  df = getDoubleParam("--student");
176  do_student_sigma_trick = !checkParam("--no_sigma_trick");
177  do_kstest = checkParam("--kstest");
178  iter_write_histograms = getIntParam("--iter_histogram");
179  seed = getIntParam("--random_seed");
180 
181  // Now reset some stuff for restart
182  if (do_restart)
183  {
184  fn_img = restart_imgmd;
185  fn_ref = restart_refmd;
186  model.n_ref = 0; // Just to be sure (not strictly necessary)
187  sigma_offset = restart_offset;
188  //sigma_noise = restart_noise;
189  seed = int(restart_seed);
190  istart = restart_iter + 1;
191  }
192 
193  if (seed == -1)
194  seed = time(nullptr);
195 
196 }
197 
198 // Show ====================================================================
199 void ProgMLF2D::show(bool ML3D)
200 {
201 
202  if (verbose)
203  {
204  // To screen
205  if (!do_ML3D)
206  {
207  std::cout
208  << " -----------------------------------------------------------------" << std::endl
209  << " | Read more about this program in the following publication: |" << std::endl
210  << " | Scheres ea. (2007) Structure, 15, 1167-1177 |" << std::endl
211  << " | |" << std::endl
212  << " | *** Please cite it if this program is of use to you! *** |" << std::endl
213  << " -----------------------------------------------------------------" << std::endl;
214  }
215  std::cout
216  << "--> Multi-reference refinement " << std::endl
217  << "--> using a maximum-likelihood in Fourier-space (MLF) target " <<std::endl
218  << (do_ctf_correction ? "--> with CTF correction " : "--> ignoring CTF effects ")<<std::endl
219  << " Input images : " << fn_img << " (" << nr_images_global << ")" << std::endl;
220 
221  if (!fn_ref.empty())
222  std::cout << " Reference image(s) : " << fn_ref << std::endl;
223  else
224  std::cout << " Number of references: : " << model.n_ref << std::endl;
225 
226  std::cout
227  << " Output rootname : " << fn_root << std::endl
228  << " Stopping criterium : " << eps << std::endl
229  << " initial sigma offset : " << sigma_offset << std::endl
230  << " Psi sampling interval : " << psi_step << " degrees" << std::endl
231  << " Translational searches : " << search_shift << " pixels" << std::endl
232  << " Low resolution limit : " << lowres_limit << " Ang" << std::endl
233  << " High resolution limit : " << highres_limit << " Ang" << std::endl;
234 
235  if (reduce_snr != 1.)
236  std::cout << " Multiply estimated SNR : " << reduce_snr << std::endl;
237  if (reduce_snr > 1.)
238  std::cerr << " --> WARNING!! With reduce_snr>1 you may likely overfit the noise!" << std::endl;
239  std::cout << " Check mirrors : " << (do_mirror ? "true" : "false") << std::endl;
240  if (!fn_frac.empty())
241  std::cout << " Initial model fractions : " << fn_frac << std::endl;
242  if (do_ctf_correction)
243  {
244  std::cout << " + Assuming images have " << (phase_flipped ? "" : "not") << "been phase flipped " << std::endl;
245 
247  {
248  std::cout << formatString(" + CTF group %d contains %d images", ifocus + 1, count_defocus[ifocus]) << std::endl;
249  }
250  }
251  if (ini_highres_limit > 0.)
252  std::cout << " + High resolution limit for 1st iteration set to " << ini_highres_limit << "Ang"<<std::endl;
253  if (search_rot < 180.)
254  std::cout << " + Limit orientational search to +/- " << search_rot << " degrees" << std::endl;
255  if (do_variable_psi)
256  std::cout << " + Vary in-plane rotational sampling with resolution " << std::endl;
257  if (do_variable_trans)
258  std::cout << " + Vary in-plane translational sampling with resolution " << std::endl;
259 
260  // Hidden stuff
261  if (fix_fractions)
262  {
263  std::cout << " + Do not update estimates of model fractions." << std::endl;
264  }
265  if (fix_sigma_offset)
266  {
267  std::cout << " + Do not update sigma-estimate of origin offsets." << std::endl;
268  }
269  if (fix_sigma_noise)
270  {
271  std::cout << " + Do not update estimated noise spectra." << std::endl;
272  }
273  if (do_student)
274  {
275  std::cout << " -> Use t-student distribution with df = " <<df<< std::endl;
277  {
278  std::cout << " -> Use sigma-trick for t-student distributions" << std::endl;
279  }
280  }
281  if (do_norm)
282  {
283  std::cout << " -> Developmental: refine normalization internally "<<std::endl;
284  }
285  if (do_kstest)
286  {
287  std::cout << " -> Developmental: perform KS-test on noise distributions "<<std::endl;
288  if (iter_write_histograms >0.)
289  std::cout << " -> Developmental: write noise histograms at iteration "<<iter_write_histograms<<std::endl;
290  }
291  std::cout << " -----------------------------------------------------------------" << std::endl;
292 
293  }
294 
295 }
296 
297 // Set up a lot of general stuff
298 // This side info is general, i.e. in parallel mode it is the same for
299 // all processors! (in contrast to produceSideInfo2)
301 {
302  //LOG_LEVEL(produceSideInfo);
303  LOG_FUNCTION();
304 
305  FileName fn_tmp, fn_base, fn_tmp2;
306  Image<double> img;
307  CTFDescription ctf;
308  MultidimArray<double> dum, rmean_ctf;
309  Matrix2D<double> A(3, 3);
310  Matrix1D<double> offsets(2);
311  MultidimArray<double> Maux, Maux2;
312  MultidimArray<std::complex<double> > Faux, ctfmask; //2D
313  MultidimArray<int> radial_count; //1D
314  Matrix1D<int> center(2);
315  std::vector<int> tmppointp, tmppointp_nolow, tmppointi, tmppointj;
316  double Q0=0.;
317 
318  // Read selfile with experimental images
319  MDimg.read(fn_img);
320  MDimg.removeDisabled(); // Discard disabled images
322 
323  // Create a vector of objectIDs, which may be randomized later on
325 
326  // Get image sizes and total number of images
327  size_t idum, ndum;
328  getImageSize(MDimg, dim, idum, idum, ndum);
329  hdim = dim / 2;
330  dim2 = dim * dim;
331 
332  // Set sampling stuff: flipping matrices, psi_step etc.
334  max_nr_psi = nr_psi;
335 
336  // Initialization of resolhist
337  if (do_kstest)
338  {
339  resolhist.resize(hdim);
340  for (size_t ires = 0; ires < hdim; ires++)
341  {
342  resolhist[ires].init(HISTMIN, HISTMAX, HISTSTEPS);
343  }
344  }
345 
346  // Fill limited translation shift-vectors
347  nr_trans = 0;
348  Maux.resize(dim, dim);
349  Maux.setXmippOrigin();
350  int ss = search_shift * search_shift;
352  {
353  int r2 = i * i + j * j;
354  if (r2 <= ss)
355  {
356  XX(offsets) = (double)j;
357  YY(offsets) = (double)i;
358  Vtrans.push_back(offsets);
359  if (i == 0 && j == 0)
361  nr_trans++;
362  }
363  }
364 
365  FileName fnt_img, fnt;
366  std::vector<FileName> all_fn_ctfs;
367 
368  count_defocus.clear();
369  Vctf.clear();
370  Vdec.clear();
371  Vsig.clear();
372  if (!do_ctf_correction)
373  {
374  nr_focus = 1;
375  count_defocus.push_back(nr_images_global);
376  Vctf.push_back(dum);
377  Vctf[0].resize(hdim);
378  Vctf[0].initConstant(1.); //fill with 1.
379  Vdec.push_back(Vctf[0]); //just copy
380  Vsig.push_back(Vctf[0]);
381  }
382  else
383  {
384  // Read ctfdat and determine the number of CTF groups
385  nr_focus = 0;
386  all_fn_ctfs.clear();
387  FileName fn_ctf;
388 
389  //CTF info now comes on input metadatas
390  MetaDataDb mdCTF;
391  std::vector<MDLabel> groupby;
392  groupCTFMetaData(MDimg, mdCTF, groupby);
393 
394  if (sampling > 0)
395  {
398  }
399 
400  nr_focus = mdCTF.size();
401 
402  //todo: set defocus group for each image
403 
404  // Check the number of images in each CTF group
405  // and read CTF-parameters from disc
406  //FOR_ALL_DEFOCUS_GROUPS()
407  int ifocus = 0;
408  count_defocus.resize(nr_focus);
410 
411  for (size_t objId : mdCTF.ids())
412  {
413  //Set defocus group
414  mdCTF.setValue(MDL_DEFGROUP, ifocus, objId);
415  //Read number of images in group
416  size_t c;
417  mdCTF.getValue(MDL_COUNT, c, objId);
418  count_defocus[ifocus] = (int)c;
419  if (count_defocus[ifocus] < 50 && verbose)
420  std::cerr << "WARNING%% CTF group " << (ifocus + 1) << " contains less than 50 images!" << std::endl;
421 
422  //Read ctf from disk
423  ctf.readFromMetadataRow(mdCTF, objId);
424 
425  double astigmCTFFactor = fabs( (ctf.DeltafV - ctf.DeltafU) / (std::max(ctf.DeltafV, ctf.DeltafU)) );
426  // we discard the CTF with a normalized diference between deltaU and deltaV of 10%
427  if (astigmCTFFactor > 0.1)
428  {
429  FileName ctfname;
430  //REPORT_ERROR(ERR_NUMERICAL, "Prog_MLFalign2D-ERROR%% Only non-astigmatic CTFs are allowed!");
431  std::cerr << "CTF is too astigmatic. We ill ignore it." << std::endl;
432  std::cerr << " defocus U: " << ctf.DeltafU << " defocus V: " << ctf.DeltafV << std::endl;
433  std::cerr << " astigmCTFFactor " << astigmCTFFactor << std::endl;
434  //continue;
435  }
436  ctf.DeltafV = (ctf.DeltafU+ctf.DeltafV)*0.5;
437  ctf.DeltafU = ctf.DeltafV;
438 
439  ctf.K = 1.;
440  ctf.enable_CTF = true;
441  ctf.produceSideInfo();
442  ctf.generateCTF(dim, dim, ctfmask);
443  if (ifocus == 0)
444  {
445  sampling = ctf.Tm;
446  Q0 = ctf.Q0;
447  }
448  else
449  {
450  if (sampling != ctf.Tm)
451  REPORT_ERROR(ERR_NUMERICAL, "Prog_MLFalign2D-ERROR%% Different sampling rates in CTF parameter files!");
452  if (Q0 != ctf.Q0 )
453  REPORT_ERROR(ERR_NUMERICAL, "Prog_MLFalign2D-ERROR%% Avoid different Q0 values in the CTF parameter files!");
454  }
455  Maux.resize(dim, dim);
457  {
458  if (phase_flipped)
459  dAij(Maux, i, j) = fabs(dAij(ctfmask, i, j).real());
460  else
461  dAij(Maux, i, j) = dAij(ctfmask, i, j).real();
462  }
463  CenterFFT(Maux, true);
464  center.initZeros();
465  rmean_ctf.initZeros();
466  Maux.setXmippOrigin();
467  radialAverage(Maux, center, rmean_ctf, radial_count, true);
468  Vctf.push_back(dum);
469  Vdec.push_back(dum);
470  Vsig.push_back(dum);
471  Vctf[ifocus].resize(hdim);
473  {
474  VCTF_ITEM = dAi(rmean_ctf, irr);
475  }
476  Vdec[ifocus].resize(Vctf[ifocus]);
477  Vsig[ifocus].resize(Vctf[ifocus]);
478  ++ifocus;
479  }
480 
481  // Make a join to set the MDL_DEFGROUP to each image
482  MetaDataDb md(MDimg);
483  MDimg.joinNatural(md, mdCTF);
484  }
485 
486  // Get a resolution pointer in Fourier-space
487  Maux.resize(dim, dim);
488  Maux.setXmippOrigin();
490  {
491  A2D_ELEM(Maux, i, j) = XMIPP_MIN((double) (hdim - 1), sqrt((double)(i * i + j * j)));
492  }
493  CenterFFT(Maux, false);
494  Mresol_int.resize(dim, dim);
496  {
497  dAij(Mresol_int, i, j) = ROUND(dAij(Maux, i, j));
498  }
499 
500  // Check whether to generate new references
501  do_generate_refs = false;
502  if (fn_ref.empty())
503  {
504  if (model.n_ref > 0)
505  {
507  do_generate_refs = true;
508 
509  if (rank == 0)
511  }
512  else
513  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS, "Please provide -ref or -nref larger than zero");
514  }
515 
516  show();
518 }
519 
520 // Read reference images to memory and initialize offset vectors
521 // This side info is NOT general, i.e. in parallel mode it is NOT the
522 // same for all processors! (in contrast to produce_Side_info)
524 {
526  int c, idum, refno = 0;
527  double aux = 0.;
528  FileName fn_tmp;
529  Image<double> img;
530  std::vector<double> Vdum, sumw_defocus;
531 
532  // Read in all reference images in memory
533  MDref.read(fn_ref);
534 
535  model.n_ref = MDref.size();
536  refno = 0;
537  double ref_fraction = (double)1. / model.n_ref;
538  double ref_weight = (double)nr_images_global / model.n_ref;
539 
540  for (size_t objId : MDref.ids())
541  {
542  MDref.getValue(MDL_IMAGE, fn_tmp, objId);
543  img.read(fn_tmp);
544  img().setXmippOrigin();
545  model.Iref.push_back(img);
546  Iold.push_back(img);
547  Ictf.push_back(img);
548  // Default start is all equal model fractions
549  alpha_k.push_back(ref_fraction);
550  model.Iref[refno].setWeight(ref_weight);
551  // Default start is half-half mirrored images
552  mirror_fraction.push_back((do_mirror ? 0.5 : 0.));
553  refno++;
554  }
555 
556  //This will differ from nr_images_global if MPI
558  //#define DEBUG
559 #ifdef DEBUG
560 
561  std::cerr << "nr_images_local= "<< nr_images_local<<std::endl;
562  std::cerr << "myFirstImg= "<< myFirstImg<<std::endl;
563  std::cerr << "myLastImg= "<< myLastImg<<std::endl;
564  std::cerr <<"size="<<size<<"rank="<<rank<<std::endl;
565 
566 #endif
567  //--------Setup for Docfile -----------
569 
570  if (do_norm)
571  {
572  average_scale = 1.;
573  refs_avgscale.assign(model.n_ref, 1.);
574  imgs_scale.assign(nr_images_local, 1.);
575  }
576 
577  // Fill imgs_offsets vectors with zeros
578  idum = (do_mirror ? 4 : 2) * model.n_ref;
579 
581  {
582  imgs_offsets.push_back(Vdum);
583  for (int refno = 0; refno < idum; refno++)
584  {
585  imgs_offsets[IMG_LOCAL_INDEX].push_back(0.);
586  }
587  }
588 
589  // For limited orientational search: fill imgs_oldphi & imgs_oldtheta
590  // (either read from fn_doc or initialize to -999.)
591  if (limit_rot)
592  {
593  imgs_oldphi.assign(nr_images_local, -999.);
594  imgs_oldtheta.assign(nr_images_local, -999.);
595  }
596 
597  if (do_restart)
598  {
599  // Read optimal image-parameters
600  // FOR_ALL_LOCAL_IMAGES()
601  // {
602  // if (limit_rot || do_norm)
603  // {
604  // MDimg.getValue(MDL_ANGLE_ROT, imgs_oldphi[IMG_LOCAL_INDEX]);
605  // MDimg.getValue(MDL_ANGLE_TILT, imgs_oldtheta[IMG_LOCAL_INDEX]);
606  // }
607  //
608  // idum = (do_mirror ? 2 : 1) * model.n_ref;
609  // double xoff, yoff;
610  // MDimg.getValue(MDL_SHIFT_X, xoff);
611  // MDimg.getValue(MDL_SHIFT_Y, yoff);
612  // for (int refno = 0; refno < idum; refno++)
613  // {
614  // imgs_offsets[IMG_LOCAL_INDEX][2 * refno] = xoff;
615  // imgs_offsets[IMG_LOCAL_INDEX][2 * refno + 1] = yoff;
616  // }
617  //
618  // if (do_norm)
619  // {
620  // MDimg.getValue(MDL_INTSCALE, imgs_scale[IMG_LOCAL_INDEX]);
621  // }
622  // }
623 
624  // read Model parameters
625  refno = 0;
626  double sumw = 0.;
627  for (size_t objId : MDref.ids())
628  {
629  MDref.getValue(MDL_WEIGHT, alpha_k[refno], objId);
630  sumw += alpha_k[refno];
631  if (do_mirror)
633  mirror_fraction[refno], objId);
634  if (do_norm)
635  MDref.getValue(MDL_INTSCALE, refs_avgscale[refno], objId);
636  refno++;
637  }
639  {
640  alpha_k[refno] /= sumw;
641  }
642  }
643 
646  MultidimArray<double> dum, rmean_signal2, spectral_signal;
647  Matrix1D<int> center(2);
648  MultidimArray<int> radial_count;
649  std::ifstream fh;
650 
651 
652 
653  center.initZeros();
654  // Calculate average spectral signal
655  c = 0;
657  {
658  if (alpha_k[refno] > 0.)
659  {
660  FourierTransform(model.Iref[refno](), Faux);
661  FFT_magnitude(Faux, Maux);
662  CenterFFT(Maux, true);
663  Maux *= Maux;
664  Maux *= alpha_k[refno] * (double)nr_images_global;
665  Maux.setXmippOrigin();
666  rmean_signal2.initZeros();
667  radialAverage(Maux, center, rmean_signal2, radial_count, true);
668  if (c == 0)
669  spectral_signal = rmean_signal2;
670  else
671  spectral_signal += rmean_signal2;
672  c++;
673  }
674  }
675  if (do_ML3D)
676  {
677  // Divide by the number of reference volumes
678  // But I don't know alpha (from 3DSSNR) yet:
679  // Introduce a fudge-factor of 2 to prevent over-estimation ...
680  // I think this is irrelevant, as the spectral_signal is
681  // re-calculated in ml_refine3d.cpp
682  double inv_2_nr_vol = 1. / (double)(nr_vols * 2);
683  spectral_signal *= inv_2_nr_vol;
684  }
685  else
686  {
687  // Divide by the number of reference images
688  double inv_n_ref = 1. / (double) model.n_ref;
689  spectral_signal *= inv_n_ref;
690  }
691 
692  // Read in Vsig-vectors with fixed file names
693  FileName fn_base = FN_ITER_BASE(istart - 1);
694  MetaDataVec md;
695 
697  {
698  fn_tmp = FN_VSIG(fn_base, ifocus, "noise.xmd");
699  md.read(fn_tmp);
700 
701  size_t i = 0;
702  for (size_t objId : md.ids())
703  {
704  md.getValue(MDL_MLF_NOISE, aux, objId);
705  dAi(Vsig[ifocus], i) = aux;
706  i++;
707  }
708 
709 #ifdef OLD_FILE
710  fh.open((fn_tmp).c_str(), std::ios::in);
711  if (!fh)
712  REPORT_ERROR(ERR_IO_NOTOPEN, (String)"Prog_MLFalign2D_prm: Cannot read file: " + fn_tmp);
713  else
714  {
716  {
717  fh >> aux;
718  if (ABS(aux - ((double)irr/(sampling*dim)) ) > 0.01 )
719  {
720  std::cerr<<"aux= "<<aux<<" resol= "<<(double)irr/(sampling*dim)<<std::endl;
721  REPORT_ERROR(ERR_NUMERICAL, (String)"Prog_MLFalign2D_prm: Wrong format: " + fn_tmp);
722  }
723  fh >> aux;
724  VSIG_ITEM = aux;
725  }
726  }
727  fh.close();
728 #endif
729  // Initially set sumw_defocus equal to count_defocus
730  sumw_defocus.push_back((double)count_defocus[ifocus]);
731  }
732  // Calculate all Wiener filters
733  updateWienerFilters(spectral_signal, sumw_defocus, istart - 1);
734 
735 }
736 
737 // For initial noise variances
739 {
740  LOG_FUNCTION();
741  // For first iteration only: calculate sigma2 (& spectral noise) from power
742  // spectra of all images and subtract power spectrum of average image
743  // (to take away low-res frequencies where the signal dominates!)
744  if (istart == 1)
745  {
746 
747  MultidimArray<double> Maux, Mallave;
748  MultidimArray<std::complex<double> > Fimg, Faux, Fave;
749  MultidimArray<double> rmean_noise, rmean_signal, rmean_avesignal;
750  std::vector<MultidimArray<double> > Msigma2, Mave;
751  Matrix1D<int> center(2);
752  MultidimArray<int> radial_count;
753  Image<double> img;
754  FileName fn_tmp;
755  std::ofstream fh;
756 
757  center.initZeros();
758 
759  int focus = 0;
760 
761  if (verbose > 0)
762  std::cout << "--> Estimating initial noise models from average power spectra ..." << std::endl;
763 
765 
766  Msigma2.clear();
767  Msigma2.resize(nr_focus);
768  Mave.clear();
769  Mave.resize(nr_focus);
770 
772  {
773  Msigma2[ifocus].initZeros(dim, dim);
774  Msigma2[ifocus].setXmippOrigin();
775  Mave[ifocus].initZeros(dim, dim);
776  Mave[ifocus].setXmippOrigin();
777  }
778 
779  Maux.initZeros(dim, dim);
780  int imgno = 0;
781 
782  for (size_t objId : MDimg.ids())
783  {
784  focus = 0;
785  if (do_ctf_correction)
786  MDimg.getValue(MDL_DEFGROUP, focus, objId);
787  MDimg.getValue(MDL_IMAGE, fn_tmp, objId);
788  //img.read(fn_tmp, false, false, false, false);
789  //TODO: Check this????
790  img.read(fn_tmp);
791  img().setXmippOrigin();
792  FourierTransform(img(), Fimg);
793  FFT_magnitude(Fimg, Maux);
794  Maux.setXmippOrigin();
795  Maux *= Maux;
796  Msigma2[focus] += Maux;
797  Mave[focus] += img();
798  setProgress(++imgno);
799  }
800 
801  endProgress();
802 
803  FileName fn_base = FN_ITER_BASE(istart - 1);
804 
805  // Calculate Vsig vectors and write them to disc
806 
808  {
809  Mave[ifocus] /= (double)count_defocus[ifocus];
810  FourierTransform(Mave[ifocus], Fave);
811  FFT_magnitude(Fave, Maux);
812  Maux *= Maux;
813  CenterFFT(Maux, true);
814  Maux.setXmippOrigin();
815  rmean_signal.initZeros();
816  radialAverage(Maux, center, rmean_signal, radial_count, true);
817  CenterFFT(Msigma2[ifocus], true);
818  Msigma2[ifocus].setXmippOrigin();
819  rmean_noise.initZeros();
820  radialAverage(Msigma2[ifocus], center, rmean_noise, radial_count, true);
821  rmean_noise /= (double)count_defocus[ifocus];
822  // Subtract signal terms
823  // Divide by factor 2 because of the 2D-Gaussian distribution!
825  VSIG_ITEM = (dAi(rmean_noise, irr) - dAi(rmean_signal, irr)) / 2.;
826 
827 
828  // write Vsig vector to disc (only master)
829  if (IS_MASTER)
830  writeNoiseFile(fn_base, ifocus);
831 
832  fn_tmp = FN_VSIG(fn_base, ifocus, "noise.xmd");
833 
834 #ifdef OLD_FILE
835 
836  fh.open((fn_tmp).c_str(), std::ios::out);
837  if (!fh)
838  REPORT_ERROR(ERR_IO_NOTOPEN, (String)"Prog_MLFalign2D_prm: Cannot write file: " + fn_tmp);
840  {
841  fh << (double)irr/(sampling*dim) << " " << VSIG_ITEM << "\n";
842  }
843  fh.close();
844 #endif
845 
846  }
847  Msigma2.clear();
848  Mave.clear();
849  }
850 
851 }
852 
854  std::vector<double> &sumw_defocus,
855  int iter)
856 {
857  LOG_FUNCTION();
858  // Use formula 2.32b on p60 from Frank's book 2nd ed.,
859  // Assume that Vctf, Vdec and Vsig exist (with their right sizes)
860  // and that Vctf, Vsig are already filled with the right values
861 
862  std::vector<MultidimArray<double> > Vsnr;
863  MultidimArray<double> Vzero, Vdenom, Vavgctf2;
866  std::ofstream fh;
867  size_t maxres = 0;
868  double noise, sum_sumw_defocus = 0.;
869  size_t int_lowres_limit, int_highres_limit, int_ini_highres_limit;
870  size_t current_probres_limit;
871  FileName fn_base, fn_tmp;
872 
873  // integer resolution limits (in shells)
874  int_lowres_limit = (size_t)(sampling * dim / lowres_limit);
875  int_highres_limit = (highres_limit > 0.) ? ROUND(sampling * dim / highres_limit) : hdim;
876  int_ini_highres_limit = (ini_highres_limit > 0.) ? ROUND(sampling * dim / ini_highres_limit) : hdim;
877 
878  // Pre-calculate average CTF^2 and initialize Vsnr
879  Vavgctf2.initZeros(hdim);
880  Vzero.initZeros(hdim);
881  Vsnr.resize(nr_focus, Vzero);
882 
884  {
885  double & defocus_weight = sumw_defocus[ifocus];
886  sum_sumw_defocus += defocus_weight;
888  dAi(Vavgctf2, irr) += VCTF_ITEM * VCTF_ITEM * defocus_weight;
889  }
890  Vavgctf2 /= sum_sumw_defocus;
891 
892  // std::cerr << "DEBUG_JM, updateWienerFilters: spectral_signal: " << spectral_signal << std::endl;
893 
894  // Calculate SSNR for all CTF groups
895  // For each group the spectral noise is estimated via (2*Vsig)/(sumw_defocus-1)
896  // The spectral signal is not split into CTF groups
897  // Therefore, affect the average spectral_signal for each defocu
898  // group with its CTF^2 and divide by the average CTF^2
900  {
902  {
903  //if (verbose) std::cerr << "DEBUG_JM: ifocus: " << ifocus << std::endl;
904  //if (verbose) std::cerr << "DEBUG_JM: irr: " << irr << std::endl;
905 
906  noise = 2. * VSIG_ITEM * sumw_defocus[ifocus];
907  noise /= sumw_defocus[ifocus] - 1;
908 
909  //if (verbose) std::cerr << "DEBUG_JM: noise: " << noise << std::endl;
910  //if (verbose) std::cerr << "DEBUG_JM: VSNR_ITEM: " << VSNR_ITEM << std::endl;
911  VSNR_ITEM = 0.;
912 
913  if (noise > 1e-20 && dAi(Vavgctf2, irr) > 0.)
914  {
916  dAi(spectral_signal, irr) / (dAi(Vavgctf2, irr) * noise);
917  //if (verbose) std::cerr << "DEBUG_JM: inside cond: (noise > 1e-20 && dAi(Vavgctf2, irr)" <<std::endl;
918  //if (verbose) std::cerr << "DEBUG_JM: VCTF_ITEM: " << VCTF_ITEM << std::endl;
919  //if (verbose) std::cerr << "DEBUG_JM: dAi(spectral_signal, irr): " << dAi(spectral_signal, irr) << std::endl;
920  //if (verbose) std::cerr << "DEBUG_JM: dAi(Vavgctf2, irr): " << dAi(Vavgctf2, irr) << std::endl;
921  //if (verbose) std::cerr << "DEBUG_JM: noise: " << noise << std::endl;
922  //if (verbose) std::cerr << "DEBUG_JM: VSNR_ITEM: " << VSNR_ITEM << std::endl;
923  }
924  // For start from already CTF-deconvoluted references:
925  if ((iter == istart - 1) && !first_iter_noctf)
926  {
927  VSNR_ITEM *= dAi(Vavgctf2, irr);
928  //if (verbose) std::cerr << "DEBUG_JM: inside cond: (noise > 1e-20 && dAi(Vavgctf2, irr)" <<std::endl;
929  //if (verbose) std::cerr << "DEBUG_JM: VSNR_ITEM: " << VSNR_ITEM << std::endl;
930  }
931  // Take ini_highres_limit into account (only for first iteration)
932  if ( iter == 0 && ini_highres_limit > 0. && irr > int_ini_highres_limit )
933  {
934  VSNR_ITEM = 0.;
935  //if (verbose) std::cerr << "DEBUG_JM: inside cond: iter == 0 && ini_highres_limit > 0. && irr > int_ini_highres_limit" <<std::endl;
936  //if (verbose) std::cerr << "DEBUG_JM: VSNR_ITEM: " << VSNR_ITEM << std::endl;
937  }
938  // Subtract 1 according Unser et al.
939  VSNR_ITEM = XMIPP_MAX(0., VSNR_ITEM - 1.);
940  // Prevent spurious high-frequency significant SNRs from random averages
941  if (iter == 0 && do_generate_refs)
942  {
943  VSNR_ITEM = XMIPP_MAX(0., VSNR_ITEM - 2.);
944  //if (verbose) std::cerr << "DEBUG_JM: inside cond: iter == 0 && do_generate_refs" <<std::endl;
945  //if (verbose) std::cerr << "DEBUG_JM: VSNR_ITEM: " << VSNR_ITEM << std::endl;
946  }
947  if (VSNR_ITEM > 0. && irr > maxres)
948  {
949  maxres = irr;
950  //if (verbose) std::cerr << "DEBUG_JM: inside cond: VSNR_ITEM > 0. && irr > maxres" <<std::endl;
951  //if (verbose) std::cerr << "DEBUG_JM: VSNR_ITEM: " << VSNR_ITEM << std::endl;
952  //if (verbose) std::cerr << "DEBUG_JM: maxres: " << maxres << std::endl;
953  }
954  }
955  }
956 
957  // Check that at least some frequencies have non-zero SSNR...
958  if (maxres == 0)
959  REPORT_ERROR(ERR_VALUE_INCORRECT, "ProgMLF2D: All frequencies have zero spectral SNRs... (increase -reduce_snr) ");
960 
961  if (do_ctf_correction)
962  {
963  // Pre-calculate denominator of eq 2.32b of Frank's book (2nd ed.)
964  Vdenom.initZeros(hdim);
966  {
968  {
969  dAi(Vdenom, irr) += sumw_defocus[ifocus] * VSNR_ITEM * VCTF_ITEM * VCTF_ITEM;
970  }
971  dAi(Vdenom, irr) += 1.;
972  dAi(Vdenom, irr) /= sum_sumw_defocus;
973  }
974 
975  // Calculate Wiener filters
977  {
979  {
980  if (VSNR_ITEM > 0.)
981  {
982  VDEC_ITEM = VSNR_ITEM * VCTF_ITEM / dAi(Vdenom, irr);
983  // Prevent too strong Wiener filter artefacts
984  VDEC_ITEM = XMIPP_MIN(10., VDEC_ITEM);
985  }
986  else
987  {
988  VDEC_ITEM = 0.;
989  }
990  }
991  }
992  }
993 
994  // Write Wiener filters and spectral SNR to text files
995  double resol_step = 1. / (sampling * dim);
996  double resol_freq = 0;
997  double resol_real = 999.;
998  MDRowVec row;
999 
1000  if (verbose > 0)
1001  {
1002  fn_base = FN_ITER_BASE(iter);
1003  // CTF group-specific Wiener filter files
1005  {
1006  resol_freq = 0;
1007  MetaDataVec md;
1009  {
1010  noise = 2. * VSIG_ITEM * sumw_defocus[ifocus];
1011  noise /= (sumw_defocus[ifocus] - 1);
1012  if (irr > 0)
1013  resol_real = (sampling*dim)/(double)irr;
1014  row.setValue(MDL_RESOLUTION_FREQ, resol_freq);
1018  row.setValue(MDL_MLF_SIGNAL, dAi(spectral_signal, irr));
1019  row.setValue(MDL_MLF_NOISE, noise);
1020  row.setValue(MDL_RESOLUTION_FREQREAL, resol_real);
1021  md.addRow(row);
1022  resol_freq += resol_step;
1023  }
1024  fn_tmp = FN_VSIG(fn_base, ifocus, "ssnr.xmd");
1025  md.write(fn_tmp, (ifocus > 0 ? MD_APPEND : MD_OVERWRITE));
1026 
1027  }
1028  }
1029 
1030  // Set the current resolution limits
1031  if (do_include_allfreqs)
1032  {
1033  current_probres_limit = hdim-1;
1035 
1036  }
1037  else if (fix_high > 0.)
1038  {
1039  current_probres_limit = ROUND((sampling*dim)/fix_high);
1041 
1042  }
1043  else
1044  {
1045  current_probres_limit = maxres;
1046  current_highres_limit = maxres + 5; // hard-code increase_highres_limit to 5
1047 
1048  }
1049 
1050  // Set overall high resolution limit
1051  current_probres_limit = XMIPP_MIN(current_probres_limit, int_highres_limit);
1053 
1054  current_probres_limit = XMIPP_MIN(current_probres_limit, hdim);
1056  //std::cerr << "DEBUG_JM(6): current_probres_limit: " << current_probres_limit << std::endl;
1057 
1058  if (debug>0)
1059  {
1060  std::cerr
1061  << "current_probres_limit dependencies: " << std::endl
1062  << " hdim: " << hdim << " dim: " << dim << std::endl
1063  << " sampling: " << sampling << " fix_high: " << fix_high << std::endl
1064  << " maxres: " << maxres << " int_highres_limit: " << int_highres_limit << std::endl;
1065 
1066  std::cerr<<" Current resolution limits: "<<std::endl;
1067  std::cerr<<" + low res= "<<lowres_limit<<" Ang ("<<int_lowres_limit<<" shell)"<<std::endl;
1068  std::cerr<<" + prob. res= "<<sampling*dim/current_probres_limit<<" Ang ("<<current_probres_limit<<" shell)"<<std::endl;
1069  std::cerr<<" + extra res= "<<sampling*dim/current_highres_limit<<" Ang ("<<current_highres_limit<<" shell)"<<std::endl;
1070  std::cerr<<" + high res= "<<highres_limit<<" Ang ("<<int_highres_limit<<" shell)"<<std::endl;
1071  }
1072 
1073  // Get the new pointers to all pixels in FourierTransformHalf
1074  Maux.initZeros(dim, dim);
1075  Maux.setXmippOrigin();
1076  FourierTransformHalf(Maux, Faux);
1077  pointer_2d.clear();
1078  pointer_i.clear();
1079  pointer_j.clear();
1080 
1081  // First, get the pixels to use in the probability calculations:
1082  // These are within [lowres_limit,current_probres_limit]
1083  nr_points_prob = 0;
1085  {
1086  size_t ires = dAij(Mresol_int, i, j);
1087  if (ires > int_lowres_limit &&
1088  ires <= current_probres_limit &&
1089  !(i == 0 && j > hdim) ) // exclude first half row in FourierTransformHalf
1090  {
1091  pointer_2d.push_back(i*XSIZE(Maux) + j);
1092  pointer_i.push_back(i);
1093  pointer_j.push_back(j);
1094  ++nr_points_prob;
1095  }
1096  }
1097  // Second, get the rest of the currently relevant pixels:
1098  // These are within [0,lowres_limit> and between <current_probres_limit,current_highres_limit]
1101  {
1102  size_t ires = dAij(Mresol_int, i, j);
1103  if ( (ires <= int_lowres_limit || ires > current_probres_limit) &&
1104  ires <= current_highres_limit &&
1105  !(i == 0 && j > hdim) ) // exclude first half row in FourierTransformHalf
1106  {
1107  pointer_2d.push_back(i*XSIZE(Maux) + j);
1108  pointer_i.push_back(i);
1109  pointer_j.push_back(j);
1110  nr_points_2d++;
1111  }
1112  }
1114 
1115  if (debug>0)
1116  {
1117  std::cerr<<"nr_points_2d= "<<nr_points_2d<<" nr_points_prob= "<<nr_points_prob<<std::endl;
1118  }
1119 
1120  // For variable in-plane sampling rates
1121  setCurrentSamplingRates(sampling*dim/current_probres_limit);
1122 
1123 }
1124 
1125 
1126 // Vary psi_step and trans_step with resolution =============================================
1127 void ProgMLF2D::setCurrentSamplingRates(double current_probres_limit)
1128 {
1129 
1130  int trans_step = 1;
1131 
1132  if (do_variable_psi)
1133  {
1134  // Sample the in-plane rotations 3x the current resolution
1135  // Note that SIND(0.5*psi_step) = Delta / dim;
1136  psi_step = (2.* ASIND(current_probres_limit/(dim*sampling))) / 3.;
1137  nr_psi = CEIL(psi_max / psi_step);
1138  // Use user-provided psi_step as minimum sampling
1140  psi_step = psi_max / nr_psi;
1141  }
1142 
1143  if (do_variable_trans)
1144  {
1145  Matrix1D<double> offsets(2);
1146  nr_trans = 0;
1147  Vtrans.clear();
1148  // Sample the in-plane translations 3x the current resolution
1149  trans_step = ROUND(current_probres_limit/(3.*sampling));
1150  // Use trans_step=1 as minimum sampling
1151  trans_step = XMIPP_MAX(1,trans_step);
1152  for (int ix = -search_shift*trans_step; ix <= search_shift*trans_step; ix+=trans_step)
1153  {
1154  for (int iy = -search_shift*trans_step; iy <= search_shift*trans_step; iy+=trans_step)
1155  {
1156  double rr = sqrt((double)(ix * ix + iy * iy));
1157  if (rr <= (double)trans_step*search_shift)
1158  {
1159  XX(offsets) = ix;
1160  YY(offsets) = iy;
1161  Vtrans.push_back(offsets);
1162  nr_trans++;
1163  if (ix == 0 && iy == 0)
1164  {
1165  zero_trans = nr_trans;
1166  // For coarser samplings, always add (-1,0) (1,0) (0,-1) and (0,1)
1167  if (trans_step > 1)
1168  {
1169  XX(offsets) = 1;
1170  YY(offsets) = 0;
1171  Vtrans.push_back(offsets);
1172  nr_trans++;
1173  XX(offsets) = -1;
1174  YY(offsets) = 0;
1175  Vtrans.push_back(offsets);
1176  nr_trans++;
1177  XX(offsets) = 0;
1178  YY(offsets) = 1;
1179  Vtrans.push_back(offsets);
1180  nr_trans++;
1181  XX(offsets) = 0;
1182  YY(offsets) = -1;
1183  Vtrans.push_back(offsets);
1184  nr_trans++;
1185  }
1186  }
1187  }
1188  }
1189  }
1190  }
1191  if (verbose > 0 && (do_variable_psi || do_variable_trans))
1192  {
1193  std::cout<<" Current resolution= "<<current_probres_limit<<" Ang; current psi_step = "<<psi_step<<" current trans_step = "<<trans_step<<std::endl;
1194 
1195  }
1196 }
1197 
1198 // Generate initial references =============================================
1200 {
1201 
1202  if (verbose > 0)
1203  {
1204  std::cout << " Generating initial references by averaging over random subsets" << std::endl;
1206  }
1207 
1208  Image<double> IRef, ITemp;
1209  FileName fn_tmp;
1210  FileName fn_base = getIterExtraPath(fn_root, 0);
1211 
1212  //randomizeImagesOrder();
1213 
1214  MDref.clear();
1215  size_t nsub, first, last;
1216  size_t id;
1217 
1218  for (int refno = 0; refno < model.n_ref; refno++)
1219  {
1220  nsub = divide_equally(nr_images_global, model.n_ref, refno, first, last);
1221  //Clear images
1222  IRef().initZeros(dim, dim);
1223  IRef().setXmippOrigin();
1224 
1225  for (size_t imgno = first; imgno <= last; imgno++)
1226  {
1227  MDimg.getValue(MDL_IMAGE, fn_tmp, img_id[imgno]);
1228  ITemp.read(fn_tmp);
1229  ITemp().setXmippOrigin();
1230  IRef() += ITemp();
1231  }
1232 
1233  fn_tmp = FN_REF(fn_base, refno + 1);
1234 
1235  IRef() /= nsub;
1236  IRef.write(fn_tmp);
1237  id = MDref.addObject();
1238  MDref.setValue(MDL_IMAGE, fn_tmp, id);
1239  MDref.setValue(MDL_ENABLED, 1, id);
1240 
1241  if (verbose > 0)
1242  progress_bar(refno);
1243  }//close for refno
1244 
1245  if (verbose > 0)
1247 
1248  fn_ref = FN_CLASSES_MD(fn_base);
1249  MDref.write(fn_ref);
1250 }
1251 
1252 
1253 // Calculate probability density function of all in-plane transformations phi
1255 {
1256 
1257  double r2, pdfpix, sum;
1258  P_phi.resize(dim, dim);
1260  Mr2.resize(dim, dim);
1261  Mr2.setXmippOrigin();
1262 
1263  sum=0.;
1265  {
1266  r2 = (double)(j * j + i * i);
1267  if (sigma_offset > 0.)
1268  {
1269  pdfpix = exp(-r2 / (2 * sigma_offset * sigma_offset));
1270  pdfpix /= 2 * PI * sigma_offset * sigma_offset * nr_psi * nr_nomirror_flips;
1271  }
1272  else
1273  {
1274  if (j == 0 && i == 0)
1275  pdfpix = 1.;
1276  else
1277  pdfpix = 0.;
1278  }
1279  A2D_ELEM(P_phi, i, j) = pdfpix;
1280  A2D_ELEM(Mr2, i, j) = (float)r2;
1281  sum+=pdfpix;
1282  }
1283  // Normalization
1284  P_phi/=sum;
1285 
1286 }
1287 
1288 void ProgMLF2D::appendFTtoVector(const MultidimArray<std::complex<double> > &in,
1289  std::vector<double> &out)
1290 {
1291 
1292  // First, store the points used in the probability calculations
1293  std::complex<double> * tmp_in = MULTIDIM_ARRAY(in);
1294  for (size_t ipoint = 0; ipoint < nr_points_2d; ipoint++)
1295  {
1296  int ii = pointer_2d[ipoint];
1297  out.push_back(tmp_in[ii].real());
1298  out.push_back(tmp_in[ii].imag());
1299  }
1300 }
1301 
1302 void ProgMLF2D::getFTfromVector(const std::vector<double> &in,
1303  const int start_point,
1304  MultidimArray<std::complex<double> > &out,
1305  bool only_real)
1306 {
1307 
1308  out.resize(hdim + 1, dim);
1309  out.initZeros();
1310  std::complex<double> * tmp_out = MULTIDIM_ARRAY(out);
1311  if (only_real)
1312  {
1313  for (size_t ipoint = 0; ipoint < nr_points_2d; ipoint++)
1314  {
1315  int ii = pointer_2d[ipoint];
1316  std::complex<double> aux(in[start_point+ipoint], 0.);
1317  tmp_out[ii] = aux;
1318  }
1319  }
1320  else
1321  {
1322  for (size_t ipoint = 0; ipoint < nr_points_2d; ipoint++)
1323  {
1324  int ii = pointer_2d[ipoint];
1325  std::complex<double> aux(in[start_point+2*ipoint],in[start_point+2*ipoint+1]);
1326  tmp_out[ii] = aux;
1327  }
1328  }
1329 
1330 
1331 }
1332 
1333 // Rotate reference for all models and rotations and fill Fref vectors =============
1334 void ProgMLF2D::rotateReference(std::vector<double> &out)
1335 {
1336  out.clear();
1337 
1338  double AA, stdAA, psi;
1339  MultidimArray<double> Maux;
1341 
1342  Maux.initZeros(dim, dim);
1343  Maux.setXmippOrigin();
1344 
1345  FOR_ALL_MODELS()
1346  {
1348  {
1349  // Add arbitrary number (small_angle) to avoid 0-degree rotation (lacking interpolation)
1350  psi = (double)(ipsi * psi_max / nr_psi) + SMALLANGLE;
1351  //model.Iref[refno]().rotateBSpline(3, psi, Maux, WRAP);
1352  rotate(xmipp_transformation::BSPLINE3, Maux, model.Iref[refno](), -psi, 'Z', xmipp_transformation::WRAP);
1353  FourierTransformHalf(Maux, Faux);
1354 
1355  // Normalize the magnitude of the rotated references to 1st rot of that ref
1356  // This is necessary because interpolation due to rotation can lead to lower overall Fref
1357  // This would result in lower probabilities for those rotations
1358  AA = Maux.sum2();
1359  if (ipsi == 0)
1360  {
1361  stdAA = AA;
1362  }
1363  if (AA > 0)
1364  {
1365  double sqrtVal = sqrt(stdAA/AA);
1367  dAi(Faux, n) *= sqrtVal;
1368  }
1369  // Add all points as doubles to the vector
1370  appendFTtoVector(Faux, out);
1371  }
1372  // Free memory
1373  model.Iref[refno]().resize(0,0);
1374  }
1375 }
1376 
1377 
1378 // Collect all rotations and sum to update Iref() for all models ==========
1379 void ProgMLF2D::reverseRotateReference(const std::vector<double> &in,
1380  std::vector<MultidimArray<double > > &out)
1381 {
1382 
1383  double psi;
1384  MultidimArray<double> Maux, Maux2;
1386  Maux.resize(dim, dim);
1387  Maux2.resize(dim, dim);
1388  Maux.setXmippOrigin();
1389  Maux2.setXmippOrigin();
1390 
1391  out.clear();
1392  FOR_ALL_MODELS()
1393  {
1394  Maux.initZeros();
1395  out.push_back(Maux);
1397  {
1398  // Add arbitrary number to avoid 0-degree rotation without interpolation effects
1399  psi = (double)(ipsi * psi_max / nr_psi) + SMALLANGLE;
1400  getFTfromVector(in, refno*nr_psi*dnr_points_2d + ipsi*dnr_points_2d, Faux);
1401  InverseFourierTransformHalf(Faux, Maux, dim);
1402  //Maux.rotateBSpline(3, -psi, Maux2, WRAP);
1403  rotate(xmipp_transformation::BSPLINE3, Maux2, Maux, psi, 'Z', xmipp_transformation::WRAP);
1404  out[refno] += Maux2;
1405  }
1406  }
1407 
1408 }
1409 
1410 void ProgMLF2D::preselectDirections(float &phi, float &theta,
1411  std::vector<double> &pdf_directions)
1412 {
1413 
1414  float phi_ref, theta_ref, angle, angle2;
1415  Matrix1D<double> u, v;
1416 
1417  pdf_directions.clear();
1418  pdf_directions.resize(model.n_ref);
1419  FOR_ALL_MODELS()
1420  {
1421  if (!limit_rot || (phi == -999. && theta == -999.))
1422  pdf_directions[refno] = 1.;
1423  else
1424  {
1425  phi_ref = model.Iref[refno].rot();
1426  theta_ref = model.Iref[refno].tilt();
1427  Euler_direction(phi, theta, 0., u);
1428  Euler_direction(phi_ref, theta_ref, 0., v);
1429  u.selfNormalize();
1430  v.selfNormalize();
1431  angle = RAD2DEG(acos(dotProduct(u, v)));
1432  angle = fabs(realWRAP(angle, -180, 180));
1433  // also check mirror
1434  angle2 = 180. + angle;
1435  angle2 = fabs(realWRAP(angle2, -180, 180));
1436  angle = XMIPP_MIN(angle, angle2);
1437  if (fabs(angle) > search_rot)
1438  pdf_directions[refno] = 0.;
1439  else
1440  pdf_directions[refno] = 1.;
1441  }
1442  }
1443 }
1444 
1445 void ProgMLF2D::fourierTranslate2D(const std::vector<double> &in,
1446  MultidimArray<double> &trans,
1447  std::vector<double> &out,
1448  int point_start)
1449 {
1450  double xx, yy, xxshift, yyshift, dotp;
1451  double a, b, c, d, ac, bd, ab_cd;
1452  xxshift = -trans(0) / (double)dim;
1453  yyshift = -trans(1) / (double)dim;
1454  //Not very clean, but very fast
1455  const double * ptrIn = &(in[point_start]);
1456  int * ptrJ = &(pointer_j[0]);
1457  int * ptrI = &(pointer_i[0]);
1458 
1459  for (size_t i = 0; i < nr_points_2d; i++)
1460  {
1461  xx = (double)ptrJ[i];
1462  yy = (double)ptrI[i];
1463  dotp = 2 * PI * (xx * xxshift + yyshift * yy);
1464  a = cos(dotp);
1465  b = sin(dotp);
1466  c = *ptrIn++;//in[point_start + 2*i];
1467  d = *ptrIn++;//in[point_start + 2*i+1];
1468  ac = a * c;
1469  bd = b * d;
1470  ab_cd = (a + b) * (c + d);
1471  out.push_back(ac - bd); // real
1472  out.push_back(ab_cd - ac - bd); // imag
1473  //*ptrOut = ac - bd; ++ptrOut;// real
1474  //*ptrOut = ab_cd - ac - bd; ++ptrOut;// imag
1475  }
1476 
1477 }
1478 
1480  const std::vector<double > &offsets,
1481  std::vector<double> &out,
1482  MultidimArray<int> &Moffsets,
1483  MultidimArray<int> &Moffsets_mirror)
1484 {
1485 
1486  int irefmir, ix, iy, iflip_start, iflip_stop, count;
1487  int nr_mir = (do_mirror) ? 2 : 1;
1488 
1489  double dxx, dyy;
1490  std::vector<double> Fimg_flip;
1492  MultidimArray<double> trans(2);
1493  MultidimArray<double> Maux2, Maux;
1494 
1495  Moffsets.resize(dim, dim);
1496  Moffsets.setXmippOrigin();
1497  Moffsets.initConstant(-1);
1498  Moffsets_mirror.resize(dim, dim);
1499  Moffsets_mirror.setXmippOrigin();
1500  Moffsets_mirror.initConstant(-1);
1501  Maux.resize(dim, dim);
1502  Maux.setXmippOrigin();
1503  Maux2.resize(dim, dim);
1504  Maux2.setXmippOrigin();
1505 
1506  // Flip images and store the precalculates Fourier Transforms in Fimg_flip
1507  out.clear();
1508  FOR_ALL_FLIPS()
1509  {
1510  Maux.setXmippOrigin();
1511  applyGeometry(xmipp_transformation::LINEAR, Maux, Mimg, F[iflip], xmipp_transformation::IS_INV, xmipp_transformation::WRAP);
1512 
1513  FourierTransformHalf(Maux, Fimg);
1514  appendFTtoVector(Fimg,Fimg_flip);
1515  }
1516 
1517  // Now for all relevant offsets calculate the Fourier transforms
1518  // Matrices Moffsets & Moffsets_mirror contain pointers for the
1519  // out vector (access as count*4*dnr_points_2d + iflip*dnr_points_2d)
1520  count = 0;
1521  FOR_ALL_MODELS()
1522  {
1523  for (int imir = 0; imir < nr_mir; imir++)
1524  {
1525  irefmir = imir * model.n_ref + refno;
1526  iflip_start = imir * nr_nomirror_flips;
1527  iflip_stop = imir * nr_nomirror_flips + nr_nomirror_flips;
1529  {
1530  ix = ROUND(offsets[2*irefmir] + Vtrans[itrans](0));
1531  iy = ROUND(offsets[2*irefmir+1] + Vtrans[itrans](1));
1532  dxx = (double)intWRAP(ix, Moffsets.startingX(), Moffsets.finishingX());
1533  dyy = (double)intWRAP(iy, Moffsets.startingY(), Moffsets.finishingY());
1534  // For non-mirrors
1535  if (imir == 0 && A2D_ELEM(Moffsets, ROUND(dyy), ROUND(dxx)) < 0)
1536  {
1537  for (int iflip = iflip_start; iflip < iflip_stop; iflip++)
1538  {
1539  Matrix2D<double> & refF_iflip = F[iflip];
1540  dAi(trans, 0) = dxx * MAT_ELEM(refF_iflip, 0, 0) + dyy * MAT_ELEM(refF_iflip, 0, 1);
1541  dAi(trans, 1) = dxx * MAT_ELEM(refF_iflip, 1, 0) + dyy * MAT_ELEM(refF_iflip, 1, 1);
1542  fourierTranslate2D(Fimg_flip,trans,out,iflip*dnr_points_2d);
1543  }
1544  A2D_ELEM(Moffsets, ROUND(dyy), ROUND(dxx)) = count;
1545  count++;
1546  }
1547  // For mirrors use a separate offset-matrix
1548  else if (imir == 1 && A2D_ELEM(Moffsets_mirror, ROUND(dyy), ROUND(dxx)) < 0)
1549  {
1550  for (int iflip = iflip_start; iflip < iflip_stop; iflip++)
1551  {
1552  Matrix2D<double> & refF_iflip = F[iflip];
1553  dAi(trans, 0) = dxx * MAT_ELEM(refF_iflip, 0, 0) + dyy * MAT_ELEM(refF_iflip, 0, 1);
1554  dAi(trans, 1) = dxx * MAT_ELEM(refF_iflip, 1, 0) + dyy * MAT_ELEM(refF_iflip, 1, 1);
1555  fourierTranslate2D(Fimg_flip,trans,out,iflip*dnr_points_2d);
1556  }
1557  A2D_ELEM(Moffsets_mirror, ROUND(dyy), ROUND(dxx)) = count;
1558  count++;
1559  }
1560  }
1561  }
1562  }
1563 }
1564 
1565 double lcdf_tstudent_mlf1(double t)
1566 {
1567  return cdf_tstudent(1,t);
1568 }
1569 double lcdf_tstudent_mlf3(double t)
1570 {
1571  return cdf_tstudent(3,t);
1572 }
1573 double lcdf_tstudent_mlf6(double t)
1574 {
1575  return cdf_tstudent(6,t);
1576 }
1577 double lcdf_tstudent_mlf9(double t)
1578 {
1579  return cdf_tstudent(9,t);
1580 }
1581 double lcdf_tstudent_mlf30(double t)
1582 {
1583  return cdf_tstudent(30,t);
1584 }
1585 
1586 
1587 // Exclude translations from the MLF_integration
1588 // For significantly contributing refno+psi: re-calculate optimal shifts
1590  const size_t focus, bool apply_ctf,
1591  double &fracweight, double &maxweight2,
1592  double &sum_refw2, double &opt_scale,
1593  size_t &opt_refno, double &opt_psi,
1594  size_t &opt_ipsi, size_t &opt_iflip,
1595  MultidimArray<double> &opt_offsets,
1596  std::vector<double> &opt_offsets_ref,
1597  std::vector<double > &pdf_directions,
1598  bool do_kstest, bool write_histograms,
1599  FileName fn_img, double &KSprob)
1600 {
1601  std::vector<double> &Mwsum_sigma2_local = Mwsum_sigma2[focus];
1602  MultidimArray<double> Mweight;
1603  MultidimArray<int> Moffsets, Moffsets_mirror;
1604  std::vector<double> Fimg_trans;
1605  std::vector<MultidimArray<double> > uniq_offsets;
1606 
1607 
1608  std::vector<double> refw(model.n_ref), refw2(model.n_ref), refw_mirror(model.n_ref), Pmax_refmir(2*model.n_ref);
1609 
1610  double aux, fracpdf, weight, weight2=0.;
1611  double tmpr, tmpi, sum_refw = 0.;
1612  double diff, maxweight = -99.e99, mindiff2 = 99.e99;
1613  double logsigma2, ldim, ref_scale = 1.;
1614  double scale_denom, scale_numer, wsum_sc = 0., wsum_sc2 = 0.;
1615  int irot, irefmir, opt_irefmir=0, ix, iy;
1616  size_t point_trans=0;
1617  int opt_itrans=0, iflip_start, iflip_stop, nr_mir;
1618  int img_start, ref_start, wsum_start;
1619 
1620  if (!do_norm)
1621  opt_scale =1.;
1622 
1623  // Convert 1D Vsig vectors to the correct vector size for the 2D FTHalfs
1624  // Multiply by a factor of two because we consider both the real and the imaginary parts
1625  ldim = (double) 2 * nr_points_prob;
1626  // For t-student: df2 changes with effective resolution!
1627  if (do_student)
1628  df2 = - ( df + ldim ) / 2. ;
1629 
1630  sum_refw2 = 0.;
1631  //change std::vectors by arrays
1632  auto *sigma2=new double[nr_points_2d];
1633  auto *inv_sigma2=new double [nr_points_2d];
1634  auto *ctf=new double[nr_points_2d];
1635  auto *decctf=new double[nr_points_2d];
1636 
1637  const int &ifocus = focus;
1638  FOR_ALL_POINTS()
1639  {
1640  int irr = DIRECT_MULTIDIM_ELEM(Mresol_int,pointer_2d[ipoint]);
1641  sigma2[ipoint] = 2. * VSIG_ITEM;
1642  inv_sigma2[ipoint] = 1./ sigma2[ipoint];
1643  decctf[ipoint] = VDEC_ITEM;
1644  ctf[ipoint] = VCTF_ITEM;
1645  }
1646 
1647  if (!apply_ctf)
1648  {
1649  FOR_ALL_POINTS()
1650  ctf[ipoint] = 1.;
1651  }
1652 
1653  // Precalculate normalization constant
1654  logsigma2 = 0.;
1655  double factor = do_student ? PI * df * 0.5 : PI;
1656  // Multiply by two because we treat real and imaginary parts!
1657  for (size_t ipoint = 0; ipoint < nr_points_prob; ipoint++)
1658  logsigma2 += 2 * log( sqrt(factor * sigma2[ipoint]));
1659 
1660  // Precalculate Fimg_trans, on pruned and expanded offset list
1661  calculateFourierOffsets(Mimg, opt_offsets_ref, Fimg_trans, Moffsets, Moffsets_mirror);
1662 
1664 
1665  FOR_ALL_MODELS()
1666  {
1667  if (!limit_rot || pdf_directions[refno] > 0.)
1668  {
1669  if (do_norm)
1670  ref_scale = opt_scale / refs_avgscale[refno];
1671 
1672  FOR_ALL_FLIPS()
1673  {
1674  irefmir = (int)floor(iflip / nr_nomirror_flips) * model.n_ref + refno;
1675  ix = (int)round(opt_offsets_ref[2*irefmir]);
1676  iy = (int)round(opt_offsets_ref[2*irefmir+1]);
1677  Pmax_refmir[irefmir] = 0.;
1678  point_trans = (iflip < nr_nomirror_flips) ? A2D_ELEM(Moffsets, iy, ix) : A2D_ELEM(Moffsets_mirror, iy, ix);
1679  if (point_trans < 0 || point_trans > dim2)
1680  {
1681  std::cerr<<"point_trans = "<<point_trans<<" ix= "<<ix<<" iy= "<<iy<<std::endl;
1682  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS,"mlf_align2d BUG: point_trans < 0");
1683  }
1684 
1685  fracpdf = (iflip < nr_nomirror_flips) ? 1. - mirror_fraction[refno] : mirror_fraction[refno];
1686  // get the starting point in the Fimg_trans vector
1687  img_start = point_trans*4*dnr_points_2d + (iflip%nr_nomirror_flips)*dnr_points_2d;
1688 
1690  {
1691  irot = iflip * nr_psi + ipsi;
1692  diff = 0.;
1693  // get the starting point in the Fref vector
1694  ref_start = refno * nr_psi * dnr_points_2d + ipsi * dnr_points_2d;
1695  if (do_ctf_correction)
1696  {
1697  for (size_t ii = 0; ii < nr_points_prob; ii++)
1698  {
1699  tmpr = Fimg_trans[img_start + 2*ii] - ctf[ii] * ref_scale * Fref[ref_start + 2*ii];
1700  tmpi = Fimg_trans[img_start + 2*ii+1] - ctf[ii] * ref_scale * Fref[ref_start + 2*ii+1];
1701  tmpr = (tmpr * tmpr + tmpi * tmpi) * inv_sigma2[ii];
1702  diff += tmpr;
1703  }
1704  }
1705  else
1706  {
1707  for (size_t ii = 0; ii < nr_points_prob; ii++)
1708  {
1709  tmpr = Fimg_trans[img_start + 2*ii] - ref_scale * Fref[ref_start + 2*ii];
1710  tmpi = Fimg_trans[img_start + 2*ii+1] - ref_scale * Fref[ref_start + 2*ii+1];
1711  diff += (tmpr * tmpr + tmpi * tmpi) * inv_sigma2[ii];
1712  }
1713 
1714  }
1715  // Multiply by two for t-student, because we divided by 2*sigma2 instead of sigma2!
1716  if (do_student)
1717  diff *= 2.;
1718  dAkij(Mweight, zero_trans, refno, irot) = diff;
1719  if (debug == 9)
1720  {
1721  std::cerr<<"refno= "<<refno<<" irot= "<<irot<<" diff= "<<diff<<" mindiff2= "<<mindiff2<<std::endl;
1722  }
1723  if (diff < mindiff2)
1724  {
1725  mindiff2 = diff;
1726  opt_refno = refno;
1727  opt_ipsi = ipsi;
1728  opt_iflip = iflip;
1729  opt_itrans = zero_trans;
1730  opt_irefmir = irefmir;
1731  }
1732  }
1733  }
1734  }
1735  if (debug == 9)
1736  {
1737  std::cerr<<">>>>> mindiff2= "<<mindiff2<<std::endl;
1738  exit(1);
1739  }
1740 
1741  }
1742 
1743  // Now that we have mindiff2 calculate all weights and maxweight
1744  FOR_ALL_MODELS()
1745  {
1746  if (!limit_rot || pdf_directions[refno] > 0.)
1747  {
1748  refw[refno] = 0.;
1749  refw_mirror[refno] = 0.;
1750 
1751  FOR_ALL_FLIPS()
1752  {
1753  irefmir = (int)floor(iflip / nr_nomirror_flips) * model.n_ref + refno;
1754  ix = (int)round(opt_offsets_ref[2*irefmir]);
1755  iy = (int)round(opt_offsets_ref[2*irefmir+1]);
1756  fracpdf = (iflip < nr_nomirror_flips) ? 1. - mirror_fraction[refno] : mirror_fraction[refno];
1757  double pdf = alpha_k[refno] * fracpdf * A2D_ELEM(P_phi, iy, ix);
1758  // get the starting point in the Fimg_trans vector
1759  img_start = point_trans*4*dnr_points_2d + (iflip%nr_nomirror_flips)*dnr_points_2d;
1760 
1762  {
1763  irot = iflip * nr_psi + ipsi;
1764  diff = dAkij(Mweight, zero_trans, refno, irot);
1765  // get the starting point in the Fref vector
1766  ref_start = refno*nr_psi*dnr_points_2d + ipsi*dnr_points_2d;
1767  if (!do_student)
1768  {
1769  // normal distribution
1770  aux = diff - mindiff2;
1771  // next line because of numerical precision of exp-function
1772  if (aux > 100.)
1773  weight = 0.;
1774  else
1775  weight = exp(-aux) * pdf;
1776  // Store weight
1777  dAkij(Mweight, zero_trans, refno, irot) = weight;
1778  }
1779  else
1780  {
1781  // t-student distribution
1782  // pdf = (1 + diff2/df)^df2
1783  // Correcting for mindiff2:
1784  // pdfc = (1 + diff2/df)^df2 / (1 + mindiff2/df)^df2
1785  // = ( (1 + diff2/df)/(1 + mindiff2/df) )^df2
1786  // = ( (df + diff2) / (df + mindiff2) )^df2
1787  // Extra factor two because we saved diff = | X - A |^2 / TWO * sigma
1788  aux = (df + diff) / (df + mindiff2);
1789  weight = pow(aux, df2) * pdf;
1790  // Calculate extra weight acc. to Eq (10) Wang et al.
1791  // Patt. Recognition Lett. 25, 701-710 (2004)
1792  weight2 = ( df + ldim ) / ( df + diff );
1793  // Store probability weights
1794  dAkij(Mweight, zero_trans, refno, irot) = weight * weight2;
1795  refw2[refno] += weight * weight2;
1796  sum_refw2 += weight * weight2;
1797  }
1798  // Accumulate sum weights
1799  if (iflip < nr_nomirror_flips)
1800  refw[refno] += weight;
1801  else
1802  refw_mirror[refno] += weight;
1803  sum_refw += weight;
1804  //std::cerr << "DEBUG_JM: refno << iflip << ipsi: " << refno << " " << iflip << " " << ipsi << std::endl;
1805  //std::cerr << "DEBUG_JM: weight: " << weight << " sum_refw: " << sum_refw << std::endl;
1806 
1807  if (do_norm)
1808  {
1809  scale_numer = 0.;
1810  scale_denom = 0.;
1811  if (do_ctf_correction)
1812  {
1813  // NOTE: scale_denom could be precalculated in
1814  // a much cheaper way!!!!
1815  for (size_t ii = 0; ii < nr_points_prob; ii++)
1816  {
1817  scale_numer += Fimg_trans[img_start + 2*ii] * ctf[ii] * Fref[ref_start + 2*ii];
1818  scale_numer += Fimg_trans[img_start + 2*ii+1] * ctf[ii] * Fref[ref_start + 2*ii+1];
1819  scale_denom += ctf[ii] * Fref[ref_start + 2*ii] * ctf[ii] * Fref[ref_start + 2*ii];
1820  scale_denom += ctf[ii] * Fref[ref_start + 2*ii+1] * ctf[ii] * Fref[ref_start + 2*ii+1];
1821  }
1822  }
1823  else
1824  {
1825  for (size_t ii = 0; ii < nr_points_prob; ii++)
1826  {
1827  scale_numer += Fimg_trans[img_start + 2*ii] * Fref[ref_start + 2*ii];
1828  scale_numer += Fimg_trans[img_start + 2*ii+1] * Fref[ref_start + 2*ii+1];
1829  scale_denom += Fref[ref_start + 2*ii] * Fref[ref_start + 2*ii];
1830  scale_denom += Fref[ref_start + 2*ii+1] * Fref[ref_start + 2*ii+1];
1831  }
1832  }
1833  wsum_sc += dAkij(Mweight, zero_trans, refno, irot) * scale_numer;
1834  wsum_sc2 += dAkij(Mweight, zero_trans, refno, irot) * scale_denom;
1835  }
1836  if (weight > Pmax_refmir[irefmir])
1837  Pmax_refmir[irefmir] = weight;
1838  if (weight > maxweight)
1839  {
1840  maxweight = weight;
1841  if (do_student)
1842  maxweight2 = weight2;
1843  opt_refno = refno;
1844  opt_ipsi = ipsi;
1845  opt_iflip = iflip;
1846  opt_itrans = zero_trans;
1847  opt_irefmir = irefmir;
1848  }
1849  }
1850  }
1851  }
1852  }
1853 
1854  //std::cerr << "DEBUG_JM: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" <<std::endl;
1855  // Now for all irefmir, check significant rotations...
1856  // and calculate their limited_translations probabilities
1857  FOR_ALL_MODELS()
1858  {
1859  if (!limit_rot || pdf_directions[refno] > 0.)
1860  {
1861  if (do_norm)
1862  ref_scale = opt_scale / refs_avgscale[refno];
1863  FOR_ALL_FLIPS()
1864  {
1865  irefmir = (int)floor(iflip / nr_nomirror_flips) * model.n_ref + refno;
1866  fracpdf = (iflip < nr_nomirror_flips) ? 1. - mirror_fraction[refno] : mirror_fraction[refno];
1867 
1869  {
1870  irot = iflip * nr_psi + ipsi;
1871  // Note that for t-students distribution we now do something
1872  // a little bit different compared to ML_integrate_complete!
1873  // Instead of comparing "weight", we compare "weight*weight2"!!
1874  if (dAkij(Mweight, zero_trans, refno, irot) > C_fast*Pmax_refmir[irefmir])
1875  {
1876  // get the starting point in the Fref vector
1877  ref_start = refno*nr_psi*dnr_points_2d + ipsi*dnr_points_2d;
1878  // expand for all limited translations
1880  {
1881  if (itrans != zero_trans)
1882  { // zero_trans has already been calculated!
1883  ix = (int)round(opt_offsets_ref[2*irefmir] + Vtrans[itrans](0));
1884  iy = (int)round(opt_offsets_ref[2*irefmir+1] + Vtrans[itrans](1));
1885  ix = intWRAP(ix, Moffsets.startingX(), Moffsets.finishingX());
1886  iy = intWRAP(iy, Moffsets.startingY(), Moffsets.finishingY());
1887  if (iflip < nr_nomirror_flips)
1888  point_trans = A2D_ELEM(Moffsets, iy, ix);
1889  else
1890  point_trans = A2D_ELEM(Moffsets_mirror, iy, ix);
1891  if (point_trans < 0 || point_trans > dim2)
1892  {
1893  std::cerr<<"point_trans = "<<point_trans<<" ix= "<<ix<<" iy= "<<iy<<std::endl;
1894  REPORT_ERROR(ERR_INDEX_OUTOFBOUNDS,"mlf_align2d BUG: point_trans < 0 or > dim2");
1895  }
1896  double pdf = alpha_k[refno] * fracpdf * A2D_ELEM(P_phi, iy, ix);
1897  if (pdf > 0)
1898  {
1899  // get the starting point in the Fimg_trans vector
1900  img_start = point_trans*4*dnr_points_2d + (iflip%nr_nomirror_flips)*dnr_points_2d;
1901  diff = 0.;
1902  if (do_ctf_correction)
1903  {
1904  for (size_t ii = 0; ii < nr_points_prob; ii++)
1905  {
1906  tmpr = Fimg_trans[img_start + 2*ii] - ctf[ii] * ref_scale * Fref[ref_start + 2*ii];
1907  tmpi = Fimg_trans[img_start + 2*ii+1] - ctf[ii] * ref_scale * Fref[ref_start + 2*ii+1];
1908  diff += (tmpr * tmpr + tmpi * tmpi) * inv_sigma2[ii];
1909  }
1910  }
1911  else
1912  {
1913  for (size_t ii = 0; ii < nr_points_prob; ii++)
1914  {
1915  tmpr = Fimg_trans[img_start + 2*ii] - ref_scale * Fref[ref_start + 2*ii];
1916  tmpi = Fimg_trans[img_start + 2*ii+1] - ref_scale * Fref[ref_start + 2*ii+1];
1917  diff += (tmpr * tmpr + tmpi * tmpi) * inv_sigma2[ii];
1918  }
1919  }
1920  if (!do_student)
1921  {
1922  // Normal distribution
1923  aux = diff - mindiff2;
1924 
1925  //FIXME: In this second loop the mindiff2 is not really the
1926  //minimum diff, that's why sometimes aux is less than zero
1927  //causing exponential to go inf, for now setting weight to zero
1928 
1929  // next line because of numerical precision of exp-function
1930  if (aux > 100. || aux < 0)
1931  weight = 0.;
1932  else
1933  weight = exp(-aux) * pdf;
1934  // Store weight
1935  dAkij(Mweight, itrans, refno, irot) = weight;
1936  }
1937  else
1938  {
1939  // t-student distribution
1940  // now diff2 and mindiff2 are already divided by sigma2!!
1941  // pdf = (1 + diff2/df)^df2
1942  // Correcting for mindiff2:
1943  // pdfc = (1 + diff2/df)^df2 / (1 + mindiff2/df)^df2
1944  // = ( (1 + diff2/df)/(1 + mindiff2/df) )^df2
1945  // = ( (df + diff2) / (df + mindiff2) )^df2
1946  // Multiply by two for t-student, because we divided by 2*sigma2
1947  diff *= 2.;
1948  // Extra factor two because we saved diff = | X - A |^2 / TWO * sigma
1949  aux = (df + diff) / (df + mindiff2);
1950  weight = pow(aux, df2) * pdf;
1951  // Calculate extra weight acc. to Eq (10) Wang et al.
1952  // Patt. Recognition Lett. 25, 701-710 (2004)
1953  weight2 = ( df + ldim ) / ( df + diff);
1954  // Store probability weights
1955  dAkij(Mweight, itrans, refno, irot) = weight * weight2;
1956  refw2[refno] += weight * weight2;
1957  sum_refw2 += weight * weight2;
1958  }
1959  // Accumulate sum weights
1960  if (iflip < nr_nomirror_flips)
1961  refw[refno] += weight;
1962  else
1963  refw_mirror[refno] += weight;
1964  sum_refw += weight;
1965 
1966  if (do_norm)
1967  {
1968  scale_numer = 0.;
1969  scale_denom = 0.;
1970  if (do_ctf_correction)
1971  {
1972  // NOTE: scale_denom could be precalculated in
1973  // a much cheaper way!!!!
1974  for (size_t ii = 0; ii < nr_points_prob; ii++)
1975  {
1976  scale_numer += Fimg_trans[img_start + 2*ii]
1977  * ctf[ii] * Fref[ref_start + 2*ii];
1978  scale_numer += Fimg_trans[img_start + 2*ii+1]
1979  * ctf[ii] * Fref[ref_start + 2*ii+1];
1980  scale_denom += ctf[ii] * Fref[ref_start + 2*ii]
1981  * ctf[ii] * Fref[ref_start + 2*ii];
1982  scale_denom += ctf[ii] * Fref[ref_start + 2*ii+1]
1983  * ctf[ii] * Fref[ref_start + 2*ii+1];
1984  }
1985  }
1986  else
1987  {
1988  for (size_t ii = 0; ii < nr_points_prob; ii++)
1989  {
1990  scale_numer += Fimg_trans[img_start + 2*ii]
1991  * Fref[ref_start + 2*ii];
1992  scale_numer += Fimg_trans[img_start + 2*ii+1]
1993  * Fref[ref_start + 2*ii+1];
1994  scale_denom += Fref[ref_start + 2*ii]
1995  * Fref[ref_start + 2*ii];
1996  scale_denom += Fref[ref_start + 2*ii+1]
1997  * Fref[ref_start + 2*ii+1];
1998  }
1999  }
2000  wsum_sc += dAkij(Mweight, itrans, refno, irot) * scale_numer;
2001  wsum_sc2 += dAkij(Mweight, itrans, refno, irot) * scale_denom;
2002  }
2003  if (weight > maxweight)
2004  {
2005  maxweight = weight;
2006  if (do_student)
2007  maxweight2 = weight2;
2008  opt_refno = refno;
2009  opt_ipsi = ipsi;
2010  opt_iflip = iflip;
2011  opt_itrans = itrans;
2012  opt_irefmir = irefmir;
2013  }
2014  }
2015  else
2016  dAkij(Mweight, itrans, refno, irot) = 0.;
2017  }
2018  }
2019  }
2020  }
2021  }
2022  }
2023  }
2024 
2025  // Update optimal offsets
2026  opt_offsets(0) = opt_offsets_ref[2*opt_irefmir] + Vtrans[opt_itrans](0);
2027  opt_offsets(1) = opt_offsets_ref[2*opt_irefmir+1] + Vtrans[opt_itrans](1);
2028  opt_psi = -psi_step * (opt_iflip * nr_psi + opt_ipsi) - SMALLANGLE;
2029 
2030  // Perform KS-test on difference image of optimal hidden parameters
2031  // And calculate noise distribution histograms
2032  if (do_kstest)
2033  {
2034  MultidimArray<double> diff(2*nr_points_prob);
2035  std::vector<std::vector<double> > res_diff;
2036  res_diff.resize(hdim);
2037  if (opt_iflip < nr_nomirror_flips)
2038  point_trans = A2D_ELEM(Moffsets, (int)opt_offsets(1), (int)opt_offsets(0));
2039  else
2040  point_trans = A2D_ELEM(Moffsets_mirror, (int)opt_offsets(1), (int)opt_offsets(0));
2041  img_start = point_trans*4*dnr_points_2d + (opt_iflip%nr_nomirror_flips)*dnr_points_2d;
2042  ref_start = opt_refno*nr_psi*dnr_points_2d + opt_ipsi*dnr_points_2d;
2043 
2044  if (do_norm)
2045  ref_scale = opt_scale / refs_avgscale[opt_refno];
2046  for (size_t ii = 0; ii < nr_points_prob; ii++)
2047  {
2048  double inv_sqrt_sigma2 = 1. / sqrt(0.5*sigma2[ii]);
2049  if (do_ctf_correction)
2050  {
2051  dAi(diff,2*ii) = (Fimg_trans[img_start + 2*ii] -
2052  ctf[ii] * ref_scale * Fref[ref_start + 2*ii]) * inv_sqrt_sigma2;
2053  dAi(diff,2*ii+1) = (Fimg_trans[img_start + 2*ii+1] -
2054  ctf[ii] * ref_scale * Fref[ref_start + 2*ii+1]) * inv_sqrt_sigma2;
2055  }
2056  else
2057  {
2058  dAi(diff,2*ii) = (Fimg_trans[img_start + 2*ii] -
2059  ref_scale * Fref[ref_start + 2*ii])* inv_sqrt_sigma2;
2060  dAi(diff,2*ii+1) = (Fimg_trans[img_start + 2*ii+1] -
2061  ref_scale * Fref[ref_start + 2*ii+1]) * inv_sqrt_sigma2;
2062  }
2063  // Fill vectors for resolution-depedent histograms
2064  int ires = DIRECT_MULTIDIM_ELEM(Mresol_int, pointer_2d[ii]);
2065  res_diff[ires].push_back(dAi(diff,2*ii));
2066  res_diff[ires].push_back(dAi(diff,2*ii+1));
2067  }
2068 
2069  double * aux_array = MULTIDIM_ARRAY(diff) - 1;
2070  double KSD =0.;
2071  if (do_student)
2072  {
2073  if (df==1)
2074  ksone(aux_array, 2*nr_points_prob, &lcdf_tstudent_mlf1, &KSD, &KSprob);
2075  else if (df==3)
2076  ksone(aux_array, 2*nr_points_prob, &lcdf_tstudent_mlf3, &KSD, &KSprob);
2077  else if (df==6)
2078  ksone(aux_array, 2*nr_points_prob, &lcdf_tstudent_mlf6, &KSD, &KSprob);
2079  else if (df==9)
2080  ksone(aux_array, 2*nr_points_prob, &lcdf_tstudent_mlf9, &KSD, &KSprob);
2081  else if (df==30)
2082  ksone(aux_array, 2*nr_points_prob, &lcdf_tstudent_mlf30, &KSD, &KSprob);
2083  else
2084  REPORT_ERROR(ERR_VALUE_INCORRECT,"KS-test for t-distribution only implemented for df=1,3,6,9 or 30!");
2085  }
2086  else
2087  {
2088  ksone(aux_array, 2*nr_points_prob, &cdf_gauss, &KSD, &KSprob);
2089  }
2090 
2091  // Compute resolution-dependent histograms
2092  for (size_t ires = 0; ires < hdim; ires++)
2093  {
2094  for (size_t j=0; j<res_diff[ires].size(); j++)
2095  resolhist[ires].insert_value(res_diff[ires][j]);
2096  }
2097 
2098  // Overall average histogram
2099  if (sumhist.sampleNo()==0)
2103 
2104  if (write_histograms)
2105  {
2106  Histogram1D hist;
2107  double val;
2108  hist.init(HISTMIN, HISTMAX, HISTSTEPS);
2109  compute_hist(diff,hist,HISTMIN, HISTMAX, HISTSTEPS);
2110  hist /= hist.sum()*hist.step_size;
2111  FileName fn_hist = fn_img + ".hist";
2112  std::ofstream fh_hist;
2113  fh_hist.open(fn_hist.c_str(), std::ios::out);
2114  if (!fh_hist)
2115  REPORT_ERROR(ERR_IO_NOTOPEN, (String)"Cannot write histogram file "+ fn_hist);
2117  {
2118  hist.index2val(i, val);
2119  val += 0.5*hist.step_size;
2120  fh_hist << val<<" "<<A1D_ELEM(hist, i)<<" ";
2121  if (do_student)
2122  fh_hist << tstudent1D(val, df, 1., 0.)<<"\n";
2123  else
2124  fh_hist << gaussian1D(val, 1., 0.)<<"\n";
2125  }
2126  fh_hist.close();
2127  }
2128 
2129  }
2130 
2131  // Update opt_scale
2132  if (do_norm)
2133  {
2134  opt_scale = wsum_sc / wsum_sc2;
2135  }
2136 
2137  if (nr_nomirror_flips == 0)
2138  {
2139  std::ostringstream msg;
2140  msg << "Division by zero: nr_nomirror_flips == 0";
2141  throw std::runtime_error(msg.str());
2142  }
2143 
2144  // Acummulate all weighted sums
2145  // and normalize them by sum_refw, such that sum over all weights is one!
2146  FOR_ALL_MODELS()
2147  {
2148  if (!limit_rot || pdf_directions[refno] > 0.)
2149  {
2150  sumw[refno] += (refw[refno] + refw_mirror[refno]) / sum_refw;
2151  sumw2[refno] += refw2[refno] / sum_refw;
2152  if (do_student)
2153  {
2154  sumwsc[refno] += refw2[refno] * opt_scale / sum_refw;
2155  sumwsc2[refno] += refw2[refno] * opt_scale * opt_scale / sum_refw;
2156  }
2157  else
2158  {
2159  sumwsc[refno] += (refw[refno] + refw_mirror[refno]) * opt_scale / sum_refw;
2160  sumwsc2[refno] += (refw[refno] + refw_mirror[refno]) * (opt_scale * opt_scale) / sum_refw;
2161  }
2162  sumw_mirror[refno] += refw_mirror[refno] / sum_refw;
2163  FOR_ALL_FLIPS()
2164  {
2165  irefmir = (int)floor(iflip / nr_nomirror_flips) * model.n_ref + refno;
2167  {
2168  irot = iflip * nr_psi + ipsi;
2169  // get the starting point in the Fwsum_imgs vectors
2170  wsum_start = refno*nr_psi*dnr_points_2d + ipsi*dnr_points_2d;
2172  {
2173  ix = ROUND(opt_offsets_ref[2*irefmir] + Vtrans[itrans](0));
2174  iy = ROUND(opt_offsets_ref[2*irefmir+1] + Vtrans[itrans](1));
2175  ix = intWRAP(ix, Moffsets.startingX(), Moffsets.finishingX());
2176  iy = intWRAP(iy, Moffsets.startingY(), Moffsets.finishingY());
2177  if (iflip < nr_nomirror_flips)
2178  point_trans = A2D_ELEM(Moffsets, iy, ix);
2179  else
2180  point_trans = A2D_ELEM(Moffsets_mirror, iy, ix);
2181  weight = dAkij(Mweight, itrans, refno, irot);
2182  if (weight > SIGNIFICANT_WEIGHT_LOW*maxweight)
2183  {
2184  weight /= sum_refw;
2185  // get the starting point in the Fimg_trans vector
2186  img_start = point_trans*4*dnr_points_2d + (iflip%nr_nomirror_flips)*dnr_points_2d;
2187  wsum_sigma_offset += weight * (double)(ix * ix + iy * iy);
2188  if (do_ctf_correction)
2189  {
2190  for (size_t ii = 0; ii < nr_points_2d; ii++)
2191  {
2192  Fwsum_imgs[wsum_start + 2*ii] += weight
2193  * opt_scale * decctf[ii] * Fimg_trans[img_start + 2*ii];
2194  Fwsum_imgs[wsum_start + 2*ii+1] += weight
2195  * opt_scale * decctf[ii] * Fimg_trans[img_start + 2*ii+1];
2196  Fwsum_ctfimgs[wsum_start + 2*ii] += weight
2197  * opt_scale * Fimg_trans[img_start + 2*ii];
2198  Fwsum_ctfimgs[wsum_start + 2*ii+1] += weight
2199  * opt_scale * Fimg_trans[img_start + 2*ii+1];
2200  tmpr = Fimg_trans[img_start + 2*ii]
2201  - ctf[ii] * opt_scale * Fref[wsum_start + 2*ii];
2202  tmpi = Fimg_trans[img_start + 2*ii+1]
2203  - ctf[ii] * opt_scale * Fref[wsum_start + 2*ii+1];
2204  Mwsum_sigma2_local[ii] += weight * (tmpr * tmpr + tmpi * tmpi);
2205  }
2206  }
2207  else
2208  {
2209  for (size_t ii = 0; ii < nr_points_2d; ii++)
2210  {
2211  Fwsum_imgs[wsum_start + 2*ii] += weight
2212  * opt_scale * Fimg_trans[img_start + 2*ii];
2213  Fwsum_imgs[wsum_start + 2*ii+1] += weight
2214  * opt_scale * Fimg_trans[img_start + 2*ii+1];
2215  tmpr = Fimg_trans[img_start + 2*ii]
2216  - opt_scale * Fref[wsum_start + 2*ii];
2217  tmpi = Fimg_trans[img_start + 2*ii+1]
2218  - opt_scale * Fref[wsum_start + 2*ii+1];
2219  Mwsum_sigma2_local[ii] += weight * (tmpr * tmpr + tmpi * tmpi);
2220  }
2221  }
2222  }// if weight > SIGNIFICANT_WEIGHT_LOW*maxweight
2223  }//forall translation
2224  }//forall rotation
2225  }//forall flips
2226  }
2227  }//forall models
2228 
2229  // Update the optimal origin offsets
2230  nr_mir = (do_mirror) ? 2 : 1;
2231 
2232  FOR_ALL_MODELS()
2233  {
2234  if (!limit_rot || pdf_directions[refno] > 0.)
2235  {
2236  for (int imir = 0; imir < nr_mir; imir++)
2237  {
2238  irefmir = imir * model.n_ref + refno;
2239  iflip_start = imir * nr_nomirror_flips;
2240  iflip_stop = imir * nr_nomirror_flips + nr_nomirror_flips;
2241  opt_itrans = zero_trans;
2242  for (int iflip = iflip_start; iflip < iflip_stop; iflip++)
2243  {
2245  {
2246  irot = iflip * nr_psi + ipsi;
2248  {
2249  weight = dAkij(Mweight, itrans, refno, irot);
2250  if (weight > Pmax_refmir[irefmir])
2251  {
2252  Pmax_refmir[irefmir] = weight;
2253  opt_itrans = itrans;
2254  }
2255  }
2256  }
2257  }
2258  opt_offsets_ref[2*irefmir] += Vtrans[opt_itrans](0);
2259  opt_offsets_ref[2*irefmir+1] += Vtrans[opt_itrans](1);
2260  }
2261  }
2262  }
2263 
2264  // Distribution widths
2265  fracweight = maxweight / sum_refw;
2266  sum_refw2 /= sum_refw;
2267 
2268 
2269  // Compute Log Likelihood
2270  if (!do_student)
2271  // 1st term: log(refw_i)
2272  // 2nd term: for subtracting mindiff2
2273  // 3rd term: for missing normalization constant
2274  LL += log(sum_refw)
2275  - mindiff2
2276  - logsigma2;
2277  else
2278  // 1st term: log(refw_i)
2279  // 2nd term: for dividing by (1 + mindiff2/df)^df2
2280  // 3rd term: for sigma-dependent normalization term in t-student distribution
2281  // 4th&5th terms: gamma functions in t-distribution
2282  //LL += log(sum_refw) - log(1. + ( mindiff2 / df )) - log(sigma_noise * sigma_noise);
2283  LL += log(sum_refw)
2284  + df2 * log( 1. + ( mindiff2 / df ))
2285  - logsigma2
2286  + gammln(-df2) - gammln(df/2.);
2287 
2288  // if (rank == 0)
2289  // {
2290  // std::cerr << "DEBUG_JM: current_image : " << current_image
2291  // << " sum_refw: " << sum_refw
2292  // << " LL: " << LL << std::endl;
2293  // }
2294  delete []sigma2;
2295  delete []inv_sigma2;
2296  delete []ctf;
2297  delete []decctf;
2298 }
2299 
2301 {
2302  // Integrate over all images
2303  expectation();
2304  // Update model with new estimates
2305  maximization();
2306 }
2307 
2309 {
2310 
2311  Image<double> img;
2312  FileName fn_img, fn_trans;
2313  std::vector<double> allref_offsets, pdf_directions(model.n_ref);
2314  MultidimArray<double> trans(2);
2315  MultidimArray<double> opt_offsets(2);
2316 
2317  float old_phi = -999., old_theta = -999.;
2318  double opt_psi, opt_flip, opt_scale, maxcorr, maxweight2;
2319  double w2, KSprob = 0.;
2320  size_t opt_refno, opt_ipsi, opt_iflip;
2321  int focus = 0;
2322  bool apply_ctf;
2323 
2324  // Pre-calculate pdfs
2326 
2327  // Generate (FT of) each rotated version of all references
2329 
2330  // Initialize progress bar
2332 
2333  trans.initZeros();
2334  int n = model.n_ref;
2335  // Set all weighted sums to zero
2336  sumw.assign(n, 0.);
2337  sumw2.assign(n, 0.);
2338  sumwsc.assign(n, 0.);
2339  sumwsc2.assign(n, 0.);
2340  sumw_mirror.assign(n, 0.);
2341 
2342  sumw_defocus.clear();
2343  Mwsum_sigma2.clear();
2344  Fwsum_imgs.clear();
2345  Fwsum_ctfimgs.clear();
2346  LL = 0.;
2347  wsum_sigma_offset = 0.;
2348  sumcorr = 0.;
2349  std::vector<double> dum;
2350  dum.assign(nr_points_2d, 0.);
2351  Mwsum_sigma2.assign(nr_focus, dum);
2353  sumw_defocus.assign(nr_focus, 0.);
2354  else
2355  {
2357  {
2358  sumw_defocus.push_back((double)count_defocus[ifocus]);
2359  }
2360  }
2361 
2362  if (dnr_points_2d > 0)
2363  {
2364  int nn = n * nr_psi * dnr_points_2d;
2365  Fwsum_imgs.assign(nn, 0.);
2366  if (do_ctf_correction)
2367  Fwsum_ctfimgs.assign(nn, 0.);
2368  }
2369 
2370  std::stringstream ss;
2371  String s;
2372  // Loop over all images
2374  {
2375  size_t id = img_id[imgno];
2376  current_image = imgno;
2377 
2378  focus = 0;
2379  // Get defocus-group
2380  if (do_ctf_correction)
2381  MDimg.getValue(MDL_DEFGROUP, focus, id);
2382 
2383  //std::cerr << formatString("processing img: %lu with id: %lu\n", imgno, id);
2384 
2385  MDimg.getValue(MDL_IMAGE, fn_img, id);
2386  //std::cerr << formatString(" filename: %s\n", fn_img.c_str());
2387  //img.read(fn_img, false, false, false, false);
2388 
2389  img.read(fn_img);
2390  img().setXmippOrigin();
2391 
2392  // Get optimal offsets for all references
2393  allref_offsets = imgs_offsets[IMG_LOCAL_INDEX];
2394 
2395  // Read optimal orientations from memory
2396  if (limit_rot)
2397  {
2398  old_phi = imgs_oldphi[IMG_LOCAL_INDEX];
2399  old_theta = imgs_oldtheta[IMG_LOCAL_INDEX];
2400  }
2401 
2402  if (do_norm)
2403  {
2404  opt_scale = imgs_scale[IMG_LOCAL_INDEX];
2405  }
2406 
2407  // For limited orientational search: preselect relevant directions
2408  preselectDirections(old_phi, old_theta, pdf_directions);
2409 
2410  // Perform the actual expectation step for this image
2411  apply_ctf = !(iter == 1 && first_iter_noctf);
2412 
2413  processOneImage(img(), focus, apply_ctf, maxcorr, maxweight2, w2,
2414  opt_scale, opt_refno, opt_psi, opt_ipsi, opt_iflip, opt_offsets,
2415  allref_offsets, pdf_directions,
2416  do_kstest, iter==iter_write_histograms, fn_img, KSprob);
2417 
2418  // for t-student, update sumw_defocus
2420  {
2421  if (debug==8)
2422  std::cerr<<"sumw_defocus[focus]= "<<sumw_defocus[focus]<<" w2= "<<w2<<std::endl;
2423  sumw_defocus[focus] += w2;
2424  }
2425 
2426  // Store optimal scale in memory
2427  if (do_norm)
2428  {
2429  imgs_scale[IMG_LOCAL_INDEX] = opt_scale;
2430  }
2431 
2432  // Store optimal translations
2433  imgs_offsets[IMG_LOCAL_INDEX] = allref_offsets;
2434 
2435  // Store optimal phi and theta in memory
2436  if (limit_rot)
2437  {
2438  imgs_oldphi[IMG_LOCAL_INDEX] = model.Iref[opt_refno].rot();
2439  imgs_oldtheta[IMG_LOCAL_INDEX] = model.Iref[opt_refno].tilt();
2440  }
2441 
2442  // Output docfile
2443  sumcorr += maxcorr;
2444  opt_flip = 0.;
2445  if (-opt_psi > 360.)
2446  {
2447  opt_psi += 360.;
2448  opt_flip = 1.;
2449  }
2450 
2452  = model.Iref[opt_refno].rot(); // rot
2454  = model.Iref[opt_refno].tilt(); // tilt
2455  dAij(docfiledata,IMG_LOCAL_INDEX,2) = opt_psi + 360.; // psi
2456  dAij(docfiledata,IMG_LOCAL_INDEX,3) = trans(0) + opt_offsets(0); // Xoff
2457  dAij(docfiledata,IMG_LOCAL_INDEX,4) = trans(1) + opt_offsets(1); // Yoff
2458  dAij(docfiledata,IMG_LOCAL_INDEX,5) = (double) (opt_refno + 1); // Ref
2459  dAij(docfiledata,IMG_LOCAL_INDEX,6) = opt_flip; // Mirror
2460  dAij(docfiledata,IMG_LOCAL_INDEX,7) = maxcorr; // P_max/P_tot
2461 
2462  if (do_student)
2463  {
2464  dAij(docfiledata,IMG_LOCAL_INDEX,8) = maxweight2; // Robustness weight
2465  }
2466  if (do_norm)
2467  {
2468  dAij(docfiledata,IMG_LOCAL_INDEX,9) = opt_scale; // image scale
2469  }
2470  if (do_kstest)
2471  {
2472  dAij(docfiledata,IMG_LOCAL_INDEX,10) = KSprob;
2473  }
2474 
2475  // Report progress bar
2476  setProgress();
2477  }
2478 
2479  endProgress();
2480 
2481  if (do_ctf_correction)
2482  {
2484  }
2486 
2487 }
2488 
2489 // Update all model parameters
2491 {
2492 
2493  MultidimArray<double> rmean_sigma2, rmean_signal2;
2494  MultidimArray<int> radial_count;
2495  Matrix1D<int> center(2);
2496  MultidimArray<std::complex<double> > Faux, Faux2;
2497  MultidimArray<double> Maux;
2498  FileName fn_tmp;
2499  double aux;
2500  int c;
2501 
2502  // Pre-calculate sumw_allrefs & average Pmax/sumP or cross-correlation
2503  sumw_allrefs = 0.;
2504 
2505  // Update the reference images
2506  FOR_ALL_MODELS()
2507  {
2508  if (!do_student && sumw[refno] > 0.)
2509  {
2510  model.Iref[refno]() = wsum_Mref[refno];
2511  model.Iref[refno]() /= sumwsc2[refno];
2512  model.Iref[refno].setWeight(sumw[refno]);
2513  sumw_allrefs += sumw[refno];
2514  if (do_ctf_correction)
2515  {
2516  Ictf[refno]() = wsum_ctfMref[refno];
2517  Ictf[refno]() /= sumwsc2[refno];
2518  Ictf[refno].setWeight(sumw[refno]);
2519  }
2520  else
2521  {
2522  Ictf[refno]=model.Iref[refno];
2523  }
2524  }
2525  else if (do_student && sumw2[refno] > 0.)
2526  {
2527  model.Iref[refno]() = wsum_Mref[refno];
2528  model.Iref[refno]() /= sumwsc2[refno];
2529  model.Iref[refno].setWeight(sumw2[refno]);
2530  sumw_allrefs += sumw[refno];
2531  //sumw_allrefs2 += sumw2[refno];
2532  if (do_ctf_correction)
2533  {
2534  Ictf[refno]() = wsum_ctfMref[refno];
2535  Ictf[refno]() /= sumwsc2[refno];
2536  Ictf[refno].setWeight(sumw2[refno]);
2537  }
2538  else
2539  {
2540  Ictf[refno]=model.Iref[refno];
2541  }
2542  }
2543  else
2544  {
2545  model.Iref[refno].setWeight(0.);
2546  Ictf[refno].setWeight(0.);
2547  model.Iref[refno]().initZeros(dim, dim);
2548  Ictf[refno]().initZeros();
2549  }
2550  }
2551 
2552  // Adjust average scale (nr_classes will be smaller than n_ref for the 3D case!)
2553  if (do_norm)
2554  {
2555  int iclass, nr_classes = ROUND(model.n_ref / refs_per_class);
2556  std::vector<double> wsum_scale(nr_classes), sumw_scale(nr_classes);
2557  ldiv_t temp;
2558  average_scale = 0.;
2559  FOR_ALL_MODELS()
2560  {
2561  average_scale += sumwsc[refno];
2562  temp = ldiv( refno, refs_per_class );
2563  iclass = ROUND(temp.quot);
2564  wsum_scale[iclass] += sumwsc[refno];
2565  sumw_scale[iclass] += sumw[refno];
2566  }
2567  FOR_ALL_MODELS()
2568  {
2569  temp = ldiv( refno, refs_per_class );
2570  iclass = ROUND(temp.quot);
2571  if (sumw_scale[iclass]>0.)
2572  {
2573  refs_avgscale[refno] = wsum_scale[iclass]/sumw_scale[iclass];
2574  model.Iref[refno]() *= refs_avgscale[refno];
2575  Ictf[refno]() *= refs_avgscale[refno];
2576  }
2577  else
2578  {
2579  refs_avgscale[refno] = 1.;
2580  }
2581  }
2583  }
2584 
2585  // Average corr
2586  sumcorr /= sumw_allrefs;
2587 
2588  // Update the model fractions
2589  if (!fix_fractions)
2590  {
2591  FOR_ALL_MODELS()
2592  {
2593  if (sumw[refno] > 0.)
2594  {
2595  alpha_k[refno] = sumw[refno] / sumw_allrefs;
2596  mirror_fraction[refno] = sumw_mirror[refno] / sumw[refno];
2597  }
2598  else
2599  {
2600  alpha_k[refno] = 0.;
2601  mirror_fraction[refno] = 0.;
2602  }
2603  }
2604  }
2605 
2606  // Update sigma of the origin offsets
2607  if (!fix_sigma_offset)
2608  {
2610  }
2611 
2612  // Update the noise parameters
2613  if (!fix_sigma_noise)
2614  {
2616  {
2617  getFTfromVector(Mwsum_sigma2[ifocus],0,Faux,true);
2618  Half2Whole(Faux, Faux2, dim);
2619  FFT_magnitude(Faux2, Maux);
2620  CenterFFT(Maux, true);
2621  Maux.setXmippOrigin();
2622  center.initZeros();
2623  rmean_sigma2.initZeros();
2624  radialAverage(Maux, center, rmean_sigma2, radial_count, true);
2625  // Factor 2 here, because the Gaussian distribution is 2D!
2626  size_t maxIrr = std::min(current_highres_limit, MULTIDIM_SIZE(Vsig[ifocus]) - 1);
2627  for (size_t irr = 0; irr <= maxIrr; irr++)
2628  {
2629  aux = dAi(rmean_sigma2, irr) / (2. * sumw_defocus[ifocus]);
2630  if (aux > 0.)
2631  {
2632  VSIG_ITEM = aux;
2633  }
2634  }
2635  }
2636  }
2637 
2638  // Calculate average spectral signal
2639  c = 0;
2640  FOR_ALL_MODELS()
2641  {
2642  if ( (!do_student && sumw[refno] > 0.) ||
2643  ( do_student && sumw2[refno] > 0.) )
2644  {
2645  FourierTransform(Ictf[refno](), Faux);
2646  FFT_magnitude(Faux, Maux);
2647  CenterFFT(Maux, true);
2648  Maux *= Maux;
2649  //if (!do_student)
2650  //Maux *= sumw[refno];
2651  //else
2652  //Maux *= sumw2[refno];
2653  Maux *= sumw[refno];
2654  center.initZeros();
2655  rmean_signal2.initZeros();
2656  Maux.setXmippOrigin();
2657  radialAverage(Maux, center, rmean_signal2, radial_count, true);
2658  if (c == 0)
2659  spectral_signal = rmean_signal2;
2660  else
2661  spectral_signal += rmean_signal2;
2662  c++;
2663  // std::cerr << "DEBUG_JM: ====================" <<std::endl;
2664  // std::cerr << "DEBUG_JM: refno: " << refno << std::endl;
2665  // std::cerr << "DEBUG_JM: rmean_signal2: " << rmean_signal2 << std::endl;
2666  // std::cerr << "DEBUG_JM: spectral_signal: " << spectral_signal << std::endl;
2667  }
2668  }
2669  double inv_nref = 1./(double)model.n_ref;
2670  spectral_signal *= inv_nref;
2671  // std::cerr << "DEBUG_JM: inv_nref: " << inv_nref << std::endl;
2672  // std::cerr << "DEBUG_JM, maximization: spectral_signal: " << spectral_signal << std::endl;
2673 }
2674 
2676 {
2678  //std::cerr << "DEBUG_JM, endIteration: spectral_signal: " << spectral_signal << std::endl;
2680 }
2681 
2682 void writeImage(Image<double> &img, const FileName &fn, MDRow &row)
2683 {
2684  img.write(fn);
2685  row.setValue(MDL_IMAGE, fn);
2686  row.setValue(MDL_ENABLED, 1);
2687  double weight = img.weight();
2688  double rot = 0., tilt = 0., psi = 0.;
2689  img.getEulerAngles(rot, tilt, psi);
2690  row.setValue(MDL_WEIGHT, weight);
2691  size_t count = ROUND(weight);
2692  row.setValue(MDL_CLASS_COUNT, count);
2693  // row.setValue(MDL_ANGLE_ROT, rot);
2694  // row.setValue(MDL_ANGLE_TILT, tilt);
2695  // row.setValue(MDL_ANGLE_PSI, psi);
2696 }
2697 
2699 {
2700 
2701  FileName fn_tmp, fn_base;
2702  Image<double> Itmp;
2703  MetaDataVec MDo;
2704  String comment;
2705  std::ofstream fh;
2706  size_t id;
2707  bool write_conv = !do_ML3D;
2708  //Only override first time
2709 
2710  if (iter == 0)
2711  write_conv = false;
2712 
2713  fn_base = (outputType == OUT_ITER || outputType == OUT_REFS) ?
2715  // {
2716  // fn_base = getIterExtraPath(fn_root, iter);
2717  // fn_prefix = FN_ITER_PREFIX(iter);
2718  //
2719  // }
2720 
2721  // Write out optimal image orientations
2722  fn_tmp = FN_IMAGES_MD(fn_base);
2723  MDimg.write(fn_tmp);
2724 
2725  // Write out current reference images and fill sel & log-file
2726  // First time for _ref, second time for _cref
2727  FileName fn_base_cref = FN_CREF_IMG;
2728  MDo = MDref;
2729  auto iterMDo = MDo.begin();
2730  auto iterMDref = MDref.ids().begin();
2731 
2732  for (int refno = 0; refno < model.n_ref; ++refno, ++iterMDo, ++iterMDref)
2733  {
2734  MDRowSql sqlRow;
2735  (*iterMDo).setValue(MDL_REF, refno + 1);
2736  sqlRow.setValue(MDL_REF, refno + 1);
2737 
2738  if (do_mirror) {
2739  (*iterMDo).setValue(MDL_MIRRORFRAC, mirror_fraction[refno]);
2740  sqlRow.setValue(MDL_MIRRORFRAC, mirror_fraction[refno]);
2741  }
2742 
2743  if (write_conv) {
2744  (*iterMDo).setValue(MDL_SIGNALCHANGE, conv[refno]*1000);
2745  sqlRow.setValue(MDL_SIGNALCHANGE, conv[refno]*1000);
2746  }
2747 
2748  if (do_norm) {
2749  (*iterMDo).setValue(MDL_INTSCALE, refs_avgscale[refno]);
2750  sqlRow.setValue(MDL_INTSCALE, refs_avgscale[refno]);
2751  }
2752 
2753  //write ctf
2754  fn_tmp.compose(refno + 1, fn_base_cref);
2755  writeImage(Ictf[refno], fn_tmp, *iterMDo);
2756 
2757  //write image
2758  fn_tmp = FN_REF(fn_base, refno + 1);
2759  Itmp = model.Iref[refno];
2760  writeImage(Itmp, fn_tmp, sqlRow);
2761  MDref.setRow(sqlRow, *iterMDref);
2762  }
2763 
2764  // Write out reference md file
2765  MDo.write(FN_CREF_IMG_MD);
2766  outRefsMd = FN_CLASSES_MD(fn_base);
2768 
2769  // Write out log-file
2770  MetaDataVec mdLog;
2771  //mdLog.setComment(cline);
2772  id = mdLog.addObject();
2773  mdLog.setValue(MDL_ITER, iter, id);
2774  mdLog.setValue(MDL_LL, LL, id);
2775  mdLog.setValue(MDL_PMAX, sumcorr, id);
2777  mdLog.setValue(MDL_RANDOMSEED, seed, id);
2778  if (do_norm)
2779  mdLog.setValue(MDL_INTSCALE, average_scale, id);
2780  // fn_tmp = FN_IMGMD(fn_prefix);
2781  // mdLog.setValue(MDL_IMGMD, fn_tmp, id);
2782  // mdLog.setValue(MDL_REFMD, outRefsMd, id);
2783  // if (outputType == OUT_ITER)
2784  // fn_prefix = fn_root + "_iter";
2785 
2786  mdLog.write(FN_LOGS_MD(fn_base), MD_APPEND);
2787 
2788  if (outputType != OUT_REFS)
2789  {
2790  MetaDataVec mdImgs;
2791  auto n = (int) MDref.size(); //Avoid int and size_t comparison warning
2792  for (int ref = 1; ref <= n; ++ref)
2793  {
2794  mdImgs.importObjects(MDimg, MDValueEQ(MDL_REF, ref));
2795  mdImgs.write(FN_CLASS_IMAGES_MD(fn_base, ref), MD_APPEND);
2796  }
2797  }
2798  // fn_tmp = FN_LOGMD(fn_prefix);
2799  // if (mode == MD_OVERWRITE)
2800  // mdLog.write(fn_tmp);
2801  // else
2802  // mdLog.append(fn_tmp);
2803  //
2804  // mode = MD_APPEND;
2805 
2806 
2807  // Write out average and resolution-dependent histograms
2808  if (do_kstest)
2809  {
2810  double val;
2811  std::ofstream fh_hist;
2812 
2813  fn_tmp = fn_base + "avg.hist.log";
2814  fh_hist.open(fn_tmp.c_str(), std::ios::out);
2815  if (!fh_hist)
2816  REPORT_ERROR(ERR_IO_NOTOPEN, (String)"Cannot write histogram file "+ fn_tmp);
2819  {
2820  sumhist.index2val(i, val);
2821  val += 0.5*sumhist.step_size;
2822  fh_hist << val<<" "<< A1D_ELEM(sumhist, i)<<" ";
2823  if (do_student)
2824  fh_hist << tstudent1D(val, df, 1., 0.)<<"\n";
2825  else
2826  fh_hist << gaussian1D(val, 1., 0.)<<"\n";
2827  }
2828  fh_hist.close();
2829 
2830  fn_tmp = fn_base + "_resol.hist";
2831  fh_hist.open(fn_tmp.c_str(), std::ios::out);
2832  if (!fh_hist)
2833  REPORT_ERROR(ERR_IO_NOTOPEN, (String)"Cannot write histogram file "+ fn_tmp);
2835  {
2836  sumhist.index2val(i, val);
2837  val += 0.5*sumhist.step_size;
2838  fh_hist << val<<" ";
2839  if (do_student)
2840  fh_hist << tstudent1D(val, df, 1., 0.)<<" ";
2841  else
2842  fh_hist << gaussian1D(val, 1., 0.)<<" ";
2843  for (size_t ires = 0; ires < hdim; ires++)
2844  {
2845  if (resolhist[ires].sampleNo() > 0)
2846  {
2847  fh_hist <<A1D_ELEM(resolhist[ires], i)/(resolhist[ires].sum()*resolhist[ires].step_size)<<" ";
2848  }
2849  }
2850  fh_hist <<"\n";
2851  }
2852  fh_hist.close();
2853 
2854  }
2855 
2856  // Write out updated Vsig vectors
2857  if (!fix_sigma_noise)
2858  {
2860  {
2861  writeNoiseFile(fn_base, ifocus);
2862  }
2863  }
2864 }//function writeOutputFiles
2865 
2866 void ProgMLF2D::writeNoiseFile(const FileName &fn_base, int ifocus)
2867 {
2869  MetaDataVec md;
2870  // Calculate resolution step
2871  double resol_step = 1. / (sampling * dim);
2873 
2876 
2877  md.fillLinear(MDL_RESOLUTION_FREQ, 0., resol_step);
2878  // write Vsig vector to disc
2879  md.write(FN_VSIG(fn_base, ifocus, "noise.xmd"), (ifocus > 0 ? MD_APPEND : MD_OVERWRITE));
2880 
2881 }//function writeNoiseFile
2882 
2885  size_t first, size_t last)
2886 {
2887  LOG_LEVEL(addPartialDocfile);
2888  for (size_t imgno = first; imgno <= last; imgno++)
2889  {
2890  size_t index = imgno - first;
2891  size_t id = img_id[imgno];
2892  //FIXME now directly to MDimg
2893  if (do_ML3D)
2894  {
2895  MDimg.setValue(MDL_ANGLE_ROT, dAij(data, index, 0), id);
2896  MDimg.setValue(MDL_ANGLE_TILT, dAij(data, index, 1), id);
2897  }
2898  //Here we change the sign of the angle becase in the code
2899  //is represent the rotation of the reference and we want
2900  //to store the rotation of the image
2901  double psi = -dAij(data, index, 2);
2902  MDimg.setValue(MDL_ANGLE_PSI, psi, id);
2903  //MDimg.setValue(MDL_ANGLE_PSI, dAij(data, index, 2), id);
2904  MDimg.setValue(MDL_SHIFT_X, dAij(data, index, 3), id);
2905  MDimg.setValue(MDL_SHIFT_Y, dAij(data, index, 4), id);
2906  MDimg.setValue(MDL_REF, ROUND(dAij(data, index, 5)), id);
2907  if (do_mirror)
2908  {
2909  MDimg.setValue(MDL_FLIP, dAij(data, index, 6) != 0., id);
2910  }
2911  MDimg.setValue(MDL_PMAX, dAij(data, index, 7), id);
2912  if (do_student)
2913  {
2914  MDimg.setValue(MDL_WROBUST, dAij(data, index, 8), id);
2915  }
2916  if (do_norm)
2917  {
2918  MDimg.setValue(MDL_INTSCALE, dAij(data, index, 9), id);
2919  }
2920  if (do_kstest)
2921  {
2922  MDimg.setValue(MDL_KSTEST, dAij(data, index, 10), id);
2923  }
2924 
2925  }
2926 }//close function addDocfileData
2927 
double cdf_gauss(double x)
void FourierTransformHalf(const MultidimArray< double > &in, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:187
size_t nr_psi
Definition: ml2d.h:154
bool do_student
IN DEVELOPMENT.
Definition: mlf_align2d.h:135
std::vector< double > Fwsum_imgs
Definition: mlf_align2d.h:157
Index out of bounds.
Definition: xmipp_error.h:132
virtual void addPartialDocfileData(const MultidimArray< double > &data, size_t first, size_t last)
Add docfiledata to docfile.
std::vector< Matrix1D< double > > Vtrans
Definition: ml2d.h:184
#define dAi(v, i)
void init_progress_bar(long total)
double lowres_limit
Definition: mlf_align2d.h:116
contribution of an image to log-likelihood value
double wsum_sigma_offset
Definition: mlf_align2d.h:153
std::vector< size_t > img_id
Definition: ml2d.h:232
bool do_generate_refs
Definition: ml2d.h:198
Name of Metadata file for all references(string)
MetaDataDb MDimg
Definition: ml2d.h:172
int refs_per_class
Definition: ml2d.h:217
Rotation angle of an image (double,degrees)
#define FOR_ALL_POINTS()
Definition: mlf_align2d.h:42
Definition: ml2d.h:76
void min(Image< double > &op1, const Image< double > &op2)
#define A2D_ELEM(v, i, j)
Definition: ml2d.h:76
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
void generateInitialReferences()
Generate initial references from random subset averages.
Fourier shell correlation (double)
double fix_high
Definition: mlf_align2d.h:124
std::vector< MultidimArray< double > > Vctf
Definition: mlf_align2d.h:110
size_t nr_flip
Definition: ml2d.h:156
double getDoubleParam(const char *param, int arg=0)
__host__ __device__ float2 floor(const float2 v)
double cdf_tstudent(int k, double t)
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
iterator begin() override
Definition: metadata_vec.h:501
#define SIGNIFICANT_WEIGHT_LOW
Definition: ml_tomo.h:46
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
#define FOR_ALL_LOCAL_IMAGES()
Definition: ml2d.h:64
double highres_limit
Definition: mlf_align2d.h:116
void ksone(double data[], int n, double(*func)(double), double *d, double *prob)
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(m)
doublereal * c
#define MULTIDIM_SIZE(v)
void Euler_direction(double alpha, double beta, double gamma, Matrix1D< double > &v)
Definition: geometry.cpp:721
#define dAij(M, i, j)
virtual void show() const
void maximization()
Update all model parameters (maximization step)
void findObjects(std::vector< size_t > &objectsOut, const MDQuery &query) const override
MultidimArray< double > Mr2
Definition: ml2d.h:178
void sqrt(Image< double > &op)
bool getValue(MDObject &mdValueOut, size_t id) const override
Signal change for an image.
ModelML2D model
Definition: ml2d.h:224
Tilting angle of an image (double,degrees)
bool do_variable_psi
Definition: mlf_align2d.h:83
MultidimArray< size_t > Mresol_int
Definition: mlf_align2d.h:108
bool fix_fractions
Definition: ml2d.h:139
double DeltafV
Defocus in V (in Angstroms). Negative values are underfocused.
Definition: ctf.h:830
void setValue(const MDObject &object) override
void groupCTFMetaData(const MetaDataDb &imgMd, MetaDataDb &ctfMd, std::vector< MDLabel > &groupbyLabels)
Definition: ctf.cpp:41
double LL
Definition: mlf_align2d.h:153
int search_shift
Definition: mlf_align2d.h:93
Shift for the image in the X axis (double)
void rotateReference(std::vector< double > &out)
Fill vector of matrices with all rotations of reference.
double average_scale
Definition: ml2d.h:213
void defineParams()
Params definition.
Definition: mlf_align2d.cpp:71
void applyGeometry(int SplineDegree, MultidimArray< std::complex< double > > &V2, const MultidimArray< std::complex< double > > &V1, const Matrix2D< double > &A, bool inv, bool wrap, std::complex< double > outside, MultidimArray< double > *BcoeffsPtr)
size_t divide_equally(size_t N, size_t size, size_t rank, size_t &first, size_t &last)
void initProgress(size_t total, size_t stepBin=60)
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)
#define FN_REF(base, refno)
Definition: mlf_align2d.h:65
#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)
virtual void defineAdditionalParams(XmippProgram *prog, const char *sectionLine)
Definition: mlf_align2d.cpp:55
#define MULTIDIM_ARRAY(v)
size_t myLastImg
Definition: ml2d.h:168
#define FN_LOGS_MD(base)
Definition: ml2d.h:56
size_t nr_trans
Definition: mlf_align2d.h:89
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
FileName fn_img
Definition: ml2d.h:132
int n_ref
Definition: ml2d.h:83
std::vector< double > sumw_defocus
Definition: mlf_align2d.h:156
double psi_step
Definition: ml2d.h:158
void selfNormalize()
Definition: matrix1d.cpp:723
void preselectDirections(float &phi, float &theta, std::vector< double > &pdf_directions)
OutputType
Definition: ml2d.h:76
Weight of t-student distribution in robust Maximum likelihood.
#define FOR_ALL_DEFOCUS_GROUPS()
Definition: mlf_align2d.h:40
#define VSNR_ITEM
Definition: mlf_align2d.h:46
std::vector< int > pointer_2d
Definition: mlf_align2d.h:126
bool allowRestart
Definition: ml2d.h:239
void expectation()
Integrate over all experimental images.
bool first_iter_noctf
Definition: mlf_align2d.h:118
void iteration()
One iteration of the process.
size_t hdim
Definition: ml2d.h:151
virtual IdIteratorProxy< false > ids()
FileName fn_root
Definition: ml2d.h:132
double psi_max
Definition: ml2d.h:160
double weight(const size_t n=0) const
int iter_write_histograms
Definition: mlf_align2d.h:143
virtual void defineAdditionalParams(XmippProgram *prog, const char *sectionLine)
Definition: ml2d.cpp:266
#define FN_CLASSES_MD(base)
Definition: ml2d.h:55
void init(double min_val, double max_val, int n_steps)
Definition: histogram.cpp:71
size_t nr_focus
Definition: mlf_align2d.h:114
#define i
Is this image enabled? (int [-1 or 1])
size_t current_highres_limit
Definition: mlf_align2d.h:129
#define rotate(a, i, j, k, l)
double reduce_snr
Definition: mlf_align2d.h:112
size_t addRow(const MDRow &row) override
void estimateInitialNoiseSpectra()
#define FOR_ALL_DIGITAL_FREQS()
Definition: mlf_align2d.h:41
doublereal * d
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
#define IMG_LOCAL_INDEX
Definition: ml2d.h:67
std::vector< double > sumwsc2
Definition: mlf_align2d.h:156
std::vector< int > pointer_j
Definition: mlf_align2d.h:126
double theta
#define FOR_ALL_LIMITED_TRANSLATIONS()
Definition: mlf_align2d.h:39
double DeltafU
Global gain. By default, 1.
Definition: ctf.h:828
bool enable_CTF
Enable CTF part.
Definition: ctf.h:275
bool do_norm
Re-normalize internally.
Definition: ml2d.h:207
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
String defaultRoot
Definition: ml2d.h:240
bool do_ML3D
Definition: ml2d.h:196
void insert_value(double val)
Definition: histogram.cpp:83
ProgTransformDimRed * prog
bool do_variable_trans
Definition: mlf_align2d.h:83
size_t nr_images_local
Definition: ml2d.h:166
glob_log first
void Half2Whole(const MultidimArray< std::complex< double > > &in, MultidimArray< std::complex< double > > &out, size_t oridim)
Definition: xmipp_fft.cpp:66
int argc
Original command line arguments.
Definition: xmipp_program.h:86
void joinNatural(const MetaDataDb &mdInLeft, const MetaDataDb &mdInRight)
constexpr float HISTMAX
Definition: mlf_align2d.h:54
double search_rot
Definition: ml2d.h:190
doublereal * b
#define VDEC_ITEM
Definition: mlf_align2d.h:48
std::vector< double > refs_avgscale
Definition: mlf_align2d.h:148
MultidimArray< double > spectral_signal
Definition: ml2d.h:253
void index2val(double i, double &v) const
Definition: histogram.h:295
bool limit_rot
Definition: ml2d.h:188
size_t myFirstImg
Definition: ml2d.h:168
void log(Image< double > &op)
const char * getParameter(int argc, const char **argv, const char *param, const char *option)
Definition: args.cpp:30
Number of elements of a type (int) [this is a genereic type do not use to transfer information to ano...
const char * getParam(const char *param, int arg=0)
void compute_hist(const MultidimArrayGeneric &array, Histogram1D &hist, int no_steps)
Definition: histogram.cpp:572
bool do_kstest
Statistical analysis of the noise distributions.
Definition: mlf_align2d.h:141
void writeImage(Image< double > &img, const FileName &fn, MDRow &row)
#define XX(v)
Definition: matrix1d.h:85
double lcdf_tstudent_mlf6(double t)
std::vector< Image< double > > Ictf
Definition: mlf_align2d.h:85
viol index
std::vector< double > imgs_oldtheta
Definition: ml2d.h:194
bool setValue(const MDObject &mdValueIn, size_t id)
size_t dnr_points_2d
Definition: mlf_align2d.h:127
#define CEIL(x)
Definition: xmipp_macros.h:225
size_t addObject() override
void readFromMetadataRow(const MetaData &MD, size_t id, bool disable_if_not_K=true)
Definition: ctf.cpp:1214
size_t addObject() override
int in
Frequency in A (double)
constexpr float HISTMIN
Definition: mlf_align2d.h:53
Defocus group.
void initSamplingStuff()
Definition: ml2d.cpp:44
void setValue(const MDObject &object) override
size_t firstRowId() const override
#define FOR_ALL_FLIPS()
Definition: mlf_align2d.h:38
virtual void defineBasicParams(XmippProgram *prog)
Definition: ml2d.cpp:226
#define FN_ITER_BASE(iter)
Definition: ml_refine3d.cpp:47
void importObjects(const MetaData &md, const std::vector< size_t > &objectsToAdd, bool doClear=true) override
std::vector< Matrix2D< double > > F
Definition: ml2d.h:174
std::vector< MultidimArray< double > > wsum_Mref
Definition: mlf_align2d.h:154
double lcdf_tstudent_mlf1(double t)
#define SMALLANGLE
Definition: ml_tomo.h:48
Flip the image? (bool)
#define FOR_ALL_ROTATIONS()
Definition: mlf_align2d.h:37
#define IS_MASTER
void endIteration()
Redefine endIteration to update Wiener filters.
FileName getIterExtraPath(const FileName &fn_root, int iter, bool makePath)
Definition: ml2d.cpp:305
bool phase_flipped
Definition: mlf_align2d.h:106
MLF signal (double)
bool do_restart
Definition: ml2d.h:236
#define XSIZE(v)
void reverseRotateReference(const std::vector< double > &in, std::vector< MultidimArray< double > > &out)
Apply reverse rotations to all matrices in vector and fill new matrix with their sum.
void progress_bar(long rlen)
Maximum value of normalized probability function (now called "Pmax/sumP") (double) ...
#define ASIND(x)
Definition: xmipp_macros.h:356
void getEulerAngles(double &rot, double &tilt, double &psi, const size_t n=0) const
bool do_student_sigma_trick
Definition: mlf_align2d.h:137
void max(Image< double > &op1, const Image< double > &op2)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
double Tm
Sampling rate (A/pixel)
Definition: ctf.h:240
Error related to numerical calculation.
Definition: xmipp_error.h:179
MultidimArray< double > docfiledata
Definition: ml2d.h:234
virtual void produceSideInfo2()
#define FN_CLASS_IMAGES_MD(base, ref)
Definition: ml2d.h:57
const char ** argv
Definition: xmipp_program.h:87
double sigma_offset
Definition: mlf_align2d.h:75
void clear() override
Definition: metadata_db.cpp:54
void radialAverage(const MultidimArray< double > &VolFourierMag, const MultidimArray< double > &V, MultidimArray< double > &radial_mean)
bool do_include_allfreqs
Definition: mlf_align2d.h:122
#define dAkij(V, k, i, j)
std::vector< std::vector< double > > imgs_offsets
Definition: ml2d.h:200
int istart
Definition: ml2d.h:145
#define ABS(x)
Definition: xmipp_macros.h:142
double df
Definition: ml2d.h:204
#define DIRECT_MULTIDIM_ELEM(v, n)
#define ROUND(x)
Definition: xmipp_macros.h:210
std::vector< double > alpha_k
Definition: mlf_align2d.h:77
#define FN_CREF_IMG_MD
Definition: mlf_align2d.h:62
Intensity scale for an image.
void readParams()
Read arguments from command line.
Definition: mlf_align2d.cpp:90
size_t dim
Definition: ml2d.h:151
int verbose
Verbosity level.
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const override
bool do_ctf_correction
Definition: mlf_align2d.h:100
double lcdf_tstudent_mlf3(double t)
std::vector< double > imgs_oldphi
Definition: ml2d.h:194
void FourierTransform(const MultidimArray< double > &in, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:124
void calculateFourierOffsets(const MultidimArray< double > &Mimg, const std::vector< double > &offsets, std::vector< double > &out, MultidimArray< int > &Moffsets, MultidimArray< int > &Moffsets_mirror)
std::vector< Histogram1D > resolhist
Definition: mlf_align2d.h:146
MetaDataDb MDref
Definition: ml2d.h:172
void initZeros()
Definition: matrix1d.h:592
KS-test statistics.
size_t size() const override
std::vector< MultidimArray< double > > Vdec
Definition: mlf_align2d.h:110
double tstudent1D(double x, double df, double sigma, double mu)
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
void writeNoiseFile(const FileName &fn_base, int ifocus)
Write noise estimation per resolution.
virtual void defineHiddenParams(XmippProgram *prog)
Definition: ml2d.cpp:290
Standard deviation of the offsets in ML model.
std::vector< double > mirror_fraction
Definition: mlf_align2d.h:79
bool fix_sigma_noise
Definition: ml2d.h:143
#define j
Frequency in 1/A (double)
std::vector< double > sumwsc
Definition: mlf_align2d.h:156
bool setRow(const MDRow &row, size_t id)
void setCurrentSamplingRates(double current_probres_limit)
Vary in-plane and translational sampling rates with resolution.
#define YY(v)
Definition: matrix1d.h:93
#define LOG_LEVEL(msg)
Definition: xmipp_log.h:89
double df2
Definition: ml2d.h:204
void generateCTF(const MultidimArray< T1 > &sample_image, MultidimArray< T2 > &CTF, double Ts=-1)
Definition: ctf.h:1194
bool getValue(MDObject &mdValueOut, size_t id) const override
double lcdf_tstudent_mlf9(double t)
bool addLabel(const MDLabel label, int pos=-1) override
double K
Global gain. By default, 1.
Definition: ctf.h:238
Class to which the image belongs (int)
File cannot be open.
Definition: xmipp_error.h:137
virtual String getComment() const
void setValue(MDLabel label, const T &d, bool addLabel=true)
constexpr int HISTSTEPS
Definition: mlf_align2d.h:55
void setProgress(size_t value=0)
std::vector< double > sumw
Definition: mlf_align2d.h:156
double sum2() const
#define FOR_ALL_ELEMENTS_IN_ARRAY1D(v)
std::vector< double > Fref
Definition: mlf_align2d.h:157
FileName fn_frac
Definition: ml2d.h:132
int round(double x)
Definition: ap.cpp:7245
bool setValue(const MDObject &mdValueIn, size_t id) override
Definition: metadata_db.cpp:90
#define LOG_FUNCTION()
Definition: xmipp_log.h:90
double sumw_allrefs
Definition: mlf_align2d.h:153
virtual void defineBasicParams(XmippProgram *prog)
Some redefinitions of the basic and additional params.
Definition: mlf_align2d.cpp:46
Number of images assigned to the same class as this image.
bool allowIEM
Definition: ml2d.h:239
#define FN_IMAGES_MD(base)
Definition: ml2d.h:54
Name of Metadata file for all images (string)
std::vector< double > sumw_mirror
Definition: mlf_align2d.h:156
std::vector< Image< double > > Iref
Definition: ml2d.h:85
T dotProduct(const Matrix1D< T > &v1, const Matrix1D< T > &v2)
Definition: matrix1d.h:1140
virtual void removeDisabled()
void getFTfromVector(const std::vector< double > &in, const int start_point, MultidimArray< std::complex< double > > &out, bool only_real=false)
#define RAD2DEG(r)
Definition: xmipp_macros.h:320
std::vector< double > sumw2
Definition: mlf_align2d.h:156
double C_fast
Definition: ml2d.h:182
void fourierTranslate2D(const std::vector< double > &in, MultidimArray< double > &trans, std::vector< double > &out, int point_start=0)
FileName fn_ref
Definition: ml2d.h:132
MLF CTF estimated value (double)
std::vector< double > Fwsum_ctfimgs
Definition: mlf_align2d.h:157
std::string String
Definition: xmipp_strings.h:34
void produceSideInfo()
Produce Side information.
Definition: ctf.cpp:1392
double psi(const double x)
size_t max_nr_psi
Definition: mlf_align2d.h:81
std::vector< std::vector< double > > Mwsum_sigma2
Definition: mlf_align2d.h:155
String formatString(const char *format,...)
Definition: ml2d.h:79
void fillLinear(MDLabel label, double initial, double step) override
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=NULL, bool decomposeStack=true) override
double sampling
Definition: mlf_align2d.h:102
#define FN_VSIG(base, ifocus, ext)
Definition: mlf_align2d.h:66
#define realWRAP(x, x0, xF)
Definition: xmipp_macros.h:304
#define VCTF_ITEM
Definition: mlf_align2d.h:47
MultidimArray< double > P_phi
Definition: ml2d.h:178
doublereal * u
String outRefsMd
Definition: ml2d.h:250
bool do_mirror
Definition: ml2d.h:137
double lcdf_tstudent_mlf30(double t)
bool checkParam(const char *param)
double step_size
Definition: histogram.h:127
double sampleNo() const
Definition: histogram.h:350
double Q0
Factor for the importance of the Amplitude contrast.
Definition: ctf.h:261
void processOneImage(const MultidimArray< double > &Mimg, size_t focus, bool apply_ctf, double &fracweight, double &maxweight2, double &sum_refw2, double &opt_scale, size_t &opt_refno, double &opt_psi, size_t &opt_ipsi, size_t &opt_iflip, MultidimArray< double > &opt_offsets, std::vector< double > &opt_offsets_ref, std::vector< double > &pdf_directions, bool do_kstest, bool write_histograms, FileName fn_img, double &KSprob)
Perform expectation step for a single image.
void calculatePdfInplane()
Calculate probability density distribution for in-plane transformations.
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
std::vector< int > pointer_i
Definition: mlf_align2d.h:126
bool fix_sigma_offset
Definition: ml2d.h:141
float r2
size_t nr_images_global
Definition: ml2d.h:164
Mirror fraction for a Maximum Likelihood model.
int idum
Shift for the image in the Y axis (double)
bool setValueCol(const MDObject &mdValueIn) override
size_t zero_trans
Definition: mlf_align2d.h:91
void initZeros(const MultidimArray< T1 > &op)
#define DATALINELENGTH
Definition: ml2d.h:50
size_t dim2
Definition: ml2d.h:151
std::vector< int > count_defocus
Definition: mlf_align2d.h:104
#define FN_CREF_IMG
Definition: mlf_align2d.h:61
#define PI
Definition: tools.h:43
Current iteration number (int)
size_t nr_nomirror_flips
Definition: ml2d.h:162
int getIntParam(const char *param, int arg=0)
Histogram1D sumhist
Definition: mlf_align2d.h:145
void updateWienerFilters(const MultidimArray< double > &spectral_signal, std::vector< double > &sumw_defocus, int iter)
void FFT_magnitude(const MultidimArray< std::complex< double > > &v, MultidimArray< double > &mag)
Definition: xmipp_fftw.cpp:393
Incorrect value received.
Definition: xmipp_error.h:195
std::vector< Image< double > > Iold
Definition: ml2d.h:176
MLF Wiener filter (double)
std::vector< double > conv
Definition: ml2d.h:219
#define VSIG_ITEM
Definition: mlf_align2d.h:49
size_t nr_points_prob
Definition: mlf_align2d.h:127
int * n
Name of an image (std::string)
virtual void writeOutputFiles(const ModelML2D &model, OutputType outputType)
Write out reference images, selfile and logfile.
int threads
Definition: ml2d.h:244
doublereal * a
double sum() const
double sumcorr
Definition: mlf_align2d.h:153
#define intWRAP(x, x0, xF)
Definition: xmipp_macros.h:272
ProgMLF2D(int nr_vols=0, int rank=0, int size=1)
Definition: mlf_align2d.cpp:30
double gammln(double xx)
virtual void endIteration()
Do some task at the end of iteration.
Definition: ml2d.cpp:168
size_t current_image
Definition: ml2d.h:221
void addParamsLine(const String &line)
double eps
Definition: ml2d.h:170
void InverseFourierTransformHalf(const MultidimArray< std::complex< double > > &in, MultidimArray< double > &out, int oridim)
Definition: xmipp_fft.cpp:197
void appendFTtoVector(const MultidimArray< std::complex< double > > &Fin, std::vector< double > &out)
double ini_highres_limit
Definition: mlf_align2d.h:116
MLF Wiener filter (double)
virtual void produceSideInfo()
Setup lots of stuff.
< Score 4 for volumes
std::vector< double > imgs_scale
Definition: ml2d.h:209
String cline
Definition: ml2d.h:134
#define FOR_ALL_MODELS()
Definition: mlf_align2d.h:36
void generateCommandLine(const std::string &command_line, int &argcp, char **&argvp, char *&copy)
Definition: args.cpp:238
std::vector< MultidimArray< double > > wsum_ctfMref
Definition: mlf_align2d.h:154
size_t nr_points_2d
Definition: mlf_align2d.h:127
Seed for random number generator.
double gaussian1D(double x, double sigma, double mu)
std::vector< MultidimArray< double > > Vsig
Definition: mlf_align2d.h:110