Xmipp  v3.23.11-Nereus
fourier_filter.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 "data/fourier_filter.h"
27 #include "mask.h"
28 #include "core/xmipp_program.h"
29 #include "core/transformations.h"
30 
31 /* Clear ------------------------------------------------------------------- */
33 {
36  w2 = w1 = 0;
37  raised_w = 0;
38  ctf.clear();
39  ctf.enable_CTFnoise = false;
40  do_generate_3dmask = false;
41  sampling_rate = -1.;
42 }
43 
44 /* Empty constructor ---------------------------------------------------------*/
46 {
47  init();
48 }
49 
50 /* Define params ------------------------------------------------------------------- */
52 {
53  program->addParamsLine("== Fourier ==");
54  program->addParamsLine(" [ --fourier <filter_type>] : Filter in Fourier space");
55  program->addParamsLine(" where <filter_type>");
56  program->addParamsLine(" low_pass <w1> <raisedw=0.02> : Cutoff freq (<1/2 or A)");
57  program->addParamsLine(" high_pass <w1> <raisedw=0.02> : Cutoff freq (<1/2 or A)");
58  program->addParamsLine(" band_pass <w1> <w2> <raisedw=0.02> : Cutoff freq (<1/2 or A)");
59  program->addParamsLine(" stop_band <w1> <w2> <raisedw=0.02> : Cutoff freq (<1/2 or A)");
60  program->addParamsLine(" stop_lowbandx <w1> <raisedw=0.02> : Cutoff freq (<1/2 or A)");
61  program->addParamsLine(" stop_lowbandy <w1> <raisedw=0.02> : Cutoff freq (<1/2 or A)");
62  program->addParamsLine(" wedge <th0> <thF> <rot=0> <tilt=0> <psi=0> : Missing wedge (along y) for data between th0-thF ");
63  program->addParamsLine(" : y is rotated by euler angles degrees");
64  program->addParamsLine(" cone <th0> : Missing cone for tilt angles up to th0 ");
65  program->addParamsLine(" : do not use mask type for wedge or cone filters");
66  program->addParamsLine(" real_gaussian <w1> : Gaussian in real space with sigma = w1");
67  program->addParamsLine(" gaussian <w1> : Gaussian in Fourier space with sigma = w1");
68  program->addParamsLine(" sparsify <p=0.975> : Delete p percent of the smallest Fourier coefficients");
69  program->addParamsLine(" ctf <ctfile> : Provide a .ctfparam file");
70  program->addParamsLine(" ctfpos <ctfile> : Provide a .ctfparam file");
71  program->addParamsLine(" : The CTF phase will be corrected before applying");
72  program->addParamsLine(" ctfinv <ctfile> <minCTF=0.05> : Apply the inverse of the CTF. Below the minCTF, the image is not corrected");
73  program->addParamsLine(" ctfposinv <ctfile> <minCTF=0.05> : Apply the inverse of the abs(CTF). Below the minCTF, the image is not corrected");
74  program->addParamsLine(" ctfdef <kV> <Cs> <Q0> <defocus> : Apply a CTF with this voltage (kV), spherical aberration (mm), Q0 (typically, 0.07), and defocus (A)");
75  program->addParamsLine(" ctfdefastig <kV> <Cs> <Q0> <defocusU> <defocusV> <defocusAngle> : Apply a CTF with this voltage (kV), spherical aberration (mm), Q0 (typically, 0.07), defocus (A), and defocusAngle (degrees)");
76  program->addParamsLine(" : The phase flip is not corrected");
77  program->addParamsLine(" bfactor <B> : Exponential filter (positive values for decay) ");
78  program->addParamsLine(" requires --sampling; ");
79  program->addParamsLine(" fsc <metadata> : Filter with the FSC profile contained in the metadata");
80  program->addParamsLine(" requires --sampling; ");
81  program->addParamsLine(" binary_file <file> : Binary file with the filter");
82  program->addParamsLine(" :+The filter must be defined in the whole Fourier space (not only the nonredundant part).");
83  program->addParamsLine(" :+This filter is produced, for instance, by xmipp_ctf_group");
84  program->addParamsLine(" astigmatism <sigma=120> : Filter images according to the astigmatism of their CTF");
85  program->addParamsLine(" :+sigma is the standard deviation of a Gaussian in degrees for the CTF phase");
86  program->addParamsLine(" requires --sampling; ");
87  program->addParamsLine(" alias -f;");
88  program->addParamsLine(" [--sampling <sampling_rate>] : If provided pass frequencies are taken in Ang and for the CTF case");
89  program->addParamsLine(" : and for the CTF case this is the sampling used to compute the CTF");
90  program->addParamsLine(" alias -s;");
91  program->addParamsLine(" requires --fourier;");
92  program->addParamsLine(" [--save <filename=\"\"> ] : Do not apply just save the mask");
93  program->addParamsLine(" requires --fourier;");
94 }
95 
96 /* Read parameters from command line. -------------------------------------- */
98 {
99  init();
100  if (program->checkParam("--save"))
101  maskFn = program->getParam("--save");
102  if (program->checkParam("--sampling"))
103  sampling_rate = program->getDoubleParam("--sampling");
104 
105  // Filter shape .........................................................
106  String filter_type;
107  filter_type = program->getParam("--fourier");
108 
109  // Read frequencies cuttoff options
110  if (filter_type == "low_pass")
111  {
112  w1 = program->getDoubleParam("--fourier", "low_pass");
113  raised_w = program->getDoubleParam("--fourier", "low_pass",1);
116  }
117  else if (filter_type == "high_pass")
118  {
119  w1 = program->getDoubleParam("--fourier", "high_pass");
120  raised_w = program->getDoubleParam("--fourier", "high_pass",1);
123  }
124  else if (filter_type == "band_pass")
125  {
126  w1 = program->getDoubleParam("--fourier", "band_pass");
127  w2 = program->getDoubleParam("--fourier", "band_pass", 1);
128  raised_w = program->getDoubleParam("--fourier", "band_pass",2);
131  }
132  else if (filter_type == "stop_band")
133  {
134  w1 = program->getDoubleParam("--fourier", "stop_band");
135  w2 = program->getDoubleParam("--fourier", "stop_band", 1);
136  raised_w = program->getDoubleParam("--fourier", "stop_band",2);
139  }
140  else if (filter_type == "stop_lowbandx")
141  {
142  w1 = program->getDoubleParam("--fourier", "stop_lowbandx");
143  raised_w = program->getDoubleParam("--fourier", "stop_lowbandx",1);
146  }
147  else if (filter_type == "stop_lowbandy")
148  {
149  w1 = program->getDoubleParam("--fourier", "stop_lowbandy");
150  raised_w = program->getDoubleParam("--fourier", "stop_lowbandy",1);
153  }
154  else if (filter_type == "wedge")
155  {
156  t1 = program->getDoubleParam("--fourier", "wedge", 0);
157  t2 = program->getDoubleParam("--fourier", "wedge", 1);
158  rot = program->getDoubleParam("--fourier", "wedge", 2);
159  tilt = program->getDoubleParam("--fourier", "wedge", 3);
160  psi = program->getDoubleParam("--fourier", "wedge", 4);
162  }
163  else if (filter_type == "cone")
164  {
165  t1 = program->getDoubleParam("--fourier", "cone", 0);
167  }
168  else if (filter_type == "gaussian")
169  {
170  w1 = program->getDoubleParam("--fourier", "gaussian");
173  }
174  else if (filter_type == "sparsify")
175  {
176  percentage = program->getDoubleParam("--fourier", "sparsify");
179  }
180  else if (filter_type == "real_gaussian")
181  {
182  w1 = program->getDoubleParam("--fourier", "real_gaussian");
185  }
186  else if (filter_type == "ctf" || filter_type == "ctfpos" || filter_type == "ctfinv" || filter_type == "ctfposinv")
187  {
188  FileName fnCTF;
189  if (filter_type == "ctf")
190  {
192  fnCTF=program->getParam("--fourier", "ctf");
193  }
194  else if (filter_type == "ctfpos")
195  {
197  fnCTF=program->getParam("--fourier", "ctfpos");
198  }
199  else if (filter_type == "ctfinv")
200  {
202  fnCTF=program->getParam("--fourier", "ctfinv");
203  minCTF = program->getDoubleParam("--fourier", "ctfinv", 1);
204  }
205  else if (filter_type == "ctfposinv")
206  {
208  fnCTF=program->getParam("--fourier", "ctfposinv");
209  minCTF = program->getDoubleParam("--fourier", "ctfposinv", 1);
210  }
211  ctf.enable_CTFnoise = false;
212  ctf.read(fnCTF);
213  if (sampling_rate > 0.)
214  {
215  std::cerr << "CTF was obtained at sampling rate: " << ctf.Tm << std::endl;
216  std::cerr << "Image sampling rate is: " << sampling_rate << std::endl;
218  }
220  }
221  else if (filter_type == "ctfdef")
222  {
224  ctf.clear();
225  ctf.kV = program->getDoubleParam("--fourier", "ctfdef");
226  ctf.Cs = program->getDoubleParam("--fourier", "ctfdef", 1);
227  ctf.Q0 = program->getDoubleParam("--fourier", "ctfdef", 2);
228  ctf.DeltafU = program->getDoubleParam("--fourier", "ctfdef", 3);
230  ctf.Tm = sampling_rate;
232  }
233  else if (filter_type == "ctfdefastig")
234  {
236  ctf.clear();
237  ctf.kV = program->getDoubleParam("--fourier", "ctfdefastig");
238  ctf.Cs = program->getDoubleParam("--fourier", "ctfdefastig", 1);
239  ctf.Q0 = program->getDoubleParam("--fourier", "ctfdefastig", 2);
240  ctf.DeltafU = program->getDoubleParam("--fourier", "ctfdefastig", 3);
241  ctf.DeltafV = program->getDoubleParam("--fourier", "ctfdefastig", 4);
242  ctf.azimuthal_angle = program->getDoubleParam("--fourier", "ctfdefastig", 5);
243  ctf.Tm = sampling_rate;
245  }
246  else if (filter_type == "bfactor")
247  {
249  w1 = program->getDoubleParam("--fourier", "bfactor");
250  }
251  else if (filter_type == "fsc")
252  {
254  fnFSC = program->getParam("--fourier", "fsc");
255  }
256  else if (filter_type == "binary_file")
257  {
259  fnFilter = program->getParam("--fourier", "binary_file");
260  }
261  else if (filter_type == "astigmatism")
262  {
264  w1 = program->getDoubleParam("--fourier", 1);
265  w1 = DEG2RAD(w1);
266  }
267  else
268  REPORT_ERROR(ERR_DEBUG_IMPOSIBLE, "This couldn't happen, check argument parser or params definition");
269 
271  {
272  if (w1 != 0)
273  w1 = sampling_rate / w1;
274  if (w2 != 0)
275  w2 = sampling_rate / w2;
276  }
277 }
278 
279 /* Show -------------------------------------------------------------------- */
281 {
282  {
283  std::cout << "Filter Band: ";
284  switch (FilterBand)
285  {
286  case LOWPASS:
287  std::cout << "Lowpass before " << w1 << std::endl;
288  break;
289  case HIGHPASS:
290  std::cout << "Highpass after " << w1 << std::endl;
291  break;
292  case BANDPASS:
293  std::cout << "Bandpass between " << w1 << " and " << w2 << std::endl;
294  break;
295  case STOPBAND:
296  std::cout << "Stopband between " << w1 << " and " << w2 << std::endl;
297  break;
298  case STOPLOWBANDX:
299  std::cout << "Stop low band X up to " << w1 << std::endl;
300  break;
301  case STOPLOWBANDY:
302  std::cout << "Stop low band Y up to " << w1 << std::endl;
303  break;
304  case CTF:
305  std::cout << "CTF\n";
306  break;
307  case CTFPOS:
308  std::cout << "CTFPOS\n";
309  break;
310  case CTFINV:
311  std::cout << "CTFINV minCTF= " << minCTF << "\n";
312  break;
313  case CTFPOSINV:
314  std::cout << "CTFPOSINV minCTF= " << minCTF << "\n";
315  break;
316  case CTFDEF:
317  std::cout << "CTFDEF voltage= " << ctf.kV << "\n";
318  std::cout << "CTFDEF Cs= " << ctf.Cs << "\n";
319  std::cout << "CTFDEF Q0= " << ctf.Q0 << "\n";
320  std::cout << "CTFDEF defocus= " << ctf.DeltafU << "\n";
321  break;
322  case BFACTOR:
323  std::cout << "Bfactor "<< w1 << std::endl
324  << "Sampling rate " << sampling_rate << std::endl;
325  break;
326  case WEDGE:
327  std::cout << "Missing wedge keep data between tilting angles of " << t1 << " and " << t2 << " deg\n";
328  break;
329  case CONE:
330  std::cout << "Missing cone for RCT data with tilting angles up to " << t1 << " deg\n";
331  break;
332  case FSCPROFILE:
333  std::cout << "FSC file " << fnFSC << std::endl
334  << "Sampling rate " << sampling_rate << std::endl;
335  break;
336  case BINARYFILE:
337  std::cout << "Filter file " << fnFilter << std::endl;
338  break;
339  case ASTIGMATISMPROFILE:
340  std::cout << "Astigmatism sigma " << RAD2DEG(w1) << std::endl;
341  break;
342  }
344  std::cout << "Filter Shape: ";
345  switch (FilterShape)
346  {
347  case RAISED_COSINE:
348  std::cout << "Raised cosine with " << raised_w
349  << " raised frequencies\n";
350  break;
351  case GAUSSIAN:
352  std::cout << "Gaussian\n";
353  break;
354  case SPARSIFY:
355  std::cout << "Sparsify\n";
356  break;
357  case REALGAUSSIAN:
358  std::cout << "Real Gaussian\n";
359  break;
360  case CTF:
361  std::cout << "CTF\n" << ctf;
362  break;
363  case CTFPOS:
364  std::cout << "CTFPOS\n" << ctf;
365  break;
366  case CTFINV:
367  std::cout << "CTFINV\n" << ctf;
368  break;
369  case CTFPOSINV:
370  std::cout << "CTFPOSINV\n" << ctf;
371  break;
372  }
373  if (maskFn != "")
374  std::cout << "Save mask in file: " << maskFn
375  << " disable actual masking"<< std::endl;
376  }
377 }
378 
380 {
381  static bool firstTime = true;
382  do_generate_3dmask = (img.zdim > 1);
383  if (firstTime)
384  {
385  generateMask(img);
386  firstTime = false;
387  }
388  if (maskFn != "")
389  if (do_generate_3dmask==0 && MULTIDIM_SIZE(img)>1024*1024)
390  REPORT_ERROR(ERR_IO_SIZE,"Cannot save 2D mask with xdim*ydim > 1M");
391  else
392  {
393  Image<int> I;
394  Image<double> D;
395  if ( XSIZE(maskFourier) !=0 )
396  {
397  I()=maskFourier;
398  I.write(maskFn);
399  }
400  else if (XSIZE(maskFourierd)!=0)
401  {
402  D()=maskFourierd;
403  D.write(maskFn);
404  }
405  else
406  REPORT_ERROR(ERR_MATRIX_EMPTY,"Cannot save mask file");
407 
408  }
409  else
410  applyMaskSpace(img);
411 }
412 
413 /* Get mask value ---------------------------------------------------------- */
415 {
416  double absw = w.module();
417  double wx=fabs(XX(w));
418  double wy=fabs(YY(w));
419 
420  // Generate mask
421  switch (FilterBand)
422  {
423  case LOWPASS:
424  switch (FilterShape)
425  {
426  case RAISED_COSINE:
427  if (absw<w1)
428  return 1;
429  else if (absw<w1+raised_w)
430  return (1+cos(PI/raised_w*(absw-w1)))/2;
431  else
432  return 0;
433  break;
434  case GAUSSIAN:
435  return 1./sqrt(2.*PI*w1)*exp(-0.5*absw*absw/(w1*w1));
436  break;
437  case REALGAUSSIAN:
438  return exp(-PI*PI*absw*absw*w1*w1); //? Should it be -2*
439  break;
440  case REALGAUSSIANZ:
441  return exp(-2.*PI*PI*absw*absw*w1*w1);
442  break;
443  case REALGAUSSIANZ2:
444  return (1./(4*PI*w1*w1))*exp(-PI*PI*absw*absw*w1*w1);
445  break;
446  case WEDGE_RC:
447  if (absw<w1)
448  return 1;
449  else if (absw<w1+raised_w)
450  return (1+cos(PI/raised_w*(absw-w1)))/2;
451  else
452  return 0;
453  break;
454  }
455  break;
456  case HIGHPASS:
457  switch (FilterShape)
458  {
459  case RAISED_COSINE:
460  if (absw>w1)
461  return 1;
462  else if (absw>w1-raised_w)
463  return (1+cos(PI/raised_w*(w1-absw)))/2;
464  else
465  return 0;
466  break;
467  }
468  break;
469  case BANDPASS:
470  switch (FilterShape)
471  {
472  case RAISED_COSINE:
473  if (absw>=w1 && absw<=w2)
474  return 1;
475  else if (absw>w1-raised_w && absw<w1)
476  return (1+cos(PI/raised_w*(w1-absw)))/2;
477  else if (absw<w2+raised_w && absw>w2)
478  return (1+cos(PI/raised_w*(w2-absw)))/2;
479  else
480  return 0;
481  break;
482  }
483  break;
484  case STOPBAND:
485  switch (FilterShape)
486  {
487  case RAISED_COSINE:
488  if (absw>=w1 && absw<=w2)
489  return 0;
490  else if (absw>w1-raised_w && absw<w1)
491  return 1-(1+cos(PI/raised_w*(w1-absw)))/2;
492  else if (absw<w2+raised_w && absw>w2)
493  return 1-(1+cos(PI/raised_w*(w2-absw)))/2;
494  else
495  return 1;
496  break;
497  }
498  break;
499  case STOPLOWBANDX:
500  switch (FilterShape)
501  {
502  case RAISED_COSINE:
503  if (wx<w1)
504  return 0;
505  else if (wx<w1+raised_w)
506  return (1+cos(PI/raised_w*(w1-wx)))/2;
507  else
508  return 1.0;
509  break;
510  }
511  break;
512  case STOPLOWBANDY:
513  switch (FilterShape)
514  {
515  case RAISED_COSINE:
516  if (wy<w1)
517  return 0;
518  else if (wy<w1+raised_w)
519  return (1+cos(PI/raised_w*(w1-wy)))/2;
520  else
521  return 1.0;
522  break;
523  }
524  break;
525  case CTF:
526  ctf.precomputeValues(XX(w)/ctf.Tm,YY(w)/ctf.Tm);
527  return ctf.getValueAt();
528  break;
529  case CTFPOS:
530  ctf.precomputeValues(XX(w)/ctf.Tm,YY(w)/ctf.Tm);
531  return fabs(ctf.getValueAt());
532  break;
533  case CTFINV:
534  {
535  ctf.precomputeValues(XX(w)/ctf.Tm,YY(w)/ctf.Tm);
536  double ctfval=ctf.getValueAt();
537  if (fabs(ctfval)<=minCTF)
538  return 0.0;
539  else
540  return 1.0/ctfval;
541  }
542  break;
543  case CTFPOSINV:
544  {
545  ctf.precomputeValues(XX(w)/ctf.Tm,YY(w)/ctf.Tm);
546  double ctfval=fabs(ctf.getValueAt());
547  if (ctfval<=minCTF)
548  return 0.0;
549  else
550  return 1.0/ctfval;
551  }
552  break;
553  case CTFDEF:
554  {
555  ctf.precomputeValues(XX(w)/ctf.Tm,YY(w)/ctf.Tm);
556  return ctf.getValueAt();
557  }
558  break;
559  case BFACTOR:
560  {
561  double R = absw / sampling_rate;
562  return exp( - (w1 / 4.) * R * R);
563  }
564  break;
565  case FSCPROFILE:
566  {
567  double R = absw / sampling_rate;
568  int idx=-1;
569  size_t imax=freqContFSC.size();
570  double *ptrFreq=&freqContFSC[0];
571  for (size_t i=0; i<imax; ++i)
572  if (ptrFreq[i]>R)
573  {
574  idx=(int)i;
575  break;
576  }
577  if (idx>=1)
578  {
579  double x0=freqContFSC[idx-1];
580  double x1=freqContFSC[idx];
581  double y0=FSC[idx-1];
582  double y1=FSC[idx];
583  return y0+(y1-y0)*(R-x0)/(x1-x0);
584  }
585  return 0;
586  }
587  case ASTIGMATISMPROFILE:
588  {
589  double R = absw / sampling_rate;
590  ctf.precomputeValues(R,0.0);
591  double phaseU=ctf.getPhaseAt();
592  ctf.precomputeValues(0.0,R);
593  double phaseV=ctf.getPhaseAt();
594  double diff=(phaseV-phaseU)*0.5;
595  return exp(-0.5*diff*diff/(w1*w1));
596  }
597  break;
598  default:
599  REPORT_ERROR(ERR_ARG_INCORRECT,"Unknown mask type");
600  }
601  return 0;
602 }
603 
604 /* Generate mask ----------------------------------------------------------- */
606 {
607  if (FilterShape==SPARSIFY)
608  return;
609 
610  if (FilterShape==FSCPROFILE)
611  {
612  MetaDataVec mdFSC(fnFSC);
615  }
616  // std::cout << "Generating mask " << do_generate_3dmask << std::endl;
617 
618  if (do_generate_3dmask)
619  {
620  transformer.setReal(v);
622  transformer.getFourierAlias(Fourier);
623 
625  {
626  maskFourier.initZeros(Fourier);
628  switch (FilterShape)
629  {
630  case WEDGE:
631  {
633  Euler_angles2matrix(rot,tilt,psi,A,false);
634  BinaryWedgeMask(maskFourier, t1, t2, A,true);
635  break;
636  }
637  case WEDGE_RC:
638  {
640  Euler_angles2matrix(rot,tilt,psi,A,false);
641  BinaryWedgeMask(maskFourier, t1, t2, A,true);
642  break;
643  }
644  case CONE:
645  BinaryConeMask(maskFourier, 90. - fabs(t1),INNER_MASK,true);
646  break;
647  }
648  }
649  else if (FilterShape==BINARYFILE)
650  {
651  Image<double> filter;
652  filter.read(fnFilter);
654  maskFourierd.resize(Fourier);
655  return;
656  }
657 
658  else
659  {
660  maskFourierd.initZeros(Fourier);
662 
663  w.resizeNoCopy(3);
664  for (size_t k=0; k<ZSIZE(Fourier); k++)
665  {
666  FFT_IDX2DIGFREQ(k,ZSIZE(v),ZZ(w));
667  for (size_t i=0; i<YSIZE(Fourier); i++)
668  {
669  FFT_IDX2DIGFREQ(i,YSIZE(v),YY(w));
670  for (size_t j=0; j<XSIZE(Fourier); j++)
671  {
672  FFT_IDX2DIGFREQ(j,XSIZE(v),XX(w));
674  }
675  }
676  }
677  }
678  }
679  else if (MULTIDIM_SIZE(v)<=1024*1024)
680  {
681  transformer.setReal(v);
683  transformer.getFourierAlias(Fourier);
684  if (FilterShape==BINARYFILE)
685  {
686  Image<double> filter;
687  filter.read(fnFilter);
689  maskFourierd.resize(Fourier);
690  return;
691  }
692  maskFourierd.initZeros(Fourier);
693  w.resizeNoCopy(3);
694  for (size_t k=0; k<ZSIZE(Fourier); k++)
695  {
696  FFT_IDX2DIGFREQ(k,ZSIZE(v),ZZ(w));
697  for (size_t i=0; i<YSIZE(Fourier); i++)
698  {
699  FFT_IDX2DIGFREQ(i,YSIZE(v),YY(w));
700  for (size_t j=0; j<XSIZE(Fourier); j++)
701  {
702  FFT_IDX2DIGFREQ(j,XSIZE(v),XX(w));
704  }
705  }
706  }
707  }
708 }
709 
711 {
713  transformer.FourierTransform(v, aux3D, false);
714  applyMaskFourierSpace(v, aux3D);
716 }
717 
719 {
720  if (XSIZE(maskFourier)!=0 && !FilterShape==WEDGE_RC)
721  {
724  }
725  else if (XSIZE(maskFourierd)!=0)
726  {
727  auto *ptrV=(double*)&DIRECT_MULTIDIM_ELEM(V,0);
728  auto *ptrMask=(double*)&DIRECT_MULTIDIM_ELEM(maskFourierd,0);
730  {
731  *ptrV++ *= *ptrMask;
732  *ptrV++ *= *ptrMask++;
733  }
734  }
735  else if (FilterShape==SPARSIFY)
736  {
737  FFT_magnitude(V,vMag);
738  vMag.resize(1,1,1,MULTIDIM_SIZE(vMag));
740  double minMagnitude=A1D_ELEM(vMagSorted,(int)(percentage*XSIZE(vMag)));
742  if (DIRECT_MULTIDIM_ELEM(vMag,n)<minMagnitude)
743  {
744  auto *ptr=(double*)&DIRECT_MULTIDIM_ELEM(V,n);
745  *ptr=0;
746  *(ptr+1)=0;
747  }
748  }
749  else if (FilterShape==WEDGE_RC)
750  {
753 
754  w.resizeNoCopy(3);
755  for (size_t k=0; k<ZSIZE(V); k++)
756  {
757  FFT_IDX2DIGFREQ(k,ZSIZE(v),ZZ(w));
758  for (size_t i=0; i<YSIZE(V); i++)
759  {
760  FFT_IDX2DIGFREQ(i,YSIZE(v),YY(w));
761  for (size_t j=0; j<XSIZE(V); j++)
762  {
763  FFT_IDX2DIGFREQ(j,XSIZE(v),XX(w));
765  }
766  }
767  }
768  }
769  else if (FilterShape==WEDGE) {
772  }
773  else
774  {
775  w.resizeNoCopy(3);
776  for (size_t k=0; k<ZSIZE(V); k++)
777  {
778  FFT_IDX2DIGFREQ(k,ZSIZE(v),ZZ(w));
779  for (size_t i=0; i<YSIZE(V); i++)
780  {
781  FFT_IDX2DIGFREQ(i,YSIZE(v),YY(w));
782  for (size_t j=0; j<XSIZE(V); j++)
783  {
784  FFT_IDX2DIGFREQ(j,XSIZE(v),XX(w));
786  }
787  }
788  }
789  }
790 }
791 
792 /* Mask power -------------------------------------------------------------- */
794 {
795  if (XSIZE(maskFourier) != 0)
797  else if (XSIZE(maskFourierd) != 0)
799  else
800  return 0;
801 }
802 
803 // Correct phase -----------------------------------------------------------
805 {
809 }
810 
811 // Bandpass -----------------------------------------------------------------
812 void bandpassFilter(MultidimArray<double> &img, double w1, double w2, double raised_w)
813 {
814  FourierFilter Filter;
815  if (w1==0)
816  {
817  Filter.FilterBand=LOWPASS;
818  Filter.w1=w2;
819  }
820  else if (w2==0.5)
821  {
822  Filter.FilterBand=HIGHPASS;
823  Filter.w1=w1;
824  }
825  else
826  {
827  Filter.FilterBand=BANDPASS;
828  Filter.w1=w1;
829  Filter.w2=w2;
830  }
831  Filter.FilterShape = RAISED_COSINE;
832  Filter.raised_w=raised_w;
833  img.setXmippOrigin();
834  Filter.generateMask(img);
835  Filter.applyMaskSpace(img);
836 }
837 
839 {
840  FourierFilter Filter;
841  Filter.FilterShape = GAUSSIAN;
842  Filter.FilterBand = LOWPASS;
843  Filter.w1=w1;
844  img.setXmippOrigin();
845  Filter.generateMask(img);
846  Filter.applyMaskSpace(img);
847 }
848 
850 {
851  FourierFilter Filter;
852  Filter.FilterShape = REALGAUSSIAN;
853  Filter.FilterBand = LOWPASS;
854  Filter.w1=sigma;
855  img.setXmippOrigin();
856  Filter.generateMask(img);
857  Filter.applyMaskSpace(img);
858 }
859 
862 {
863  program->addParamsLine("== Soft negative pixels ==");
864  program->addParamsLine(
865  " [ --softnegative <mask_file> <fsc> <Ts=1> <K=2>] : Removes strong negative values inside the mask");
866  program->addParamsLine(" : Ts is the sampling rate in A/pix");
867 }
868 
871 {
872  mask.read(program->getParam("--softnegative",0));
873  fnFSC=program->getParam("--softnegative",1);
874  Ts = program->getDoubleParam("--softnegative",2);
875  K = program->getDoubleParam("--softnegative",3);
876 }
877 
880 {
881  // Invert the mask and measure stddev outside the mask
882  MultidimArray<int> &mMask=mask();
883  mMask.setXmippOrigin();
884  img.setXmippOrigin();
885  double sum=0;
886  double sum2=0;
887  double N=0;
888  auto R2max=(double)((XSIZE(img)/2)*(XSIZE(img)/2));
890  {
891  A3D_ELEM(mMask,k,i,j)=1-A3D_ELEM(mMask,k,i,j);
892  if (A3D_ELEM(mMask,k,i,j))
893  {
894  double R2=i*i+j*j+k*k;
895  if (R2<R2max)
896  {
897  double val=A3D_ELEM(img,k,i,j);
898  sum+=val;
899  sum2+=val*val;
900  N+=1;
901  }
902  }
903  }
904  double avg=sum/N;
905  double stddev=sqrt(sum2/N-avg*avg);
906 
907  // Measure the stddev outside the structure
908  // double avg, stddev;
909  // img.computeAvgStdev_within_binary_mask(mMask,avg,stddev);
910 
911  // Find the too negative values
912  double threshold=-K*stddev;
913  if (avg<0)
914  threshold+=avg;
915  // std::cout << "avg=" << avg << " sigma=" << stddev << " threshold=" << threshold << std::endl;
916  MultidimArray<double> softMask;
917  MultidimArray<double> imgThresholded;
918  softMask.initZeros(mMask);
919  imgThresholded.initZeros(mMask);
921  if (DIRECT_MULTIDIM_ELEM(img,n)>=threshold)
922  {
923  DIRECT_MULTIDIM_ELEM(softMask,n)=1;
924  DIRECT_MULTIDIM_ELEM(imgThresholded,n)=DIRECT_MULTIDIM_ELEM(img,n);
925  }
926  mask.clear(); // Free memory
927 // Image<double> save;
928 // save()=softMask; save.write("PPPsoftmask.vol");
929 
930  FourierFilter filter;
931  filter.FilterBand=filter.FilterShape=FSCPROFILE;
932  filter.fnFSC=fnFSC;
933  filter.sampling_rate=Ts;
934  filter.generateMask(softMask);
935  filter.applyMaskSpace(softMask);
936  filter.applyMaskSpace(imgThresholded);
937  softMask+=1;
938 // save()=softMask; save.write("PPPsoftmaskFiltered.vol");
939 // save()=imgThresholded; save.write("PPPthresholded.vol");
940 
942  {
943  DIRECT_MULTIDIM_ELEM(softMask,n)=CLIP(DIRECT_MULTIDIM_ELEM(softMask,n),0,1);
945  (1-DIRECT_MULTIDIM_ELEM(softMask,n))*DIRECT_MULTIDIM_ELEM(imgThresholded,n);
946  }
947 // save()=softMask; save.write("PPPsoftmaskFilteredClipped.vol");
948 }
#define SPARSIFY
#define ASTIGMATISMPROFILE
#define CONE
void BinaryConeMask(MultidimArray< int > &mask, double theta, int mode, bool centerOrigin)
Definition: mask.cpp:488
#define YSIZE(v)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
double module() const
Definition: matrix1d.h:983
double getDoubleParam(const char *param, int arg=0)
CTFDescription ctf
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
#define CTFINV
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void sort(MultidimArray< T > &result) const
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
#define MULTIDIM_SIZE(v)
void readParams(XmippProgram *program)
#define DEG2RAD(d)
Definition: xmipp_macros.h:312
FileName fnFilter
void BinaryWedgeMask(MultidimArray< int > &mask, double theta0, double thetaF, const Matrix2D< double > &A, bool centerOrigin)
Definition: mask.cpp:524
Just for debugging, situation that can&#39;t happens.
Definition: xmipp_error.h:120
void sqrt(Image< double > &op)
void gaussianFilter(MultidimArray< double > &img, double w1)
static void defineParams(XmippProgram *program)
#define BANDPASS
double DeltafV
Defocus in V (in Angstroms). Negative values are underfocused.
Definition: ctf.h:830
std::vector< double > FSC
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 apply(MultidimArray< double > &img)
The matrix is empty.
Definition: xmipp_error.h:151
#define A1D_ELEM(v, i)
MultidimArray< double > vMag
MultidimArray< double > maskFourierd
#define i
#define WEDGE
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
Matrix1D< double > w
void read(const FileName &fn, bool disable_if_not_K=true)
Definition: ctf.cpp:1220
#define CTFDEF
#define STOPLOWBANDX
double DeltafU
Global gain. By default, 1.
Definition: ctf.h:828
#define CLIP(x, x0, xF)
Definition: xmipp_macros.h:260
void threshold(double *phi, unsigned long nvox, double limit)
Definition: lib_vwk.cpp:524
#define A3D_ELEM(V, k, i, j)
double azimuthal_angle
Azimuthal angle (between X and U) in degrees.
Definition: ctf.h:832
double sampling_rate
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
#define BINARYFILE
#define y0
const char * getParam(const char *param, int arg=0)
#define x0
#define XX(v)
Definition: matrix1d.h:85
void apply(MultidimArray< double > &img)
double getValueAt(bool show=false) const
Compute CTF at (U,V). Continuous frequencies.
Definition: ctf.h:1050
void setReal(MultidimArray< double > &img)
Definition: xmipp_fftw.cpp:129
#define REALGAUSSIANZ
#define CTF
Incorrect argument received.
Definition: xmipp_error.h:113
#define BFACTOR
#define XSIZE(v)
#define HIGHPASS
#define RAISED_COSINE
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
double Tm
Sampling rate (A/pixel)
Definition: ctf.h:240
#define ZSIZE(v)
#define DIRECT_MULTIDIM_ELEM(v, n)
#define STOPBAND
void precomputeValues(double X, double Y)
Precompute values for a given frequency.
Definition: ctf.h:1002
#define CTFPOSINV
double Cs
Spherical aberration (in milimeters). Typical value 5.6.
Definition: ctf.h:246
#define DIRECT_A3D_ELEM(v, k, i, j)
void FourierTransform(T &v, T1 &V, bool getCopy=true)
Definition: xmipp_fftw.h:166
double maskValue(const Matrix1D< double > &w)
__device__ float FFT_IDX2DIGFREQ(int idx, int size)
std::vector< double > freqContFSC
#define j
Frequency in 1/A (double)
void scaleToSize(int SplineDegree, MultidimArrayGeneric &V2, const MultidimArrayGeneric &V1, int Xdim, int Ydim, int Zdim)
void bandpassFilter(MultidimArray< double > &img, double w1, double w2, double raised_w)
#define FSCPROFILE
#define YY(v)
Definition: matrix1d.h:93
void getColumnValues(const MDLabel label, std::vector< MDObject > &valuesOut) const override
#define WEDGE_RC
double sum2() const
#define CTFPOS
MultidimArray< double > vMagSorted
void realGaussianFilter(MultidimArray< double > &img, double sigma)
#define RAD2DEG(r)
Definition: xmipp_macros.h:320
void getFourierAlias(T &V)
Definition: xmipp_fftw.h:207
#define STOPLOWBANDY
std::string String
Definition: xmipp_strings.h:34
void produceSideInfo()
Produce Side information.
Definition: ctf.cpp:1392
void readParams(XmippProgram *program)
void applyMaskFourierSpace(const MultidimArray< double > &v, MultidimArray< std::complex< double > > &V)
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458
bool checkParam(const char *param)
double Q0
Factor for the importance of the Amplitude contrast.
Definition: ctf.h:261
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
MultidimArray< int > maskFourier
constexpr int K
void clear()
Clear.
Definition: ctf.cpp:1366
#define REALGAUSSIAN
Incorrect file size.
Definition: xmipp_error.h:145
double kV
Accelerating Voltage (in KiloVolts)
Definition: ctf.h:242
void initZeros(const MultidimArray< T1 > &op)
bool enable_CTFnoise
Enable CTFnoise part.
Definition: ctf.h:273
#define GAUSSIAN
#define PI
Definition: tools.h:43
#define REALGAUSSIANZ2
void FFT_magnitude(const MultidimArray< std::complex< double > > &v, MultidimArray< double > &mag)
Definition: xmipp_fftw.cpp:393
void generateMask(MultidimArray< double > &v)
int * n
FourierTransformer transformer
#define ZZ(v)
Definition: matrix1d.h:101
double getPhaseAt() const
Get Phase of the CTF.
Definition: ctf.h:1063
#define LOWPASS
void addParamsLine(const String &line)
void applyMaskSpace(MultidimArray< double > &v)
static void defineParams(XmippProgram *program)
Fourier shell correlation (double)
constexpr int INNER_MASK
Definition: mask.h:47