Xmipp  v3.23.11-Nereus
phantom_simulate_microscope.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 
29 #include "core/histogram.h"
30 #include "core/transformations.h"
31 
32 /* Read parameters --------------------------------------------------------- */
34 {
36 
37  fn_ctf = "";//initialize empty, force recalculation of first time
38  pmdIn = dynamic_cast<MetaDataVec*>(getInputMd());
39  CTFpresent=true;
40  if (checkParam("--ctf"))
41  {
42  //Fill the input metadata with the value of 'fn_ctf'
43  fn_ctf=getParam("--ctf");
44  MDConstGenerator generator(fn_ctf);
45  generator.label = MDL_CTF_MODEL;
46  generator.fill(*pmdIn);
47  }
48  else
49  {
51  {
52  //sort the images according to the ctf to avoid the recaculation of it
53  //beeten images of the same ctf group
54  MetaDataDb md(*pmdIn);
55  pmdIn->sort(md, MDL_CTF_MODEL);
56  }
57  else
58  CTFpresent=false;
59  }
60  after_ctf_noise = checkParam("--after_ctf_noise");
61  defocus_change = getDoubleParam("--defocus_change");
62  if (checkParam("--noise"))
63  {
64  sigma = getDoubleParam("--noise");
65  low_pass_before_CTF = getDoubleParam("--noise",1);
66  estimateSNR=false;
67  }
68  else if (checkParam("--noNoise"))
69  {
70  estimateSNR=0;
71  sigma=0;
73  }
74  else
75  {
76  targetSNR = getDoubleParam("--targetSNR");
78  estimateSNR=true;
79  }
80  downsampling = getDoubleParam("--downsampling");
81 
82 }
83 
84 /* Usage ------------------------------------------------------------------- */
86 {
88  save_metadata_stack = true;
90  addUsageLine("Simulate the effect of the microscope on ideal projections.");
91  addParamsLine("==CTF options==");
92  addParamsLine(" [--ctf <CTFdescr=\"\">] : a CTF description, if this param is not supplied it should come in metadata");
93  addParamsLine(" [--after_ctf_noise] : apply noise after CTF");
94  addParamsLine(" [--defocus_change <v=0>] : change in the defocus value (percentage)");
95  addParamsLine("==Noise options==");
96  addParamsLine(" --noise <stddev> <w=0.5> : noise to be added, this noise is filtered at the frequency specified (<0.5).");
97  addParamsLine("or --targetSNR <snr> : the necessary noise power for a specified SNR is estimated");
98  addParamsLine("or --noNoise : do not add any noise, only simulate the CTF");
99  addParamsLine(" [--downsampling <D=1>] : Downsampling factor of the input micrograph with respect to the original");
100  addParamsLine(" : micrograph.");
101  addExampleLine("Generate a set of images with the CTF applied without any noise", false);
102  addExampleLine(" xmipp_phantom_simulate_microscope -i g0ta.sel --oroot g1ta --ctf untilt_ARMAavg.ctfparam");
103  addExampleLine("Generate a set of images with a target SNR", false);
104  addExampleLine(" xmipp_phantom_simulate_microscope -i g0ta.sel --oroot g2ta --ctf untilt_ARMAavg.ctfparam --targetSNR 0.2 --after_ctf_noise");
105  addExampleLine("Generate a set of images with the CTF applied and noise before and after CTF", false);
106  addExampleLine(" xmipp_phantom_simulate_microscope -i g0ta.sel --oroot g2ta --ctf untilt_ARMAavg.ctfparam --noise 4.15773 --after_ctf_noise");
107 }
108 
109 /* Show -------------------------------------------------------------------- */
111 {
112  if (!verbose)
113  return;
115  std::cout
116  << "Noise: " << sigma << std::endl
117  << "Low pass freq: " << low_pass_before_CTF << std::endl
118  << "After CTF noise: " << after_ctf_noise << std::endl
119  << "Defocus change: " << defocus_change << std::endl
120  ;
121  if (estimateSNR)
122  std::cout
123  << "Target SNR: " << targetSNR << std::endl;
124  if (CTFpresent)
125  std::cout << "CTF file: " << fn_ctf << std::endl;
126  else
127  std::cout << "No CTF provided\n";
128 }
129 
131 {
132  if (CTFpresent)
133  {
134  ctf.FilterBand = CTF;
135  ctf.ctf.enable_CTFnoise = false;
136  ctf.ctf.read(getParam("--ctf"));
139  }
140 
141  size_t N_stats = pmdIn->size();
142  std::cout << "N_stats=" << N_stats << std::endl;
143 
144  MultidimArray<double> proj_power(N_stats);
145  MultidimArray<double> proj_area(N_stats);
146  double power_avg=0., power_stddev, area_avg=0., area_stddev, avg, dummy;
147  if (verbose!=0)
148  {
149  std::cerr << "Estimating noise power for target SNR=" << targetSNR << std::endl;
150  init_progress_bar(N_stats);
151  }
152  FileName fnImg;
153  Image<double> proj;
154  size_t nImg=0;
155  for (size_t objId : pmdIn->ids())
156  {
157  pmdIn->getValue(image_label, fnImg,objId);
158  proj.read(fnImg);
159  MultidimArray<double> mProj=proj();
160 
161  if (CTFpresent)
162  {
163  if (nImg == 0)
164  ctf.generateMask(mProj);
165  ctf.applyMaskSpace(mProj);
166  }
167 
168  // Compute projection area
169  DIRECT_A1D_ELEM(proj_area,nImg) = 0;
171  if (fabs(DIRECT_MULTIDIM_ELEM(mProj,n)) > 1e-6)
172  DIRECT_A1D_ELEM(proj_area,nImg)++;
173 
174  // Compute projection power
175  mProj.computeStats(avg, DIRECT_A1D_ELEM(proj_power,nImg), dummy, dummy);
176 
177  if (nImg++ % 30 == 0 && verbose!=0)
178  progress_bar(nImg);
179  }
180  progress_bar(N_stats);
181  Histogram1D hist_proj, hist_area;
182  compute_hist(proj_power, hist_proj, 300);
183  compute_hist(proj_area, hist_area, 300);
184  proj_power.computeStats(power_avg, power_stddev, dummy, dummy);
185  std::cout << "# Projection power average: " << power_avg << std::endl
186  << "# Projection power stddev: " << power_stddev << std::endl
187  << "# Projection percentil 2.5%: " << hist_proj.percentil(2.5) << std::endl
188  << "# Projection percentil 97.5%: " << hist_proj.percentil(97.5) << std::endl;
189  proj_area.computeStats(area_avg, area_stddev, dummy, dummy);
190  std::cout << "# Projection area average: " << area_avg << std::endl
191  << "# Projection area stddev: " << area_stddev << std::endl
192  << "# Area percentil 2.5%: " << hist_area.percentil(2.5) << std::endl
193  << "# Area percentil 97.5%: " << hist_area.percentil(97.5) << std::endl;
194 
195  sigma=sqrt(power_avg*power_avg*Xdim*Ydim / (targetSNR*area_avg));
196  std::cout << "Estimated sigma=" << sigma << std::endl;
197  updateCtfs();
198 }
199 
201  double &power)
202 {
203  static int dXdim = 2 * Xdim, dYdim = 2 * Ydim;
204  static MultidimArray<double> aux;
205 
206  filter.FilterBand = CTF;
207  filter.ctf.read(fn_ctf);
210  filter.ctf.enable_CTF = !isBackground;
211  filter.ctf.enable_CTFnoise = isBackground;
212  filter.ctf.produceSideInfo();
213  aux.resizeNoCopy(dYdim, dXdim);
214  aux.setXmippOrigin();
215  filter.do_generate_3dmask=true;
216  filter.generateMask(aux);
217  power = filter.maskPower();
218 }
219 
221 {
222  double before_power = 0, after_power = 0;
224 
225  if (CTFpresent)
226  {
227  setupFourierFilter(ctf, false, before_power);
228  if (after_ctf_noise)
229  setupFourierFilter(after_ctf, true, after_power);
230  }
231 
232  // Compute noise balance
233  if ((after_power != 0 || before_power != 0) && sigma!=0)
234  {
235  double p = after_power / (after_power + before_power);
236  double K = 1 / sqrt(p * after_power + (1 - p) * before_power);
237  sigma_after_CTF = sqrt(p) * K * sigma;
238  sigma_before_CTF = sqrt(1 - p) * K * sigma;
239  }
240  else if (sigma != 0)
241  {
243  sigma_after_CTF = 0;
244  }
245  else
247 }
248 
249 /* Produce side information ------------------------------------------------ */
251 {
253  size_t dum, dum2;
254  getImageSize(*pmdIn, Xdim, Ydim, dum, dum2);
255 
256  if (low_pass_before_CTF < 0.5)
257  {
261  }
262 
263  if (estimateSNR)
264  estimateSigma();
265 }
266 
267 void ProgSimulateMicroscope::processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
268 {
269  static Image<double> img;
270  static FileName last_ctf;
271  static bool firstImage=true;
272  last_ctf = fn_ctf;
273  img.read(fnImg);
274 
275  rowOut=rowIn;
276 
277  rowIn.getValue(MDL_CTF_MODEL, fn_ctf);
278  rowOut.setValue(MDL_IMAGE, fnImgOut);
279  rowOut.setValue(MDL_CTF_MODEL, fn_ctf);
280  if (fn_ctf != last_ctf || firstImage)
281  {
282  updateCtfs();
283  firstImage=false;
284  }
285 
286  if (ZSIZE(img())!=1)
287  REPORT_ERROR(ERR_MULTIDIM_DIM,"This process is not intended for volumes");
288 
289  apply(img());
290 
291  img.write(fnImgOut);
292 }
293 
294 /* Apply ------------------------------------------------------------------- */
296 {
297  I.setXmippOrigin();
300 
301  // Add noise before CTF
302  MultidimArray<double> noisy;
303  noisy.resize(I);
305  if (low_pass_before_CTF < 0.5)
306  lowpass.applyMaskSpace(noisy);
307  I += noisy;
308 
309  if (CTFpresent)
310  {
311  // Check if the mask is a defocus changing CTF
312  // In that case generate a new mask with a random defocus
313  if (defocus_change != 0)
314  {
316  ctf.ctf.DeltafU = defocusU * rnd_unif(1 - defocus_change / 100, 1 + defocus_change / 100);
317  ctf.ctf.DeltafV = defocusV *rnd_unif(1 - defocus_change / 100, 1 + defocus_change / 100);
318  aux.initZeros(2*Ydim, 2*Xdim);
319  ctf.generateMask(aux);
320  }
321 
322  // Apply CTF
323  ctf.applyMaskSpace(I);
324 
325  // Add noise after CTF
327  if (after_ctf_noise)
328  after_ctf.applyMaskSpace(noisy);
329  I += noisy;
330  }
333 }
void init_progress_bar(long total)
double defocus_change
Defocus change (%)
void selfWindow(int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T init_value=0)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
void apply(MultidimArray< double > &I)
void sort(const MetaDataVec &MDin, const MDLabel sortLabel, bool asc=true, int limit=-1, int offset=0)
double getDoubleParam(const char *param, int arg=0)
CTFDescription ctf
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void initRandom(double op1, double op2, RandomMode mode=RND_UNIFORM)
size_t Ydim
Input image Ydim.
void resizeNoCopy(const MultidimArray< T1 > &v)
void sqrt(Image< double > &op)
double low_pass_before_CTF
Low pass frequency before CTF.
void computeStats(double &avg, double &stddev, T &minval, T &maxval) const
void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
double DeltafV
Defocus in V (in Angstroms). Negative values are underfocused.
Definition: ctf.h:830
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)
bool after_ctf_noise
Filename with the root squared spectrum for noise after CTF.
void getImageSize(const MetaData &md, size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim, MDLabel image_label)
Name for the CTF Model (std::string)
void changeSamplingRate(double newTm)
Definition: ctf.h:994
double percentil(double percent_mass)
Definition: histogram.cpp:160
FileName fn_ctf
Filename with the CTF.
virtual IdIteratorProxy< false > ids()
double sigma_after_CTF
Noise power after CTF.
size_t size() const override
void read(const FileName &fn, bool disable_if_not_K=true)
Definition: ctf.cpp:1220
double DeltafU
Global gain. By default, 1.
Definition: ctf.h:828
bool enable_CTF
Enable CTF part.
Definition: ctf.h:275
double sigma_before_CTF
Noise power before CTF.
double rnd_unif()
#define DIRECT_A1D_ELEM(v, i)
T & getValue(MDLabel label)
const char * getParam(const char *param, int arg=0)
void compute_hist(const MultidimArrayGeneric &array, Histogram1D &hist, int no_steps)
Definition: histogram.cpp:572
#define CTF
double sigma
Total noise power.
FourierFilter lowpass
Low pass filter, if it is 0 no lowpass filter is applied.
void progress_bar(long rlen)
#define RAISED_COSINE
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
FourierFilter after_ctf
After CTF noise root squared spectrum.
double Tm
Sampling rate (A/pixel)
Definition: ctf.h:240
#define ZSIZE(v)
#define DIRECT_MULTIDIM_ELEM(v, n)
void addExampleLine(const char *example, bool verbatim=true)
int verbose
Verbosity level.
double dummy
MDLabel image_label
MDLabel to be used to read/write images, usually will be MDL_IMAGE.
size_t Xdim
Input image Xdim.
bool getValue(MDObject &mdValueOut, size_t id) const override
void power(Image< double > &op)
void setValue(MDLabel label, const T &d, bool addLabel=true)
void show() const override
bool save_metadata_stack
Save the associated output metadata when output file is a stack.
#define FIRST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:439
void produceSideInfo()
Produce Side information.
Definition: ctf.cpp:1392
bool checkParam(const char *param)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
MetaDataVec * pmdIn
Particular reference to mdIn to manipulated.
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
constexpr int K
bool each_image_produces_an_output
Indicate that an output is produced for each image in the input.
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
unsigned int randomize_random_generator()
bool containsLabel(const MDLabel label) const override
bool enable_CTFnoise
Enable CTFnoise part.
Definition: ctf.h:273
#define LAST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:448
void generateMask(MultidimArray< double > &v)
int * n
Name of an image (std::string)
#define LOWPASS
void addParamsLine(const String &line)
void applyMaskSpace(MultidimArray< double > &v)
void setupFourierFilter(FourierFilter &filter, bool isBackground, double &power)
void fill(MetaData &md)