Xmipp  v3.23.11-Nereus
ctf.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar S. Sorzano (coss@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "ctf.h"
27 #include "core/multidim_array.h"
28 #include "core/xmipp_fftw.h"
29 #include "core/xmipp_image.h"
30 #include "core/xmipp_program.h"
31 #include "core/metadata_vec.h"
32 
34 {
35  for(int i=0; i < CTF_BASIC_LABELS_SIZE; i++)
37  return false;
38  return true;
39 }
40 
41 void groupCTFMetaData(const MetaDataDb &imgMd, MetaDataDb &ctfMd, std::vector<MDLabel> &groupbyLabels)
42 {
43  //number of different CTFs
44  if (imgMd.containsLabel(MDL_CTF_MODEL))
45  {
48  }
49  else if (containsCTFBasicLabels(imgMd))
50  {
51  groupbyLabels.clear();
52  for(int i=0; i < CTF_ALL_LABELS_SIZE; i++)
53  if (imgMd.containsLabel(CTF_ALL_LABELS[i]))
54  groupbyLabels.push_back(CTF_ALL_LABELS[i]);
56  groupbyLabels.push_back(MDL_MICROGRAPH_ID);
57  else
58  REPORT_ERROR(ERR_MD_MISSINGLABEL,"ERROR: Input metadata does not have micrographId");
59  ctfMd.aggregateGroupBy(imgMd, AGGR_COUNT, groupbyLabels, MDL_CTF_DEFOCUSU, MDL_COUNT);
60  }
61  else
62  REPORT_ERROR(ERR_MD_MISSINGLABEL,"Expecting CTF_MODEL or (MDL_CTF_DEFOCUSU, MDL_CTF_DEFOCUSV, MDL_CTF_DEFOCUS_ANGLE) labels");
63 
64 }
65 
66 
67 void generateCTFImageWith2CTFs(const MetaData &MD1, const MetaData &MD2, int Xdim, MultidimArray<double> &imgOut)
68 {
69  CTFDescription CTF1;
70  CTFDescription CTF2;
71  CTF1.enable_CTF=true;
72  CTF1.enable_CTFnoise=false;
73  CTF1.readFromMetadataRow(MD1,MD1.firstRowId());
74  CTF1.produceSideInfo();
75 
76  CTF2.enable_CTF=true;
77  CTF2.enable_CTFnoise=false;
78  CTF2.readFromMetadataRow(MD2,MD2.firstRowId());
79  CTF2.produceSideInfo();
80 
81  imgOut.initZeros(Xdim,Xdim);
82  Matrix1D<int> idx(2);
83  Matrix1D<double> freq(2);
85  {
86  XX(idx) = j;
87  YY(idx) = i;
88 
89  // Digital frequency
90  FFT_idx2digfreq(imgOut, idx, freq);
91  if (XX(freq)>=0 && XX(freq)<0.5)
92  {
93  digfreq2contfreq(freq, freq, CTF1.Tm);
94  CTF1.precomputeValues(XX(freq),YY(freq));
95  A2D_ELEM(imgOut,i,j)=CTF1.getValueAt();
96  }
97  else
98  {
99  digfreq2contfreq(freq, freq, CTF2.Tm);
100  CTF2.precomputeValues(XX(freq),YY(freq));
101  A2D_ELEM(imgOut,i,j)=CTF2.getValueAt();
102  }
103  }
104  CenterFFT(imgOut,false);
105 }
106 
108  MetaData &MD2,
109  size_t Xdim,
110  double minFreq,
111  double maxFreq)
112 {
113 
114  Matrix1D<double> freq(2); // Frequencies for Fourier plane
115 
116  CTFDescription CTF1;
117  CTFDescription CTF2;
118 
119  CTF1.enable_CTF=true;
120  CTF1.enable_CTFnoise=false;
121  CTF1.readFromMetadataRow(MD1,MD1.firstRowId());
122  CTF1.produceSideInfo();
123 
124  CTF2.enable_CTF=true;
125  CTF2.enable_CTFnoise=false;
126  CTF2.readFromMetadataRow(MD2,MD2.firstRowId());
127  CTF2.produceSideInfo();
128 
129  double iTm=1.0/CTF1.Tm;
130  size_t xDim;
131  size_t yDim;
132  xDim = yDim = Xdim;
133 #define DEBUG
134 #ifdef DEBUG
135 
136  Image<double> img1(xDim,yDim);
137  Image<double> img2(xDim,yDim);
138  Image<double> img3(xDim,yDim);
139 
140  MultidimArray<double> &dummy1 = img1.data;
141  MultidimArray<double> &dummy2 = img2.data;
142  MultidimArray<double> &dummy3 = img3.data;
143 #endif
144 
145  double error =0.;
146  double _freq=0.;
147  minFreq /= CTF1.Tm;
148  maxFreq /= CTF1.Tm;
149 
150  for (int i=0; i<(int)yDim; ++i)
151  {
152  FFT_IDX2DIGFREQ(i, yDim, YY(freq));
153  YY(freq) *= iTm;
154  for (int j=0; j<(int)xDim; ++j)
155  {
156  FFT_IDX2DIGFREQ(j, xDim, XX(freq));
157  XX(freq) *= iTm;
158  _freq = freq.module();
159  if (_freq < minFreq || _freq > maxFreq)
160  continue;
161  //freq *= CTF1.Tm;
162  CTF1.precomputeValues(XX(freq),YY(freq));
163  CTF2.precomputeValues(XX(freq),YY(freq));
164  error += fabs(CTF2.getValuePureWithoutDampingAt()- CTF1.getValuePureWithoutDampingAt());
165 #ifdef DEBUG
166 
167  double a = CTF1.getValuePureWithoutDampingAt();
168  double b = CTF2.getValuePureWithoutDampingAt();
169  DIRECT_A2D_ELEM(dummy1,i,j)=a;
170  DIRECT_A2D_ELEM(dummy2,i,j)=b;
171  DIRECT_A2D_ELEM(dummy3,i,j)=fabs(b-a);
172 #endif
173 
174  }
175  }
176 #ifdef DEBUG
177  img1.write("/tmp/img1.spi");
178  img2.write("/tmp/img2.spi");
179  img3.write("/tmp/img3.spi");
180 #endif
181 #undef DEBUG
182 
183  return error;
184 }
185 
186 
188  double phaseRad)
189 {
190  CTFDescription CTF1;
191 
192  CTF1.enable_CTF=true;
193  CTF1.enable_CTFnoise=false;
194  CTF1.readFromMetadataRow(MD1,MD1.firstRowId());
195  CTF1.produceSideInfo();
196 
197 
198 //#define DEBUG
199 #ifdef DEBUG
200  std::cerr << "DEBUG_ROB: CTF1.DeltaU: " << CTF1.DeltafU << std::endl;
201  std::cerr << "DEBUG_ROB: CTF1.DeltaV: " << CTF1.DeltafV << std::endl;
202  std::cerr << "DEBUG_ROB: var: " << phaseRad/(CTF1.K1*abs(CTF1.DeltafU - CTF1.DeltafV)) << std::endl;
203  std::cerr << "DEBUG_ROB: var: " << sqrt(phaseRad/(CTF1.K1*abs(CTF1.DeltafU - CTF1.DeltafV))) << std::endl;
204  std::cerr << "DEBUG_ROB: var: " << 1/sqrt(phaseRad/(CTF1.K1*abs(CTF1.DeltafU - CTF1.DeltafV))) << std::endl;
205 
206 #endif
207 #undef DEBUG
208  //Armstrong ^-1
209  //K1 = PI / 2 * 2 * lambda;
210  return 1.0/sqrt(phaseRad/(CTF1.K1*abs(CTF1.DeltafU - CTF1.DeltafV)));
211 }
212 
213 
215  MetaData &MD2,
216  size_t Xdim,
217  double phaseRad)
218 {
219  Matrix1D<double> freq(2); // Frequencies for Fourier plane
220 
221  CTFDescription CTF1;
222  CTFDescription CTF2;
223 
224  CTF1.enable_CTF=true;
225  CTF1.enable_CTFnoise=false;
226  CTF1.readFromMetadataRow(MD1,MD1.firstRowId());
227  CTF1.produceSideInfo();
228 
229  CTF2.enable_CTF=true;
230  CTF2.enable_CTFnoise=false;
231  CTF2.readFromMetadataRow(MD2,MD2.firstRowId());
232  CTF2.produceSideInfo();
233 
234  double iTm=1.0/CTF1.Tm;
235  size_t xDim;
236  size_t yDim;
237  xDim = yDim = Xdim;
238 //#define DEBUG
239 #ifdef DEBUG
240 
241  Image<double> arg1(xDim,yDim);
242  Image<double> arg2(xDim,yDim);
243  Image<double> argDiff(xDim,yDim);
244  Image<double> ctf1(xDim,yDim);
245  Image<double> ctf2(xDim,yDim);
246  Image<double> ctfDiff(xDim,yDim);
247  Image<double> aux(xDim,yDim);
248 
249  MultidimArray<double> &arg1Mul = arg1.data;
250  MultidimArray<double> &arg2Mul = arg2.data;
251  MultidimArray<double> &argDiffMul = argDiff.data;
252  MultidimArray<double> &ctf1Mul = ctf1.data;
253  MultidimArray<double> &ctf2Mul = ctf2.data;
254  MultidimArray<double> &ctfDiffMul = ctfDiff.data;
255  MultidimArray<double> &auxMul = aux.data;
256  int counterAux = 0 ;
257 #endif
258 
259  int counter = 0 ;
260  //double _freq=0.;
261  for (int i=0; i<(int)yDim; ++i)
262  {
263  FFT_IDX2DIGFREQ(i, yDim, YY(freq));
264  YY(freq) *= iTm;
265  for (int j=0; j<(int)xDim; ++j)
266  {
267  FFT_IDX2DIGFREQ(j, xDim, XX(freq));
268  XX(freq) *= iTm;
269  //_freq = freq.module();
270  //freq *= CTF1.Tm;
271  CTF1.precomputeValues(XX(freq),YY(freq));
272  CTF2.precomputeValues(XX(freq),YY(freq));
273  double a = CTF1.getValueArgument();
274  double b = CTF2.getValueArgument();
275  if (fabs(b-a) < phaseRad)
276  counter++;
277 #ifdef DEBUG
278  counterAux++;
279  DIRECT_A2D_ELEM(argDiffMul,i,j)=fabs(b-a);
280  DIRECT_A2D_ELEM(arg1Mul,i,j)=a;
281  DIRECT_A2D_ELEM(arg2Mul,i,j)=b;
282  a = CTF1.getValuePureWithoutDampingAt();
283  b = CTF2.getValuePureWithoutDampingAt();
284  DIRECT_A2D_ELEM(ctf1Mul,i,j)=a;
285  DIRECT_A2D_ELEM(ctf2Mul,i,j)=b;
286  DIRECT_A2D_ELEM(ctfDiffMul,i,j)=fabs(b-a);
287 #endif
288 
289  }
290  }
291  double areaLessHalfPIPixels = counter;
292  double totalArePixels = PI*Xdim*Xdim/4.0;
293  double maxFreqA = 1./(2.*CTF1.Tm);
294  double resolutionA_1 = 0;
295  if (areaLessHalfPIPixels > totalArePixels)
296  resolutionA_1 = maxFreqA;
297  else
298  resolutionA_1 = areaLessHalfPIPixels * maxFreqA / totalArePixels;
299  double resolutionA = 1./ resolutionA_1;
300 #ifdef DEBUG
302  R.initIdentity(3);
303  R(2, 0) = 128.;
304  R(2, 1) = 128.;
305  applyGeometry(BSPLINE3, auxMul, arg1Mul, R.transpose(), IS_NOT_INV, true, 0.);
306  aux.write("/tmp/arg1.spi");
307  applyGeometry(BSPLINE3, auxMul, arg2Mul, R.transpose(), IS_NOT_INV, true, 0.);
308  aux.write("/tmp/arg2.spi");
309  applyGeometry(BSPLINE3, auxMul, argDiffMul, R.transpose(), IS_NOT_INV, true, 0.);
310  aux.write("/tmp/argDiff.spi");
311  applyGeometry(BSPLINE3, auxMul, ctf1Mul, R.transpose(), IS_NOT_INV, true, 0.);
312  aux.write("/tmp/ctf1.spi");
313  applyGeometry(BSPLINE3, auxMul, ctf2Mul, R.transpose(), IS_NOT_INV, true, 0.);
314  aux.write("/tmp/ctf2.spi");
315  applyGeometry(BSPLINE3, auxMul, ctfDiffMul, R.transpose(), IS_NOT_INV, true, 0.);
316  aux.write("/tmp/ctfMDiff.spi");
317 
318  std::cerr << "DEBUG_ROB: counter: " << counter << std::endl;
319  std::cerr << "DEBUG_ROB: counterAux: " << counterAux << std::endl;
320  std::cerr << "DEBUG_ROB: res in pixels: " << sqrt (counter/PI) << std::endl;
321  // area < halfpi area whole sprecta normalize to .5
322  std::cerr << "DEBUG_ROB: resolutionA_1: " << resolutionA_1 << std::endl;
323  std::cerr << "DEBUG_ROB: resolutionA: " << resolutionA << std::endl;
324 #endif
325 #undef DEBUG
326  return resolutionA;
327  //divide between area
328 }
329 
331 {
332  img.rangeAdjust(-1,1);
333  CenterFFT(img,false);
334 
336  CTF.enable_CTF=true;
337  CTF.enable_CTFnoise=false;
338  CTF.readFromMetadataRow(MD,MD.firstRowId());
339  CTF.produceSideInfo();
340 
341  Matrix1D<int> idx(2);
342  Matrix1D<double> freq(2);
344  {
345  XX(idx) = j;
346  YY(idx) = i;
347 
348  // Digital frequency
349  FFT_idx2digfreq(img, idx, freq);
350  if (XX(freq)>=0 && XX(freq)<0.5)
351  {
352  digfreq2contfreq(freq, freq, CTF.Tm);
353  CTF.precomputeValues(XX(freq),YY(freq));
354  double aux=CTF.getValueAt();
355  A2D_ELEM(img,i,j)=aux*aux;
356  }
357  }
358  CenterFFT(img,true);
359 }
360 
361 
363 
364 /* Read -------------------------------------------------------------------- */
365 void CTFDescription1D::readFromMdRow(const MDRow &row, bool disable_if_not_K)
366 {
368 
369  if (enable_CTF)
370  {
372  {
383  row.getValueOrDefault(MDL_CTF_K, K, 1);
387  }
388  else if (row.containsLabel(MDL_CTF_MODEL))
389  {
390  FileName fnctf;
391  row.getValue(MDL_CTF_MODEL,fnctf);
392  MetaDataVec ctfparam;
393  ctfparam.read(fnctf);
394  readFromMetadataRow(ctfparam,ctfparam.firstRowId(), disable_if_not_K);
395  }
396 
397  if (K == 0 && disable_if_not_K)
398  enable_CTF = false;
399  }
400  if (enable_CTFnoise)
401  {
414 
415  if (gaussian_K == 0 && sqrt_K == 0 && base_line == 0 && gaussian_K2 == 0 &&
416  disable_if_not_K)
417  enable_CTFnoise = false;
418  }
419 }
420 
421 void CTFDescription1D::readFromMetadataRow(const MetaData &md, size_t id, bool disable_if_not_K)
422 {
423  std::unique_ptr<const MDRow> row = md.getRow(id);
424  readFromMdRow(*row, disable_if_not_K);
425 }
426 
427 void CTFDescription1D::read(const FileName &fn, bool disable_if_not_K)
428 {
429  if (fn.isMetaData())
430  {
431  MetaDataVec md;
432  md.read(fn);
433  MDRowVec row;
434  md.getRow(row, md.firstRowId());
435  readFromMdRow(row, disable_if_not_K);
436  }
437 }
438 
439 /* Write ------------------------------------------------------------------- */
441 {
443  if (enable_CTF)
444  {
447  row.setValue(MDL_CTF_CS, Cs);
448  row.setValue(MDL_CTF_CA, Ca);
454  row.setValue(MDL_CTF_Q0, Q0);
455  row.setValue(MDL_CTF_K, K);
459  }
460  if (enable_CTFnoise)
461  {
474  }
475  if (isLocalCTF)
476  {
477  row.setValue(MDL_CTF_X0, x0);
478  row.setValue(MDL_CTF_XF, xF);
479  row.setValue(MDL_CTF_Y0, y0);
480  row.setValue(MDL_CTF_YF, yF);
481  }
482 }
483 
485 {
486  MDRowVec row;
487  setRow(row);
488 
489  MetaDataVec md;
490  md.setColumnFormat(false);
491  md.addRow(row);
492  md.write(fn);
493 }
494 
495 /* Define Params ------------------------------------------------------------------- */
497 {
498  program->addParamsLine("== CTF1D description");
499  program->addParamsLine(" [--ctf_similar_to++ <ctfFile>] : ctfparam file");
500  program->addParamsLine(" : Parameters from this file are ");
501  program->addParamsLine(" : overriden by the parameters in the command line");
502  program->addParamsLine(" [--sampling_rate <Tm>] : Angstroms/pixel. Ex: 1.4");
503  program->addParamsLine(" : This parameter is compulsory if a CTF is needed.");
504  program->addParamsLine(" [--voltage <kV>] : Accelerating voltage (kV). Ex: 200");
505  program->addParamsLine(" : This parameter is compulsory if a CTF is needed.");
506  program->addParamsLine(" alias --kV;");
507  program->addParamsLine(" [--spherical_aberration <Cs>] : Milimiters. Ex: 5.6");
508  program->addParamsLine(" : This parameter is compulsory if a CTF is needed.");
509  program->addParamsLine(" alias --Cs;");
510  program->addParamsLine(" [--defocusU <Defocus>] : Defocus in Angstroms (Ex: 2000)");
511  program->addParamsLine(" [--chromatic_aberration++ <Ca=0>] : Milimiters. Ex: 2");
512  program->addParamsLine(" [--energy_loss++ <espr=0>] : eV. Ex: 1");
513  program->addParamsLine(" [--lens_stability++ <ispr=0>] : ppm. Ex: 1");
514  program->addParamsLine(" [--convergence_cone++ <alpha=0>] : mrad. Ex: 0.5");
515  program->addParamsLine(" [--longitudinal_displace++ <DeltaF=0>]: Angstrom. Ex: 100");
516  program->addParamsLine(" [--transversal_displace++ <DeltaR=0>] : Angstrom. Ex: 3");
517  program->addParamsLine(" [--Q0++ <Q0=0>] : Percentage of cosine (Q0>0)");
518  program->addParamsLine(" [--K++ <K=0>] : Global gain");
519  program->addParamsLine(" [--phase_shift++ <phase_shift>] : VPP phase shift");
520  program->addParamsLine(" [--VPP_radius++ <VPP_radius>] : phase plate radius");
521 }
522 
523 /* Read from command line -------------------------------------------------- */
525 {
526  kV=Tm=Cs=0;
527  if (program->checkParam("--ctf_similar_to"))
528  read(program->getParam("--ctf_similar_to"));
529  if (program->checkParam("--sampling_rate"))
530  Tm=program->getDoubleParam("--sampling_rate");
531  if (Tm==0)
532  REPORT_ERROR(ERR_ARG_MISSING,"--sampling_rate");
533  if (program->checkParam("--voltage"))
534  kV=program->getDoubleParam("--voltage");
535  if (kV==0)
536  REPORT_ERROR(ERR_ARG_MISSING,"--voltage");
537  if (program->checkParam("--spherical_aberration"))
538  Cs=program->getDoubleParam("--spherical_aberration");
539  if (program->checkParam("--defocusU"))
540  Defocus=program->getDoubleParam("--defocusU");
541  if (program->checkParam("--Q0"))
542  Q0=program->getDoubleParam("--Q0");
543  if (program->checkParam("--phase_shift"))
544  {
545  phase_shift=program->getDoubleParam("--phase_shift");
546  phase_shift=(phase_shift*PI)/180;
547  }
548  else
549  phase_shift = 0.0;
550  if (program->checkParam("--VPP_radius"))
551  VPP_radius=program->getDoubleParam("--VPP_radius");
552  else
553  VPP_radius = 0.0;
554  Ca=program->getDoubleParam("--chromatic_aberration");
555  espr=program->getDoubleParam("--energy_loss");
556  ispr=program->getDoubleParam("--lens_stability");
557  alpha=program->getDoubleParam("--convergence_cone");
558  DeltaF=program->getDoubleParam("--longitudinal_displace");
559  DeltaR=program->getDoubleParam("--transversal_displace");
560  K=program->getDoubleParam("--K");
561 }
562 
563 /* Show -------------------------------------------------------------------- */
564 std::ostream & operator << (std::ostream &out, const CTFDescription1D &ctf)
565 {
566  if (ctf.enable_CTF)
567  {
568  out
569  << "sampling_rate= " << ctf.Tm << std::endl
570  << "voltage= " << ctf.kV << std::endl
571  << "defocusU= " << ctf.Defocus << std::endl
572  << "spherical_aberration= " << ctf.Cs << std::endl
573  << "chromatic_aberration= " << ctf.Ca << std::endl
574  << "energy_loss= " << ctf.espr << std::endl
575  << "lens_stability= " << ctf.ispr << std::endl
576  << "convergence_cone= " << ctf.alpha << std::endl
577  << "longitudinal_displace=" << ctf.DeltaF << std::endl
578  << "transversal_displace= " << ctf.DeltaR << std::endl
579  << "envR0= " << ctf.envR0 << std::endl
580  << "envR1= " << ctf.envR1 << std::endl
581  << "envR2= " << ctf.envR2 << std::endl
582  << "Q0= " << ctf.Q0 << std::endl
583  << "K= " << ctf.K << std::endl
584  ;
585  }
586  if (ctf.enable_CTFnoise)
587  {
588  out
589  << "gaussian_K= " << ctf.gaussian_K << std::endl
590  << "sigma1= " << ctf.sigma1 << std::endl
591  << "Gc1= " << ctf.Gc1 << std::endl
592  << "sqrt_K= " << ctf.sqrt_K << std::endl
593  << "sq= " << ctf.sq << std::endl
594  << "bg1= " << ctf.bgR1 << std::endl
595  << "bg2= " << ctf.bgR2 << std::endl
596  << "bg3= " << ctf.bgR3 << std::endl
597  << "base_line= " << ctf.base_line << std::endl
598  << "gaussian_K2= " << ctf.gaussian_K2 << std::endl
599  << "sigma2= " << ctf.sigma2 << std::endl
600  << "Gc2= " << ctf.Gc2 << std::endl
601  << "phase_shift= " << ctf.phase_shift << std::endl
602  << "VPP_radius= " << ctf.VPP_radius << std::endl
603  ;
604  }
605  return out;
606 }
607 
608 
609 /* Default values ---------------------------------------------------------- */
611 {
612  enable_CTF = true;
613  enable_CTFnoise = false;
614  isLocalCTF = false;
615  clearNoise();
616  clearPureCtf();
617  y0=x0=xF=yF=0;
618 }
619 
621 {
622  base_line = 0;
623  Gc1 = sigma1 = gaussian_K = 0;
624  sq = sqrt_K = 0;
625  Gc2 = sigma2 = gaussian_K2 = 0;
626  bgR1 = bgR2 = bgR3 = 0.0;
627  isLocalCTF = false;
628 }
629 
631 {
632  enable_CTF = true;
633  enable_CTFnoise = false;
634  Tm = 2;
635  kV = 100;
636  Defocus = 0;
637  Cs = Ca = espr = ispr = alpha = DeltaF = DeltaR = 0;
638  K = 1;
639  Q0 = 0;
640  envR0 = envR1 = envR2 = 0.0;
641  isLocalCTF = false;
642 }
643 
644 /* Produce Side Information ------------------------------------------------ */
646 {
647  // Change units
648  double local_Cs = Cs * 1e7;
649  double local_Ca = Ca * 1e7;
650  double local_kV = kV * 1e3;
651  double local_ispr = ispr * 1e6;
652 
653  lambda=12.2643247/sqrt(local_kV*(1.+0.978466e-6*local_kV)); // See http://en.wikipedia.org/wiki/Electron_diffraction
654  //
655  // Phase shift for spherical aberration
656  // X(u)=-PI*deltaf(u)*lambda*u^2+PI/2*Cs*lambda^3*u^4
657  // ICE: X(u)=-PI/2*deltaf(u)*lambda*u^2+PI/2*Cs*lambda^3*u^4
658  // = K1*deltaf(u)*u^2 +K2*u^4
659  K1 = PI * lambda;
660  K2 = PI / 2 * local_Cs * lambda * lambda * lambda;
661 
662  // Envelope
663  // D(u)=Ed(u)*Ealpha(u)
664  // Ed(u)=exp(-1/2*PI^2*lambda^2*D^2*u^4)
665  // Ealpha(u)=exp(-PI^2*alpha^2*u^2*(Cs*lambda^2*u^2+Deltaf(u))^2)
666  // ICE: Eespr(u)=exp(-(1/4*PI*Ca*lambda*espr/kV)^2*u^4/log2)
667  // ICE: Eispr(u)=exp(-(1/2*PI*Ca*lambda*ispr)^2*u^4/log2)
668  // ICE: EdeltaF(u)=bessj0(PI*DeltaF*lambda*u^2)
669  // ICE: EdeltaR(u)=sinc(u*DeltaR)
670  // ICE: Ealpha(u)=exp(-PI^2*alpha^2*(Cs*lambda^2*u^3+Deltaf(u)*u)^2)
671  // CO: K3=pow(0.25*PI*Ca*lambda*(espr/kV,2)/log(2); Both combines in new K3
672  // CO: K4=pow(0.5*PI*Ca*lambda*ispr,2)/log(2);
673  K3 = pow(0.25 * PI * local_Ca * lambda * (espr / kV + 2 * local_ispr), 2) / log(2.0);
674  K5 = PI * DeltaF * lambda;
675  K6 = PI * PI * alpha * alpha;
676  K7 = local_Cs * lambda * lambda;
677  Ksin = sqrt(1-Q0*Q0);
678  Kcos = Q0;
679 }
680 
681 /* Precompute values ------------------------------------------------------- */
683 {
684  precomputedImage.reserve(MULTIDIM_SIZE(cont_x_freq));
685  precomputedImageXdim=XSIZE(cont_x_freq);
686 
687  FOR_ALL_ELEMENTS_IN_ARRAY2D(cont_x_freq)
688  {
689  double X=A2D_ELEM(cont_x_freq,i,j);
690  precomputeValues(X);
691  if (fabs(X) < XMIPP_EQUAL_ACCURACY)
693  else
694  precomputed.deltaf=-1;
695  precomputedImage.push_back(precomputed);
696  }
697 }
698 
699 /* Look for zeroes, maxima or minima ------------------------------------------------------------ */
700 //#define DEBUG
701 void CTFDescription1D::lookFor(int n, const Matrix1D<double> &u, Matrix1D<double> &freq, int iwhat)
702 {
703  double wmax = 1 / (2 * Tm);
704  double wstep = wmax / 300;
705  int found = 0;
706  double last_ctf = getValuePureNoPrecomputedAt(0);
707  double ctf=0.0;
708  double state=1;
709 
710  double w = 0;
711 
712  while (w <= wmax)
713  {
714  V2_BY_CT(freq, u, w);
715  ctf = getValuePureNoPrecomputedAt(XX(freq));
716 
717  switch (iwhat)
718  {
719  case 0: // Looking for zeroes
720  if (SGN(ctf) != SGN(last_ctf))
721  found++;
722  break;
723  case 1: // Looking for maxima
724  if (w>0)
725  {
726  if (state==1) // Going up
727  {
728  if (ctf<last_ctf)
729  {
730  found++;
731  state=-1;
732  }
733  }
734  else // Going down
735  {
736  if (ctf>last_ctf)
737  state=1;
738  }
739  }
740  break;
741  case -1: // Looking for minima
742  if (w>0)
743  {
744  if (state==-1) // Going down
745  {
746  if (ctf>last_ctf)
747  {
748  found++;
749  state=1;
750  }
751  }
752  else // Going up
753  {
754  if (ctf<last_ctf)
755  state=-1;
756  }
757  }
758  break;
759  }
760  if (found == n)
761  {
762  break;
763  }
764 
765  last_ctf = ctf;
766  w += wstep;
767  }
768  if (found != n)
769  {
770 
771  VECTOR_R2(freq, -1, -1);
772  }
773  else
774  {
775  // Compute more accurate zero
776 #ifdef DEBUG
777  std::cout << n << " zero: w=" << w << " (" << wmax << ") freq="
778  << (u*w).transpose()
779  << " last_ctf=" << last_ctf << " ctf=" << ctf << " ";
780 #endif
781 
782  switch (iwhat)
783  {
784  case 0:
785  w += ctf * wstep / (last_ctf - ctf);
786  break;
787  default:
788  w-=wstep;
789  }
790  V2_BY_CT(freq, u, w);
791 #ifdef DEBUG
792 
793  std::cout << " final w= " << w << " final freq=" << freq.transpose() << std::endl;
794 #endif
795  }
796 }
797 #undef DEBUG
798 
799 /* Apply the CTF to an image ----------------------------------------------- */
800 void CTFDescription1D::applyCTF(MultidimArray < std::complex<double> > &FFTI, const MultidimArray<double> &I, double Ts, bool absPhase)
801 {
802  Matrix1D<int> idx(2);
803  Matrix1D<double> freq(2);
804  if ( ZSIZE(FFTI) > 1 )
805  REPORT_ERROR(ERR_MULTIDIM_DIM,"ERROR: Apply_CTF only works on 2D images, not 3D.");
806 
807  double iTs=1.0/Ts;
809  {
810  XX(idx) = j;
811  YY(idx) = i;
812  FFT_idx2digfreq(I, idx, freq);
813  precomputeValues(XX(freq)*iTs);
814  double ctf = getValueAt();
815  if (absPhase)
816  ctf=fabs(ctf);
817  A2D_ELEM(FFTI, i, j) *= ctf;
818  }
819 }
820 
821 void CTFDescription1D::applyCTF(MultidimArray <double> &I, double Ts, bool absPhase)
822 {
823  FourierTransformer transformer;
825  transformer.setReal(I);
826  transformer.FourierTransform();
827  applyCTF(transformer.fFourier, I, Ts, absPhase);
828  transformer.inverseFourierTransform();
829 }
830 
831 /* Apply the CTF to an image ----------------------------------------------- */
832 void CTFDescription1D::correctPhase(MultidimArray < std::complex<double> > &FFTI, const MultidimArray<double> &I, double Ts)
833 {
834  Matrix1D<int> idx(2);
835  Matrix1D<double> freq(2);
836  if ( ZSIZE(FFTI) > 1 )
837  REPORT_ERROR(ERR_MULTIDIM_DIM,"ERROR: Correct phase only works on 2D images, not 3D.");
838 
839  double iTs=1.0/Ts;
841  {
842  XX(idx) = j;
843  YY(idx) = i;
844  FFT_idx2digfreq(I, idx, freq);
845  precomputeValues(XX(freq)*iTs);
846  double ctf = getValuePureAt();
847  if (ctf<0)
848  A2D_ELEM(FFTI, i, j) *= -1;
849  }
850 }
851 
853 {
854  FourierTransformer transformer;
856  transformer.setReal(I);
857  transformer.FourierTransform();
858  correctPhase(transformer.fFourier, I, Ts);
859  transformer.inverseFourierTransform();
860 }
861 
862 /* Get profiles ------------------------------------------------------------ */
863 void CTFDescription1D::getProfile(double fmax, int nsamples,
864  MultidimArray<double> &profiles)
865 {
866  double step = fmax / nsamples;
867 
868  profiles.resizeNoCopy(nsamples, 4);
869  //double sinus = sin(angle);
870  //double cosinus = cos(angle);
871  double f;
872  size_t i;
873 
874  for (i = 0, f = 0; i < YSIZE(profiles); i++, f += step)
875  {
876  double fx = f;
877 
878  // Compute current frequencies.
879  precomputeValues(fx);
880 
881  // Store values.
882  double bgNoise = getValueNoiseAt();
883  double ctf = getValuePureAt();
884  double E = getValueDampingAt();
885 
886  A2D_ELEM(profiles, i, 0) = 10*log10(bgNoise);
887  A2D_ELEM(profiles, i, 1) = 10*log10(bgNoise + E * E);
888  A2D_ELEM(profiles, i, 2) = 10*log10(bgNoise + ctf * ctf);
889  A2D_ELEM(profiles, i, 3) = getValuePureNoKAt();
890  }
891 }
892 
893 /* Get average profiles ----------------------------------------------------- */
894 void CTFDescription1D::getAverageProfile(double fmax, int nsamples,
895  MultidimArray<double> &profiles)
896 {
897  double step = fmax / nsamples;
898  profiles.initZeros(nsamples, 4);
899 
900  for (int angle=0; angle < 360; angle++) //Angulo??? En 1D no hay. Con que itero?
901  {
902  double angle2 = float(angle);
903  double cosinus = cos(angle2);
904  double f;
905  size_t i;
906  for (i = 0, f = 0; i < YSIZE(profiles); i++, f += step)
907  {
908  double fx = f * cosinus;
909 
910  // Compute current frequencies.
911  precomputeValues(fx);
912 
913  // Store values.
914  double bgNoise = getValueNoiseAt();
915  double ctf = getValuePureAt();
916  double E = getValueDampingAt();
917 
918  A2D_ELEM(profiles, i, 0) += 10*log10(bgNoise);
919  A2D_ELEM(profiles, i, 1) += 10*log10(bgNoise + E * E);
920  A2D_ELEM(profiles, i, 2) += 10*log10(bgNoise + ctf * ctf);
921  A2D_ELEM(profiles, i, 3) += getValuePureNoKAt();
922  }
923  }
924  profiles*=1.0/360;
925 }
926 
927 /* Physical meaning -------------------------------------------------------- */
928 //#define DEBUG
930 {
931  bool retval;
932  if (enable_CTF)
933  {
934  precomputeValues(0);
935  retval =
936  K >= 0 && base_line >= 0 &&
937  kV >= 50 && kV <= 1000 &&
938  espr >= 0 && espr <= 20 &&
939  ispr >= 0 && ispr <= 20 &&
940  Cs >= 0 && Cs <= 20 &&
941  Ca >= 0 && Ca <= 7 &&
942  alpha >= 0 && alpha <= 5 &&
943  DeltaF >= 0 && DeltaF <= 1000 &&
944  DeltaR >= 0 && DeltaR <= 100 &&
945  Q0 >= 0 && Q0 <= 0.40 &&
946  Defocus >= 0 && getValueAt() >= 0;
947 #ifdef DEBUG
948 
949  if (retval == false)
950  {
951  std::cout << *this << std::endl;
952  std::cout << "K>=0 && base_line>=0 " << (K >= 0 && base_line >= 0) << std::endl
953  << "kV>=50 && kV<=1000 " << (kV >= 50 && kV <= 1000) << std::endl
954  << "espr>=0 && espr<=20 " << (espr >= 0 && espr <= 20) << std::endl
955  << "ispr>=0 && ispr<=20 " << (ispr >= 0 && ispr <= 20) << std::endl
956  << "Cs>=0 && Cs<=20 " << (Cs >= 0 && Cs <= 20) << std::endl
957  << "Ca>=0 && Ca<=3 " << (Ca >= 0 && Ca <= 3) << std::endl
958  << "alpha>=0 && alpha<=5 " << (alpha >= 0 && alpha <= 5) << std::endl
959  << "DeltaF>=0 && DeltaF<=1000 " << (DeltaF >= 0 && DeltaF <= 1000) << std::endl
960  << "DeltaR>=0 && DeltaR<=100 " << (DeltaR >= 0 && DeltaR <= 100) << std::endl
961  << "Q0>=0 && Q0<=0.4 " << (Q0 >= 0 && Q0 <= 0.4) << std::endl
962  << "Defocus>=0 " << (DeltafU >= 0 << std::endl
963  << "getValueAt(0,0)>=0 " << (getValueAt() >= 0) << std::endl
964  ;
965  std::cout << "getValueAt(0,0)=" << getValueAt(true) << std::endl;
966  }
967 #endif
968 
969  }
970  else
971  retval = true;
972  bool retval2;
973  if (enable_CTFnoise)
974  {
975  double min_sigma = XMIPP_MIN(sigma1, sigma1);
976  double min_c = XMIPP_MIN(Gc1, Gc1);
977  double min_sigma2 = XMIPP_MIN(sigma2, sigma2);
978  double min_c2 = XMIPP_MIN(Gc2, Gc2);
979  retval2 =
980  base_line >= 0 &&
981  gaussian_K >= 0 &&
982  sigma1 >= 0 &&
983  sigma1 <= 100e3 &&
984  Gc1 >= 0 &&
985  sq >= 0 &&
986  sqrt_K >= 0 &&
987  gaussian_K2 >= 0 &&
988  sigma2 >= 0 &&
989  sigma2 <= 100e3 &&
990  Gc2 >= 0 &&
991  phase_shift >= 0.0 && phase_shift <= 3.14
992  ;
993 
994  if (min_sigma > 0)
995  retval2 = retval2 && sigma1 / min_sigma <= 3;
996  if (min_c > 0)
997  retval2 = retval2 && Gc1 / min_c <= 3;
998  if (gaussian_K != 0)
999  retval2 = retval2 && (Gc1 * Tm >= 0.01);
1000  if (min_sigma2 > 0)
1001  retval2 = retval2 && sigma2 / min_sigma2 <= 3;
1002  if (min_c2 > 0)
1003  retval2 = retval2 && Gc2 / min_c2 <= 3;
1004  if (gaussian_K2 != 0)
1005  retval2 = retval2 && (Gc2 * Tm >= 0.01);
1006 
1007 #ifdef DEBUG
1008 
1009  if (retval2 == false)
1010  {
1011  std::cout << *this << std::endl;
1012  std::cout << "base_line>=0 && " << (base_line >= 0) << std::endl
1013  << "gaussian_K>=0 && " << (gaussian_K >= 0) << std::endl
1014  << "sigmaU>=0 && sigmaV>=0 " << (sigmaU >= 0 && sigmaV >= 0) << std::endl
1015  << "sigmaU<=100e3 && sigmaV<=100e3 " << (sigmaU <= 100e3 && sigmaV <= 100e3) << std::endl
1016  << "cU>=0 && cV>=0 " << (cU >= 0 && cV >= 0) << std::endl
1017  << "sqU>=0 && sqV>=0 " << (sqU >= 0 && sqV >= 0) << std::endl
1018  << "sqrt_K>=0 && " << (sqrt_K >= 0) << std::endl
1019  << "gaussian_K2>=0 && " << (gaussian_K2 >= 0) << std::endl
1020  << "sigmaU2>=0 && sigmaV2>=0 " << (sigmaU2 >= 0 && sigmaV2 >= 0) << std::endl
1021  << "sigmaU2<=100e3 && sigmaV2<=100e3 " << (sigmaU2 <= 100e3 && sigmaV2 <= 100e3) << std::endl
1022  << "cU2>=0 && cV2>=0 " << (cU2 >= 0 && cV2 >= 0) << std::endl
1023  << "gaussian_angle>=0 && gaussian_angle<=90 " << (gaussian_angle >= 0 && gaussian_angle <= 90) << std::endl
1024  << "sqrt_angle>=0 && sqrt_angle<=90 " << (sqrt_angle >= 0 && sqrt_angle <= 90) << std::endl
1025  << "gaussian_angle2>=0 && gaussian_angle2<=90 " << (gaussian_angle2 >= 0 && gaussian_angle2 <= 90) << std::endl
1026  ;
1027  if (min_sigma > 0)
1028  std::cout << "ABS(sigmaU-sigmaV)/min_sigma<=3 " << (ABS(sigmaU - sigmaV) / min_sigma <= 3) << std::endl;
1029  if (min_c > 0)
1030  std::cout << "ABS(cU-cV)/min_c<=3 " << (ABS(cU - cV) / min_c <= 3) << std::endl;
1031  if (gaussian_K > 0)
1032  std::cout << "(cU*Tm>=0.01) && (cV*Tm>=0.01) " << ((cU*Tm >= 0.01) && (cV*Tm >= 0.01)) << std::endl;
1033  if (min_sigma2 > 0)
1034  std::cout << "ABS(sigmaU2-sigmaV2)/min_sigma2<=3 " << (ABS(sigmaU2 - sigmaV2) / min_sigma2 <= 3) << std::endl;
1035  if (min_c2 > 0)
1036  std::cout << "ABS(cU2-cV2)/min_c2<=3 " << (ABS(cU2 - cV2) / min_c2 <= 3) << std::endl;
1037  if (gaussian_K2 > 0)
1038  std::cout << "(cU2*Tm>=0.01) && (cV2*Tm>=0.01) " << ((cU2*Tm >= 0.01) && (cV2*Tm >= 0.01)) << std::endl;
1039  std::cout << cV2*Tm << std::endl;
1040  }
1041 #endif
1042 
1043  }
1044  else
1045  retval2 = true;
1046 #ifdef DEBUG
1047 
1048 #endif
1049 
1050  return retval && retval2;
1051 }
1052 #undef DEBUG
1053 
1054 /* Force Physical meaning -------------------------------------------------- */
1056 {
1057  if (enable_CTF)
1058  {
1059  if (K < 0)
1060  K = 0;
1061  if (base_line < 0)
1062  base_line = 0;
1063  if (kV < 50)
1064  kV = 50;
1065  if (kV > 1000)
1066  kV = 1000;
1067  if (espr < 0)
1068  espr = 0;
1069  if (espr > 20)
1070  espr = 20;
1071  if (ispr < 0)
1072  ispr = 0;
1073  if (ispr > 20)
1074  ispr = 20;
1075  if (Cs < 0)
1076  Cs = 0;
1077  if (Cs > 20)
1078  Cs = 20;
1079  if (Ca < 0)
1080  Ca = 0;
1081  if (Ca > 3)
1082  Ca = 3;
1083  if (alpha < 0)
1084  alpha = 0;
1085  if (alpha > 5)
1086  alpha = 5;
1087  if (DeltaF < 0)
1088  DeltaF = 0;
1089  if (DeltaF > 1000)
1090  DeltaF = 1000;
1091  if (DeltaR < 0)
1092  DeltaR = 0;
1093  if (DeltaR > 1000)
1094  DeltaR = 1000;
1095  if (Q0 > 0.40)
1096  Q0 = 0.40;
1097  if (Q0 < 0)
1098  Q0 = 0;
1099  if (Defocus < 0)
1100  Defocus = 0;
1101 
1102  }
1103  if (enable_CTFnoise)
1104  {
1105  double min_sigma = XMIPP_MIN(sigma1, sigma1);
1106  double min_c = XMIPP_MIN(Gc1, Gc1);
1107  double min_sigma2 = XMIPP_MIN(sigma2, sigma2);
1108  double min_c2 = XMIPP_MIN(Gc2, Gc2);
1109  if (base_line < 0)
1110  base_line = 0;
1111  if (gaussian_K < 0)
1112  gaussian_K = 0;
1113  if (sigma1 < 0)
1114  sigma1 = 0;
1115  if (sigma1 > 100e3)
1116  sigma1 = 100e3;
1117  if (Gc1 < 0)
1118  Gc1 = 0;
1119  if (sq < 0)
1120  sq = 0;
1121  if (sqrt_K < 0)
1122  sqrt_K = 0;
1123  if (gaussian_K2 < 0)
1124  gaussian_K2 = 0;
1125  if (sigma2 < 0)
1126  sigma2 = 0;
1127  if (sigma2 > 100e3)
1128  sigma2 = 100e3;
1129  if (Gc2 < 0)
1130  Gc2 = 0;
1131  if (min_sigma > 0)
1132  if (sigma1 / min_sigma > 3)
1133  {
1134  sigma1 = 3.9 * sigma1;
1135  }
1136  if (min_c > 0)
1137  if (Gc1 / min_c > 3)
1138  {
1139  Gc1 = 3.9 * Gc1;
1140  }
1141  if (gaussian_K != 0)
1142  {
1143  if (Gc1*Tm < 0.01)
1144  Gc1 = 0.011 / Tm;
1145  }
1146  if (min_sigma2 > 0)
1147  if (sigma2 / min_sigma2 > 3)
1148  {
1149  sigma2 = 3.9 * sigma2;
1150  }
1151  if (min_c2 > 0)
1152  if (Gc2 / min_c2 > 3)
1153  {
1154  Gc2 = 3.9 * Gc2;
1155  }
1156  if (gaussian_K2 != 0)
1157  {
1158  if (Gc2*Tm < 0.01)
1159  Gc2 = 0.011 / Tm;
1160  }
1161  if (phase_shift > PI || phase_shift < -PI) //Normalize phase shift between 0-PI
1162  {
1163  phase_shift = realWRAP(phase_shift,-PI,PI);//phase_shift - floor(phase_shift/3.14)*3.14;
1164  }
1165  }
1166 }
1167 #undef DEBUG
1168 
1170 
1171 /* Read -------------------------------------------------------------------- */
1172 void CTFDescription::readFromMdRow(const MDRow &row, bool disable_if_not_K)
1173 {
1174  CTFDescription1D::readFromMdRow(row, disable_if_not_K);
1175  if (enable_CTF)
1176  {
1178  {
1179  row.getValueOrDefault(MDL_CTF_DEFOCUSU, DeltafU, 0);
1180  row.getValueOrDefault(MDL_CTF_DEFOCUSV, DeltafV, DeltafU);
1181  row.getValueOrDefault(MDL_CTF_DEFOCUS_ANGLE, azimuthal_angle, 0);
1184 
1185  }
1186  else if (row.containsLabel(MDL_CTF_MODEL))
1187  {
1188  FileName fnctf;
1189  row.getValue(MDL_CTF_MODEL,fnctf);
1190  MetaDataVec ctfparam;
1191  ctfparam.read(fnctf);
1192  readFromMetadataRow(ctfparam, ctfparam.firstRowId(), disable_if_not_K);
1193  }
1194 
1195  }
1196  if (enable_CTFnoise)
1197  {
1199  row.getValueOrDefault(MDL_CTF_BG_GAUSSIAN_SIGMAV, sigmaV, sigmaU);
1202  row.getValueOrDefault(MDL_CTF_BG_GAUSSIAN_ANGLE, gaussian_angle, 0);
1203  row.getValueOrDefault(MDL_CTF_BG_SQRT_U, sqU, 0);
1204  row.getValueOrDefault(MDL_CTF_BG_SQRT_V, sqV, sqU);
1205  row.getValueOrDefault(MDL_CTF_BG_SQRT_ANGLE, sqrt_angle, 0);
1207  row.getValueOrDefault(MDL_CTF_BG_GAUSSIAN2_SIGMAV, sigmaV2, sigmaU2);
1210  row.getValueOrDefault(MDL_CTF_BG_GAUSSIAN2_ANGLE, gaussian_angle2, 0);
1211  }
1212 }
1213 
1214 void CTFDescription::readFromMetadataRow(const MetaData &md, size_t id, bool disable_if_not_K)
1215 {
1216  std::unique_ptr<const MDRow> row = md.getRow(id);
1217  readFromMdRow(*row, disable_if_not_K);
1218 }
1219 
1220 void CTFDescription::read(const FileName &fn, bool disable_if_not_K)
1221 {
1222  if (fn.isMetaData())
1223  {
1224  MetaDataVec md;
1225  md.read(fn);
1226  MDRowVec row;
1227  md.getRow(row, md.firstRowId());
1228  readFromMdRow(row, disable_if_not_K);
1229  }
1230 }
1231 
1232 /* Write ------------------------------------------------------------------- */
1234 {
1236  if (enable_CTF)
1237  {
1238  row.setValue(MDL_CTF_DEFOCUSU, DeltafU);
1239  row.setValue(MDL_CTF_DEFOCUSV, DeltafV);
1240  row.setValue(MDL_CTF_DEFOCUS_ANGLE, azimuthal_angle);
1241 
1242  }
1243  if (enable_CTFnoise)
1244  {
1245  row.setValue(MDL_CTF_BG_GAUSSIAN_SIGMAU, sigmaU);
1246  row.setValue(MDL_CTF_BG_GAUSSIAN_SIGMAV, sigmaV);
1249  row.setValue(MDL_CTF_BG_GAUSSIAN_ANGLE, gaussian_angle);
1250  row.setValue(MDL_CTF_BG_SQRT_U, sqU);
1251  row.setValue(MDL_CTF_BG_SQRT_V, sqV);
1252  row.setValue(MDL_CTF_BG_SQRT_ANGLE, sqrt_angle);
1253  row.setValue(MDL_CTF_BG_GAUSSIAN2_SIGMAU, sigmaU2);
1254  row.setValue(MDL_CTF_BG_GAUSSIAN2_SIGMAV, sigmaV2);
1257  row.setValue(MDL_CTF_BG_GAUSSIAN2_ANGLE, gaussian_angle2);
1258  if(VPP_radius != 0.0)
1259  {
1262  }
1263 
1264 
1265  }
1266  if (isLocalCTF)
1267  {
1268  row.setValue(MDL_CTF_X0, x0);
1269  row.setValue(MDL_CTF_XF, xF);
1270  row.setValue(MDL_CTF_Y0, y0);
1271  row.setValue(MDL_CTF_YF, yF);
1272  }
1273 }
1274 
1276 {
1277  MDRowVec row;
1278  setRow(row);
1279 
1280  MetaDataVec md;
1281  md.setColumnFormat(false);
1282  md.addRow(row);
1283  md.write(fn);
1284 }
1285 
1286 /* Define Params ------------------------------------------------------------------- */
1288 {
1290  program->addParamsLine("== CTF 2D description");
1291  program->addParamsLine(" [--defocusV++ <DeltafV>] : If astigmatic");
1292  program->addParamsLine(" [--azimuthal_angle++ <ang=0>] : Angle between X and U (degrees)");
1293 
1294 }
1295 
1296 /* Read from command line -------------------------------------------------- */
1298 {
1300  if (program->checkParam("--defocusU"))
1301  DeltafU=program->getDoubleParam("--defocusU");
1302  if (program->checkParam("--defocusV"))
1303  DeltafV=program->getDoubleParam("--defocusV");
1304  else
1305  DeltafV=DeltafU;
1306  azimuthal_angle=program->getDoubleParam("--azimuthal_angle");
1307 }
1308 
1309 /* Show -------------------------------------------------------------------- */
1310 std::ostream & operator << (std::ostream &out, const CTFDescription &ctf)
1311 {
1312  if (ctf.enable_CTF)
1313  {
1314  out
1315  << "sampling_rate= " << ctf.Tm << std::endl
1316  << "voltage= " << ctf.kV << std::endl
1317  << "defocusU= " << ctf.DeltafU << std::endl
1318  << "defocusV= " << ctf.DeltafV << std::endl
1319  << "azimuthal_angle= " << ctf.azimuthal_angle << std::endl
1320  << "spherical_aberration= " << ctf.Cs << std::endl
1321  << "chromatic_aberration= " << ctf.Ca << std::endl
1322  << "energy_loss= " << ctf.espr << std::endl
1323  << "lens_stability= " << ctf.ispr << std::endl
1324  << "convergence_cone= " << ctf.alpha << std::endl
1325  << "longitudinal_displace=" << ctf.DeltaF << std::endl
1326  << "transversal_displace= " << ctf.DeltaR << std::endl
1327  << "envR0= " << ctf.envR0 << std::endl
1328  << "envR1= " << ctf.envR1 << std::endl
1329  << "envR2= " << ctf.envR2 << std::endl
1330  << "Q0= " << ctf.Q0 << std::endl
1331  << "K= " << ctf.K << std::endl
1332  ;
1333  }
1334  if (ctf.enable_CTFnoise)
1335  {
1336  out
1337  << "gaussian_K= " << ctf.gaussian_K << std::endl
1338  << "sigmaU= " << ctf.sigmaU << std::endl
1339  << "sigmaV= " << ctf.sigmaV << std::endl
1340  << "cU= " << ctf.cU << std::endl
1341  << "cV= " << ctf.cV << std::endl
1342  << "gaussian_angle= " << ctf.gaussian_angle << std::endl
1343  << "sqrt_K= " << ctf.sqrt_K << std::endl
1344  << "sqU= " << ctf.sqU << std::endl
1345  << "sqV= " << ctf.sqV << std::endl
1346  << "sqrt_angle= " << ctf.sqrt_angle << std::endl
1347  << "bg1= " << ctf.bgR1 << std::endl
1348  << "bg2= " << ctf.bgR2 << std::endl
1349  << "bg3= " << ctf.bgR3 << std::endl
1350  << "base_line= " << ctf.base_line << std::endl
1351  << "gaussian_K2= " << ctf.gaussian_K2 << std::endl
1352  << "sigmaU2= " << ctf.sigmaU2 << std::endl
1353  << "sigmaV2= " << ctf.sigmaV2 << std::endl
1354  << "cU2= " << ctf.cU2 << std::endl
1355  << "cV2= " << ctf.cV2 << std::endl
1356  << "gaussian_angle2= " << ctf.gaussian_angle2 << std::endl
1357  << "phase_shift= " << ctf.phase_shift << std::endl
1358  << "VPP_radius= " << ctf.VPP_radius << std::endl
1359  ;
1360  }
1361  return out;
1362 }
1363 
1364 
1365 /* Default values ---------------------------------------------------------- */
1367 {
1369  clearNoise();
1370  clearPureCtf();
1371 }
1372 
1374 {
1375  base_line = 0;
1376  cU = cV = sigmaU = sigmaV = gaussian_angle = gaussian_K = 0;
1377  sqU = sqV = sqrt_K = sqrt_angle = 0;
1378  cU2 = cV2 = sigmaU2 = sigmaV2 = gaussian_angle2 = gaussian_K2 = 0;
1379  bgR1 = bgR2 = bgR3 = 0.0;
1380  VPP_radius = phase_shift = 0.0;
1381  isLocalCTF = false;
1382 }
1383 
1385 {
1387  DeltafU = DeltafV = azimuthal_angle = 0;
1388 }
1389 
1390 
1391 /* Produce Side Information ------------------------------------------------ */
1393 {
1395  // Add parameters for 2D
1396  rad_azimuth = DEG2RAD(azimuthal_angle);
1397  rad_gaussian = DEG2RAD(gaussian_angle);
1398  rad_gaussian2 = DEG2RAD(gaussian_angle2);
1399  rad_sqrt = DEG2RAD(sqrt_angle);
1400  defocus_average = -(DeltafU + DeltafV) * 0.5;
1401  defocus_deviation = -(DeltafU - DeltafV) * 0.5;
1402 }
1403 
1404 
1405 /* Precompute values ------------------------------------------------------- */
1407  const MultidimArray<double> &cont_y_freq)
1408 {
1409  precomputedImage.reserve(MULTIDIM_SIZE(cont_x_freq));
1410  precomputedImageXdim=XSIZE(cont_x_freq);
1411 
1412  FOR_ALL_ELEMENTS_IN_ARRAY2D(cont_x_freq)
1413  {
1414  double X=A2D_ELEM(cont_x_freq,i,j);
1415  double Y=A2D_ELEM(cont_y_freq,i,j);
1416  precomputeValues(X, Y);
1417  if (fabs(X) < XMIPP_EQUAL_ACCURACY &&
1418  fabs(Y) < XMIPP_EQUAL_ACCURACY)
1419  precomputed.deltaf=0;
1420  else
1421  precomputed.deltaf=-1;
1422  precomputedImage.push_back(precomputed);
1423  }
1424 }
1425 
1426 /* Look for zeroes, maxima or minima ------------------------------------------------------------ */
1427 //#define DEBUG
1428 void CTFDescription::lookFor(int n, const Matrix1D<double> &u, Matrix1D<double> &freq, int iwhat)
1429 {
1430  double wmax = 1 / (2 * Tm);
1431  double wstep = wmax / 300;
1432  int found = 0;
1433  double last_ctf = getValuePureNoDampingNoPrecomputedAt(0,0);
1434  double ctf=0.0;
1435  double state=1; //getValuePureWithoutDampingAt()
1436  double w = 0;
1437  while (w <= wmax)
1438  {
1439  V2_BY_CT(freq, u, w);
1440  ctf = getValuePureNoDampingNoPrecomputedAt(XX(freq),YY(freq));
1441  switch (iwhat)
1442  {
1443  case 0: // Looking for zeroes
1444  if (SGN(ctf) != SGN(last_ctf))
1445  found++;
1446  break;
1447  case 1: // Looking for maxima
1448  if (w>0)
1449  {
1450  if (state==1) // Going up
1451  {
1452  if (ctf<last_ctf)
1453  {
1454  found++;
1455  state=-1;
1456  }
1457  }
1458  else // Going down
1459  {
1460  if (ctf>last_ctf)
1461  state=1;
1462  }
1463  }
1464  break;
1465  case -1: // Looking for minima
1466  if (w>0)
1467  {
1468  if (state==-1) // Going down
1469  {
1470  if (ctf>last_ctf)
1471  {
1472  found++;
1473  state=1;
1474  }
1475  }
1476  else // Going up
1477  {
1478  if (ctf<last_ctf)
1479  state=-1;
1480  }
1481  }
1482  break;
1483  }
1484  if (found == n)
1485  break;
1486 
1487  last_ctf = ctf;
1488  w += wstep;
1489  }
1490  if (found != n)
1491  {
1492  VECTOR_R2(freq, -1, -1);
1493  }
1494  else
1495  {
1496  // Compute more accurate zero
1497 #ifdef DEBUG
1498  std::cout << n << " zero: w=" << w << " (" << wmax << ") freq="
1499  << (u*w).transpose()
1500  << " last_ctf=" << last_ctf << " ctf=" << ctf << " ";
1501 #endif
1502 
1503  switch (iwhat)
1504  {
1505  case 0:
1506  w += ctf * wstep / (last_ctf - ctf);
1507  break;
1508  default:
1509  w-=wstep;
1510  }
1511  V2_BY_CT(freq, u, w);
1512 #ifdef DEBUG
1513 
1514  std::cout << " final w= " << w << " final freq=" << freq.transpose() << std::endl;
1515 #endif
1516  }
1517 }
1518 #undef DEBUG
1519 
1520 /* Apply the CTF to an image ----------------------------------------------- */
1521 void CTFDescription::applyCTF(MultidimArray < std::complex<double> > &FFTI, const MultidimArray<double> &I, double Ts, bool absPhase)
1522 {
1523  Matrix1D<int> idx(2);
1524  Matrix1D<double> freq(2);
1525  if ( ZSIZE(FFTI) > 1 )
1526  REPORT_ERROR(ERR_MULTIDIM_DIM,"ERROR: Apply_CTF only works on 2D images, not 3D.");
1527 
1528  double iTs=1.0/Ts;
1530  {
1531  XX(idx) = j;
1532  YY(idx) = i;
1533  FFT_idx2digfreq(I, idx, freq);
1534  precomputeValues(XX(freq)*iTs, YY(freq)*iTs);
1535  double ctf = getValueAt();
1536  if (absPhase)
1537  ctf=fabs(ctf);
1538  A2D_ELEM(FFTI, i, j) *= ctf;
1539  }
1540 }
1541 
1542 void CTFDescription::applyCTF(MultidimArray <double> &I, double Ts, bool absPhase)
1543 {
1544  FourierTransformer transformer;
1545  MultidimArray<double> FFTI;
1546  transformer.setReal(I);
1547  transformer.FourierTransform();
1548  applyCTF(transformer.fFourier, I, Ts, absPhase);
1549  transformer.inverseFourierTransform();
1550 }
1551 
1552 /* Apply the CTF to an image ----------------------------------------------- */
1553 void CTFDescription::correctPhase(MultidimArray < std::complex<double> > &FFTI, const MultidimArray<double> &I, double Ts)
1554 {
1555  Matrix1D<int> idx(2);
1556  Matrix1D<double> freq(2);
1557  if ( ZSIZE(FFTI) > 1 )
1558  REPORT_ERROR(ERR_MULTIDIM_DIM,"ERROR: Apply_CTF only works on 2D images, not 3D.");
1559 
1560  double iTs=1.0/Ts;
1562  {
1563  XX(idx) = j;
1564  YY(idx) = i;
1565  FFT_idx2digfreq(I, idx, freq);
1566  precomputeValues(XX(freq)*iTs, YY(freq)*iTs);
1567  double ctf = getValuePureAt();
1568  if (ctf<0)
1569  A2D_ELEM(FFTI, i, j) *= -1;
1570  }
1571 }
1572 
1574 {
1575  FourierTransformer transformer;
1576  MultidimArray<double> FFTI;
1577  transformer.setReal(I);
1578  transformer.FourierTransform();
1579  correctPhase(transformer.fFourier, I, Ts);
1580  transformer.inverseFourierTransform();
1581 }
1582 
1583 /* Get profiles ------------------------------------------------------------ */
1584 void CTFDescription::getProfile(double angle, double fmax, int nsamples,
1585  MultidimArray<double> &profiles)
1586 {
1587  double step = fmax / nsamples;
1588 
1589  profiles.resizeNoCopy(nsamples, 4);
1590  double sinus = sin(angle);
1591  double cosinus = cos(angle);
1592  double f;
1593  size_t i;
1594 
1595  for (i = 0, f = 0; i < YSIZE(profiles); i++, f += step)
1596  {
1597  double fx = f * cosinus;
1598  double fy = f * sinus;
1599 
1600  // Compute current frequencies.
1601  precomputeValues(fx, fy);
1602 
1603  // Store values.
1604  double bgNoise = getValueNoiseAt();
1605  double ctf = getValuePureAt();
1606  double E = getValueDampingAt();
1607 
1608  A2D_ELEM(profiles, i, 0) = 10*log10(bgNoise);
1609  A2D_ELEM(profiles, i, 1) = 10*log10(bgNoise + E * E);
1610  A2D_ELEM(profiles, i, 2) = 10*log10(bgNoise + ctf * ctf);
1611  A2D_ELEM(profiles, i, 3) = getValuePureNoKAt();
1612  }
1613 }
1614 
1615 /* Get average profiles ----------------------------------------------------- */
1616 void CTFDescription::getAverageProfile(double fmax, int nsamples,
1617  MultidimArray<double> &profiles)
1618 {
1619  double step = fmax / nsamples;
1620  profiles.initZeros(nsamples, 4);
1621 
1622  for(int angle=0; angle < 360; angle++)
1623  {
1624  double angle2 = float(angle);
1625  double sinus = sin(angle2);
1626  double cosinus = cos(angle2);
1627  double f;
1628  size_t i;
1629  for (i = 0, f = 0; i < YSIZE(profiles); i++, f += step)
1630  {
1631  double fx = f * cosinus;
1632  double fy = f * sinus;
1633 
1634  // Compute current frequencies.
1635  precomputeValues(fx, fy);
1636 
1637  // Store values.
1638  double bgNoise = getValueNoiseAt();
1639  double ctf = getValuePureAt();
1640  double E = getValueDampingAt();
1641 
1642  A2D_ELEM(profiles, i, 0) += 10*log10(bgNoise);
1643  A2D_ELEM(profiles, i, 1) += 10*log10(bgNoise + E * E);
1644  A2D_ELEM(profiles, i, 2) += 10*log10(bgNoise + ctf * ctf);
1645  A2D_ELEM(profiles, i, 3) += getValuePureNoKAt();
1646  }
1647  }
1648  profiles*=1.0/360;
1649 }
1650 
1651 /* Physical meaning -------------------------------------------------------- */
1652 //#define DEBUG
1654 {
1655  bool retval;
1656  if (enable_CTF)
1657  {
1658  precomputeValues(0,0);
1659  retval =
1660  K >= 0 && base_line >= 0 &&
1661  kV >= 50 && kV <= 1000 &&
1662  espr >= 0 && espr <= 20 &&
1663  ispr >= 0 && ispr <= 20 &&
1664  Cs >= 0 && Cs <= 20 &&
1665  Ca >= 0 && Ca <= 7 &&
1666  alpha >= 0 && alpha <= 9 &&
1667  DeltaF >= 0 && DeltaF <= 1000 &&
1668  DeltaR >= 0 && DeltaR <= 100 &&
1669  Q0 >= 0 && Q0 <= 0.40 &&
1670  DeltafU >= 0 && DeltafV >= 0 &&
1671  getValueAt() >= 0;
1672 #ifdef DEBUG
1673 
1674  if (retval == false)
1675  {
1676  std::cout << *this << std::endl;
1677  std::cout << "K>=0 && base_line>=0 " << (K >= 0 && base_line >= 0) << std::endl
1678  << "kV>=50 && kV<=1000 " << (kV >= 50 && kV <= 1000) << std::endl
1679  << "espr>=0 && espr<=20 " << (espr >= 0 && espr <= 20) << std::endl
1680  << "ispr>=0 && ispr<=20 " << (ispr >= 0 && ispr <= 20) << std::endl
1681  << "Cs>=0 && Cs<=20 " << (Cs >= 0 && Cs <= 20) << std::endl
1682  << "Ca>=0 && Ca<=3 " << (Ca >= 0 && Ca <= 7) << std::endl
1683  << "alpha>=0 && alpha<=5 " << (alpha >= 0 && alpha <= 5) << std::endl
1684  << "DeltaF>=0 && DeltaF<=1000 " << (DeltaF >= 0 && DeltaF <= 1000) << std::endl
1685  << "DeltaR>=0 && DeltaR<=100 " << (DeltaR >= 0 && DeltaR <= 100) << std::endl
1686  << "Q0>=0 && Q0<=0.4 " << (Q0 >= 0 && Q0 <= 0.4) << std::endl
1687  << "DeltafU>=0 && DeltafV>=0 " << (DeltafU >= 0 && DeltafV >= 0) << std::endl
1688  << "getValueAt(0,0)>=0 " << (getValueAt() >= 0) << std::endl
1689  ;
1690  std::cout << "getValueAt(0,0)=" << getValueAt(true) << std::endl;
1691  }
1692 #endif
1693 
1694  }
1695  else
1696  retval = true;
1697  bool retval2;
1698  if (enable_CTFnoise)
1699  {
1700  double min_sigma = XMIPP_MIN(sigmaU, sigmaV);
1701  double min_c = XMIPP_MIN(cU, cV);
1702  double min_sigma2 = XMIPP_MIN(sigmaU2, sigmaV2);
1703  double min_c2 = XMIPP_MIN(cU2, cV2);
1704  retval2 =
1705  base_line >= 0 &&
1706  gaussian_K >= 0 &&
1707  sigmaU >= 0 && sigmaV >= 0 &&
1708  sigmaU <= 100e3 && sigmaV <= 100e3 &&
1709  cU >= 0 && cV >= 0 &&
1710  sqU >= 0 && sqV >= 0 &&
1711  sqrt_K >= 0 &&
1712  gaussian_K2 >= 0 &&
1713  sigmaU2 >= 0 && sigmaV2 >= 0 &&
1714  sigmaU2 <= 100e3 && sigmaV2 <= 100e3 &&
1715  cU2 >= 0 && cV2 >= 0 &&
1716  gaussian_angle >= 0 && gaussian_angle <= 90 &&
1717  sqrt_angle >= 0 && sqrt_angle <= 90 &&
1718  gaussian_angle2 >= 0 && gaussian_angle2 <= 90 &&
1719  phase_shift >= -PI && phase_shift <= PI
1720  ;
1721  if (min_sigma > 0)
1722  retval2 = retval2 && ABS(sigmaU - sigmaV) / min_sigma <= 3;
1723  if (min_c > 0)
1724  retval2 = retval2 && ABS(cU - cV) / min_c <= 3;
1725  if (gaussian_K != 0)
1726  retval2 = retval2 && (cU * Tm >= 0.01) && (cV * Tm >= 0.01);
1727  if (min_sigma2 > 0)
1728  retval2 = retval2 && ABS(sigmaU2 - sigmaV2) / min_sigma2 <= 3;
1729  if (min_c2 > 0)
1730  retval2 = retval2 && ABS(cU2 - cV2) / min_c2 <= 3;
1731  if (gaussian_K2 != 0)
1732  retval2 = retval2 && (cU2 * Tm >= 0.01) && (cV2 * Tm >= 0.01);
1733 #ifdef DEBUG
1734 
1735  if (retval2 == false)
1736  {
1737  std::cout << *this << std::endl;
1738  std::cout << "base_line>=0 && " << (base_line >= 0) << std::endl
1739  << "gaussian_K>=0 && " << (gaussian_K >= 0) << std::endl
1740  << "sigmaU>=0 && sigmaV>=0 " << (sigmaU >= 0 && sigmaV >= 0) << std::endl
1741  << "sigmaU<=100e3 && sigmaV<=100e3 " << (sigmaU <= 100e3 && sigmaV <= 100e3) << std::endl
1742  << "cU>=0 && cV>=0 " << (cU >= 0 && cV >= 0) << std::endl
1743  << "sqU>=0 && sqV>=0 " << (sqU >= 0 && sqV >= 0) << std::endl
1744  << "sqrt_K>=0 && " << (sqrt_K >= 0) << std::endl
1745  << "gaussian_K2>=0 && " << (gaussian_K2 >= 0) << std::endl
1746  << "sigmaU2>=0 && sigmaV2>=0 " << (sigmaU2 >= 0 && sigmaV2 >= 0) << std::endl
1747  << "sigmaU2<=100e3 && sigmaV2<=100e3 " << (sigmaU2 <= 100e3 && sigmaV2 <= 100e3) << std::endl
1748  << "cU2>=0 && cV2>=0 " << (cU2 >= 0 && cV2 >= 0) << std::endl
1749  << "gaussian_angle>=0 && gaussian_angle<=90 " << (gaussian_angle >= 0 && gaussian_angle <= 90) << std::endl
1750  << "sqrt_angle>=0 && sqrt_angle<=90 " << (sqrt_angle >= 0 && sqrt_angle <= 90) << std::endl
1751  << "gaussian_angle2>=0 && gaussian_angle2<=90 " << (gaussian_angle2 >= 0 && gaussian_angle2 <= 90) << std::endl
1752  ;
1753  if (min_sigma > 0)
1754  std::cout << "ABS(sigmaU-sigmaV)/min_sigma<=3 " << (ABS(sigmaU - sigmaV) / min_sigma <= 3) << std::endl;
1755  if (min_c > 0)
1756  std::cout << "ABS(cU-cV)/min_c<=3 " << (ABS(cU - cV) / min_c <= 3) << std::endl;
1757  if (gaussian_K > 0)
1758  std::cout << "(cU*Tm>=0.01) && (cV*Tm>=0.01) " << ((cU*Tm >= 0.01) && (cV*Tm >= 0.01)) << std::endl;
1759  if (min_sigma2 > 0)
1760  std::cout << "ABS(sigmaU2-sigmaV2)/min_sigma2<=3 " << (ABS(sigmaU2 - sigmaV2) / min_sigma2 <= 3) << std::endl;
1761  if (min_c2 > 0)
1762  std::cout << "ABS(cU2-cV2)/min_c2<=3 " << (ABS(cU2 - cV2) / min_c2 <= 3) << std::endl;
1763  if (gaussian_K2 > 0)
1764  std::cout << "(cU2*Tm>=0.01) && (cV2*Tm>=0.01) " << ((cU2*Tm >= 0.01) && (cV2*Tm >= 0.01)) << std::endl;
1765  std::cout << cV2*Tm << std::endl;
1766  }
1767 #endif
1768 
1769  }
1770  else
1771  retval2 = true;
1772 #ifdef DEBUG
1773 
1774 #endif
1775 
1776  return retval && retval2;
1777 }
1778 #undef DEBUG
1779 
1780 /* Force Physical meaning -------------------------------------------------- */
1782 {
1784  if (enable_CTF)
1785  {
1786  if (DeltafU < 0)
1787  DeltafU = 0;
1788  if (DeltafV < 0)
1789  DeltafV = 0;
1790  }
1791  if (enable_CTFnoise)
1792  {
1793  double min_sigma = XMIPP_MIN(sigmaU, sigmaV);
1794  double min_c = XMIPP_MIN(cU, cV);
1795  double min_sigma2 = XMIPP_MIN(sigmaU2, sigmaV2);
1796  double min_c2 = XMIPP_MIN(cU2, cV2);
1797  if (base_line < 0)
1798  base_line = 0;
1799  if (gaussian_K < 0)
1800  gaussian_K = 0;
1801  if (sigmaU < 0)
1802  sigmaU = 0;
1803  if (sigmaV < 0)
1804  sigmaV = 0;
1805  if (sigmaU > 100e3)
1806  sigmaU = 100e3;
1807  if (sigmaV > 100e3)
1808  sigmaV = 100e3;
1809  if (cU < 0)
1810  cU = 0;
1811  if (cV < 0)
1812  cV = 0;
1813  if (sqU < 0)
1814  sqU = 0;
1815  if (sqV < 0)
1816  sqV = 0;
1817  if (sqrt_K < 0)
1818  sqrt_K = 0;
1819  if (gaussian_K2 < 0)
1820  gaussian_K2 = 0;
1821  if (sigmaU2 < 0)
1822  sigmaU2 = 0;
1823  if (sigmaV2 < 0)
1824  sigmaV2 = 0;
1825  if (sigmaU2 > 100e3)
1826  sigmaU2 = 100e3;
1827  if (sigmaV2 > 100e3)
1828  sigmaV2 = 100e3;
1829  if (cU2 < 0)
1830  cU2 = 0;
1831  if (cV2 < 0)
1832  cV2 = 0;
1833  if (gaussian_angle < 0)
1834  gaussian_angle = 0;
1835  if (gaussian_angle > 90)
1836  gaussian_angle = 90;
1837  if (sqrt_angle < 0)
1838  sqrt_angle = 0;
1839  if (sqrt_angle > 90)
1840  sqrt_angle = 90;
1841  if (gaussian_angle2 < 0)
1842  gaussian_angle2 = 0;
1843  if (gaussian_angle2 > 90)
1844  gaussian_angle2 = 90;
1845  if (min_sigma > 0)
1846  if (ABS(sigmaU - sigmaV) / min_sigma > 3)
1847  {
1848  if (sigmaU < sigmaV)
1849  sigmaV = 3.9 * sigmaU;
1850  else
1851  sigmaU = 3.9 * sigmaV;
1852  }
1853  if (min_c > 0)
1854  if (ABS(cU - cV) / min_c > 3)
1855  {
1856  if (cU < cV)
1857  cV = 3.9 * cU;
1858  else
1859  cU = 3.9 * cV;
1860  }
1861  if (gaussian_K != 0)
1862  {
1863  if (cU*Tm < 0.01)
1864  cU = 0.011 / Tm;
1865  if (cV*Tm < 0.01)
1866  cV = 0.011 / Tm;
1867  }
1868  if (min_sigma2 > 0)
1869  if (ABS(sigmaU2 - sigmaV2) / min_sigma2 > 3)
1870  {
1871  if (sigmaU2 < sigmaV2)
1872  sigmaV2 = 3.9 * sigmaU2;
1873  else
1874  sigmaU2 = 3.9 * sigmaV2;
1875  }
1876  if (min_c2 > 0)
1877  if (ABS(cU2 - cV2) / min_c2 > 3)
1878  {
1879  if (cU2 < cV2)
1880  cV2 = 3.9 * cU2;
1881  else
1882  cU2 = 3.9 * cV2;
1883  }
1884  if (gaussian_K2 != 0)
1885  {
1886  if (cU2*Tm < 0.01)
1887  cU2 = 0.011 / Tm;
1888  if (cV2*Tm < 0.01)
1889  cV2 = 0.011 / Tm;
1890  }
1891  }
1892 }
1893 #undef DEBUG
1894 
1895 
1896 
double sigmaU
Spherical aberration (in milimeters). Typical value 5.6.
Definition: ctf.h:871
int precomputedImageXdim
Definition: ctf.h:235
Argument missing.
Definition: xmipp_error.h:114
CTF Background parameter.
#define VECTOR_R2(v, x, y)
Definition: matrix1d.h:112
CTF gain.
The CTF is valid within (x0,y0) to (xF,yF) in the micrograph coordinates.
#define YSIZE(v)
void write(const FileName &fn)
Definition: ctf.cpp:484
#define A2D_ELEM(v, i, j)
double bgR1
Definition: ctf.h:295
const MDLabel CTF_ALL_LABELS[]
Definition: ctf.h:48
Defocus U (Angstroms)
double lambda
Definition: ctf.h:214
#define yDim
Definition: projection.cpp:42
double K1
Definition: ctf.h:218
double module() const
Definition: matrix1d.h:983
double getDoubleParam(const char *param, int arg=0)
CTF Background parameter.
double bgR2
Definition: ctf.h:296
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
double gaussian_angle2
Second Gaussian angle.
Definition: ctf.h:897
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
double envR1
Definition: ctf.h:300
void lookFor(int n, const Matrix1D< double > &u, Matrix1D< double > &freq, int iwhat=0)
Definition: ctf.cpp:701
Defocus angle (degrees)
#define xDim
Definition: projection.cpp:41
double getValueAt(bool show=false) const
Compute CTF at (U,V). Continuous frequencies.
Definition: ctf.h:417
#define MULTIDIM_SIZE(v)
#define DEG2RAD(d)
Definition: xmipp_macros.h:312
void resizeNoCopy(const MultidimArray< T1 > &v)
void precomputeValues(double X)
Precompute values for a given frequency.
Definition: ctf.h:376
CTF Background parameter.
MultidimArray< std::complex< double > > fFourier
Definition: xmipp_fftw.h:70
void sqrt(Image< double > &op)
void generatePSDCTFImage(MultidimArray< double > &img, const MetaData &MD)
Definition: ctf.cpp:330
double envR2
Definition: ctf.h:301
virtual bool containsLabel(const MDLabel label) const =0
void fillExpand(MDLabel label)
virtual size_t firstRowId() const =0
void getProfile(double angle, double fmax, int nsamples, MultidimArray< double > &profiles)
Definition: ctf.cpp:1584
double DeltafV
Defocus in V (in Angstroms). Negative values are underfocused.
Definition: ctf.h:830
void groupCTFMetaData(const MetaDataDb &imgMd, MetaDataDb &ctfMd, std::vector< MDLabel > &groupbyLabels)
Definition: ctf.cpp:41
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)
void setRow(MDRow &row) const
Definition: ctf.cpp:1233
#define DIRECT_A2D_ELEM(v, i, j)
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
void write(const FileName &fn)
Definition: ctf.cpp:1275
Convergence cone.
double espr
Definition: ctf.h:251
void rangeAdjust(T minF, T maxF)
double cU2
Second Gaussian center for U.
Definition: ctf.h:893
void getAverageProfile(double fmax, int nsamples, MultidimArray< double > &profiles)
Definition: ctf.cpp:894
CTF Background parameter.
double cU
Gaussian center for U.
Definition: ctf.h:875
bool containsCTFBasicLabels(const MetaData &md)
Definition: ctf.cpp:33
doublereal * w
void abs(Image< double > &op)
CTF Background parameter.
Name for the CTF Model (std::string)
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
double phase_shift
Definition: ctf.h:305
Matrix2D< T > transpose() const
Definition: matrix2d.cpp:1314
double getValueNoiseAt(bool show=false) const
Compute noise at (X,Y). Continuous frequencies, notice it is squared.
Definition: ctf.h:506
CTF Background parameter.
The CTF is valid within (x0,y0) to (xF,yF) in the micrograph coordinates.
double gaussian_K
Gain for the gaussian term.
Definition: ctf.h:279
double envR0
Definition: ctf.h:299
void FFT_idx2digfreq(T &v, const Matrix1D< int > &idx, Matrix1D< double > &freq)
Definition: xmipp_fft.h:80
CTF Background parameter.
double errorMaxFreqCTFs2D(MetaData &MD1, MetaData &MD2, size_t Xdim, double phaseRad)
Definition: ctf.cpp:214
std::unique_ptr< MDRow > getRow(size_t id) override
CTF Background parameter.
double sq
Sqrt width.
Definition: ctf.h:287
Spherical aberration.
const MDLabel CTF_BASIC_LABELS[]
Definition: ctf.h:42
void aggregateGroupBy(const MetaDataDb &mdIn, AggregateOperation op, const std::vector< MDLabel > &groupByLabels, MDLabel operateLabel, MDLabel resultLabel)
double DeltaF
Longitudinal mechanical displacement (ansgtrom). Typical value 100.
Definition: ctf.h:257
double sqrt_angle
Sqrt angle.
Definition: ctf.h:887
#define i
static void defineParams(XmippProgram *program)
Define parameters in the command line.
Definition: ctf.cpp:1287
size_t addRow(const MDRow &row) override
Microscope voltage (kV)
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
CTF Background parameter.
void read(const FileName &fn, bool disable_if_not_K=true)
Definition: ctf.cpp:1220
void aggregate(const MetaDataDb &mdIn, AggregateOperation op, MDLabel aggregateLabel, MDLabel operateLabel, MDLabel resultLabel)
double DeltafU
Global gain. By default, 1.
Definition: ctf.h:828
bool enable_CTF
Enable CTF part.
Definition: ctf.h:275
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
double azimuthal_angle
Azimuthal angle (between X and U) in degrees.
Definition: ctf.h:832
void clearNoise()
Clear noise.
Definition: ctf.cpp:620
double Gc2
Second Gaussian center.
Definition: ctf.h:293
CTF Background polynomial parameter.
double sigma2
Second Gaussian width.
Definition: ctf.h:291
MultidimArray< T > data
Definition: xmipp_image.h:55
const int CTF_BASIC_LABELS_SIZE
Definition: ctf.h:41
double getValueArgument(bool show=false) const
Compute pure CTF without damping at (U,V). Continuous frequencies.
Definition: ctf.h:1057
CTF Envelope polynomial parameter.
double base_line
Global base_line.
Definition: ctf.h:277
void readFromMetadataRow(const MetaData &MD, size_t id, bool disable_if_not_K=true)
Definition: ctf.cpp:421
double deltaf
Definition: ctf.h:91
doublereal * b
double K2
Definition: ctf.h:219
double K6
Definition: ctf.h:223
double sqU
Gain for the square root term.
Definition: ctf.h:883
T & getValue(MDLabel label)
void log(Image< double > &op)
double Gc1
Gaussian center.
Definition: ctf.h:283
void generateCTFImageWith2CTFs(const MetaData &MD1, const MetaData &MD2, int Xdim, MultidimArray< double > &imgOut)
Definition: ctf.cpp:67
Number of elements of a type (int) [this is a genereic type do not use to transfer information to ano...
double K7
Definition: ctf.h:224
const char * getParam(const char *param, int arg=0)
#define XX(v)
Definition: matrix1d.h:85
CTF Envelope polynomial parameter.
void applyCTF(MultidimArray< std::complex< double > > &FFTI, const MultidimArray< double > &I, double Ts, bool absPhase=false)
Apply CTF to an image.
Definition: ctf.cpp:1521
double getValueAt(bool show=false) const
Compute CTF at (U,V). Continuous frequencies.
Definition: ctf.h:1050
double Ksin
Definition: ctf.h:225
void setReal(MultidimArray< double > &img)
Definition: xmipp_fftw.cpp:129
void transpose(double *array, int size)
void correctPhase(MultidimArray< std::complex< double > > &FFTI, const MultidimArray< double > &I, double Ts)
Correct phase flip of an image.
Definition: ctf.cpp:832
CTF Envelope polynomial parameter.
Inelastic absorption.
double gaussian_K2
Gain for the second Gaussian term.
Definition: ctf.h:289
void readFromMetadataRow(const MetaData &MD, size_t id, bool disable_if_not_K=true)
Definition: ctf.cpp:1214
CTF Background parameter.
#define CTF
Longitudinal displacement.
double * f
double getValuePureNoPrecomputedAt(double X, bool show=false) const
Compute CTF pure at (U,V). Continuous frequencies.
Definition: ctf.h:613
size_t firstRowId() const override
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
double errorBetween2CTFs(MetaData &MD1, MetaData &MD2, size_t Xdim, double minFreq, double maxFreq)
Definition: ctf.cpp:107
void readParams(XmippProgram *program)
Read parameters from the command line.
Definition: ctf.cpp:524
#define XSIZE(v)
const int CTF_ALL_LABELS_SIZE
Definition: ctf.h:47
CTF Background parameter.
CTF Background parameter.
double ispr
Objective lens stability (deltaI/I) (ppm). Typical value 1.
Definition: ctf.h:253
double sqV
Sqrt width V.
Definition: ctf.h:885
double Tm
Sampling rate (A/pixel)
Definition: ctf.h:240
CTF Background polynomial parameter.
Missing expected label.
Definition: xmipp_error.h:158
#define ABS(x)
Definition: xmipp_macros.h:142
#define ZSIZE(v)
double bgR3
Definition: ctf.h:297
virtual std::unique_ptr< MDRow > getRow(size_t id)=0
static void defineParams(XmippProgram *program)
Define parameters in the command line.
Definition: ctf.cpp:496
bool hasPhysicalMeaning()
Definition: ctf.cpp:929
Micrograph unique id for reference (MDL_ITEM_ID should be used for Micrographs list) ...
CTF Background parameter.
void readFromMdRow(const MDRow &row, bool disable_if_not_K=true)
Definition: ctf.cpp:1172
void precomputeValues(double X, double Y)
Precompute values for a given frequency.
Definition: ctf.h:1002
void log10(Image< double > &op)
double getValueDampingAt(bool show=false) const
Compute CTF damping at (U,V). Continuous frequencies.
Definition: ctf.h:424
double Cs
Spherical aberration (in milimeters). Typical value 5.6.
Definition: ctf.h:246
double DeltaR
Transversal mechanical displacement (ansgtrom). Typical value 3.
Definition: ctf.h:259
double sigmaV
Gaussian width V.
Definition: ctf.h:873
double getValuePureWithoutDampingAt(bool show=false) const
Compute pure CTF without damping at (U,V). Continuous frequencies.
Definition: ctf.h:542
void FourierTransform(T &v, T1 &V, bool getCopy=true)
Definition: xmipp_fftw.h:166
__device__ float FFT_IDX2DIGFREQ(int idx, int size)
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
CTF_ CTF Background parameter.
void forcePhysicalMeaning()
Definition: ctf.cpp:1055
void correctPhase(MultidimArray< std::complex< double > > &FFTI, const MultidimArray< double > &I, double Ts)
Correct phase flip of an image.
Definition: ctf.cpp:1553
double errorMaxFreqCTFs(MetaData &MD1, double phaseRad)
Definition: ctf.cpp:187
double getValuePureNoKAt() const
Compute CTF pure at (U,V). Continuous frequencies.
Definition: ctf.h:499
#define j
double Defocus
Defocus (in Angstroms). Negative values are underfocused.
Definition: ctf.h:244
#define YY(v)
Definition: matrix1d.h:93
const T & getValueOrDefault(MDLabel label, const T &def) const
CTF Background parameter.
void applyCTF(MultidimArray< std::complex< double > > &FFTI, const MultidimArray< double > &I, double Ts, bool absPhase=false)
Apply CTF to an image.
Definition: ctf.cpp:800
double K
Global gain. By default, 1.
Definition: ctf.h:238
double gaussian_angle
Gaussian angle.
Definition: ctf.h:879
void readFromMdRow(const MDRow &row, bool disable_if_not_K=true)
Definition: ctf.cpp:365
void read(const FileName &fn, bool disable_if_not_K=true)
Definition: ctf.cpp:427
void error(char *s)
Definition: tools.cpp:107
double K5
Definition: ctf.h:222
virtual void setColumnFormat(bool column)
void setValue(MDLabel label, const T &d, bool addLabel=true)
bool isLocalCTF
Local CTF determination.
Definition: ctf.h:271
bool isMetaData(bool failIfNotExists=true) const
void clearPureCtf()
Clear pure CTF.
Definition: ctf.cpp:630
virtual bool containsLabel(MDLabel label) const =0
double VPP_radius
Definition: ctf.h:306
std::vector< PrecomputedForCTF > precomputedImage
Definition: ctf.h:233
void clearPureCtf()
Clear pure CTF.
Definition: ctf.cpp:1384
double Ca
Chromatic aberration (in milimeters). Typical value 2.
Definition: ctf.h:248
void lookFor(int n, const Matrix1D< double > &u, Matrix1D< double > &freq, int iwhat=0)
Definition: ctf.cpp:1428
void produceSideInfo()
Produce Side information.
Definition: ctf.cpp:1392
void forcePhysicalMeaning()
Definition: ctf.cpp:1781
double alpha
Convergence cone semiangle (in mrad). Typical value 0.5.
Definition: ctf.h:255
#define V2_BY_CT(a, b, k)
Definition: matrix1d.h:179
#define realWRAP(x, x0, xF)
Definition: xmipp_macros.h:304
double y0
In the case of local CTF determination x0,xF,y0,yF determines the region where the CTF is determined...
Definition: ctf.h:267
CTF Background parameter.
doublereal * u
bool checkParam(const char *param)
The CTF is valid within (x0,y0) to (xF,yF) in the micrograph coordinates.
double Q0
Factor for the importance of the Amplitude contrast.
Definition: ctf.h:261
double x0
In the case of local CTF determination x0,xF,y0,yF determines the region where the CTF is determined...
Definition: ctf.h:263
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
void clear()
Clear.
Definition: ctf.cpp:1366
CTF Background polynomial parameter.
friend std::ostream & operator<<(std::ostream &out, const CTFDescription1D &ctf)
Show.
Definition: ctf.cpp:564
double kV
Accelerating Voltage (in KiloVolts)
Definition: ctf.h:242
void initZeros(const MultidimArray< T1 > &op)
double cV2
Second Gaussian center for V.
Definition: ctf.h:895
void getProfile(double fmax, int nsamples, MultidimArray< double > &profiles)
Definition: ctf.cpp:863
bool enable_CTFnoise
Enable CTFnoise part.
Definition: ctf.h:273
void clearNoise()
Clear noise.
Definition: ctf.cpp:1373
double xF
In the case of local CTF determination x0,xF,y0,yF determines the region where the CTF is determined...
Definition: ctf.h:265
void clear()
Clear.
Definition: ctf.cpp:610
double getValuePureAt(bool show=false) const
Compute CTF pure at (U,V). Continuous frequencies.
Definition: ctf.h:452
#define PI
Definition: tools.h:43
Defocus V (Angstroms)
double sigma1
Gaussian width.
Definition: ctf.h:281
double sqrt_K
Gain for the square root term.
Definition: ctf.h:285
Chromatic aberration.
Transversal displacemente.
PrecomputedForCTF precomputed
Definition: ctf.h:231
double fmax
#define SGN(x)
Definition: xmipp_macros.h:155
double yF
In the case of local CTF determination x0,xF,y0,yF determines the region where the CTF is determined...
Definition: ctf.h:269
void produceSideInfo()
Produce Side information.
Definition: ctf.cpp:645
int * n
double Kcos
Definition: ctf.h:226
Lens stability.
doublereal * a
bool hasPhysicalMeaning()
Definition: ctf.cpp:1653
double sigmaU2
Second Gaussian width U.
Definition: ctf.h:889
void addParamsLine(const String &line)
void initIdentity()
Definition: matrix2d.h:673
void digfreq2contfreq(const Matrix1D< double > &digfreq, Matrix1D< double > &contfreq, double pixel_size)
Definition: xmipp_fft.h:125
The CTF is valid within (x0,y0) to (xF,yF) in the micrograph coordinates.
void setRow(MDRow &row) const
Definition: ctf.cpp:440
double sigmaV2
Second Gaussian width V.
Definition: ctf.h:891
double cV
Gaussian center for V.
Definition: ctf.h:877
bool containsLabel(const MDLabel label) const override
Definition: metadata_db.h:305
double K3
Definition: ctf.h:220
CTF Background parameter.
void readParams(XmippProgram *program)
Read parameters from the command line.
Definition: ctf.cpp:1297
void getAverageProfile(double fmax, int nsamples, MultidimArray< double > &profiles)
Definition: ctf.cpp:1616