Xmipp  v3.23.11-Nereus
movie_filter_dose.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Roberto Marabini roberto@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 "movie_filter_dose.h"
28 #include "core/metadata_vec.h"
29 #include "data/fourier_filter.h"
30 
31 #define OUTSIDE_WRAP 0
32 #define OUTSIDE_AVG 1
33 #define OUTSIDE_VALUE 2
34 
35 // Read arguments ==========================================================
39  user_supplied_first_frame = getIntParam("--frameRange", 0);
40  user_supplied_last_frame = getIntParam("--frameRange", 1);
41  pixel_size = getDoubleParam("--sampling");
42  dose_per_frame = getDoubleParam("--dosePerFrame");
43  acceleration_voltage = getDoubleParam("--accVoltage");
45  pre_exposure_amount = getDoubleParam("--preExposure");
46  //restore_power = checkParam("--restoreNoiPow");
47 
48 }
49 
50 // Show ====================================================================
52  if (!verbose)
53  return;
54  std::cout << "Input movie: " << user_supplied_input_filename
55  << std::endl << "Output movie: "
56  << user_supplied_output_filename << std::endl
57  << "Frame range alignment: " << user_supplied_first_frame << " "
58  << user_supplied_last_frame << std::endl
59  << "Sampling: " << pixel_size << std::endl
60  << "Dose per Frame (e/A^2): " << dose_per_frame << std::endl
61  << "Acceleration_Voltage (kV): " << acceleration_voltage
62  << std::endl << "Pre-exposure Amount (e/A^2): "
63  << pre_exposure_amount << std::endl
64  << "Restore Power after Filter: " << restore_power << std::endl;
65 }
66 
67 // usage ===================================================================
69  addUsageLine("Align a set of frames by cross-correlation of the frames");
70  addParamsLine(" -i <movie> : input movie");
71  addParamsLine(" [-o <fn=\"out.mrcs\">] : output filtered movie.");
73  " [--frameRange <n0=-1> <nF=-1>] : First and last frame to align, frame numbers start at 0");
74  addParamsLine(" [--sampling <Ts=1>] : Sampling rate (A/pixel)");
75  addParamsLine(" [--dosePerFrame <dose=2>] : Dose per frame (e/A^2)");
77  " [--accVoltage <voltage=300>] : Acceleration voltage (kV) min_value=200.0e0,max_value=300.0e0)");
78  addParamsLine(" [--preExposure <preExp=0>] : P (e/A^2)");
79 // addParamsLine(
80 // " [--restoreNoiPow] : Restore noise power after filtering? (default=false)");
81  addExampleLine("A typical example", false);
82  addExampleLine("xmipp_cxzczxczccxztobedone");
83 }
84 
85 double ProgMovieFilterDose::doseFilter(double dose_at_end_of_frame,
86  double critical_dose) {
87  return exp((-0.5 * dose_at_end_of_frame) / critical_dose);
88 }
89 
90 double ProgMovieFilterDose::criticalDose(double spatial_frequency) {
91  return ((critical_dose_a * pow(spatial_frequency, critical_dose_b))
93 }
95  return 2.51284 * critical_dose;
96 }
97 
100  critical_dose_a = 0.24499;
101  critical_dose_b = -1.6649;
102  critical_dose_c = 2.8141;
103  // init with a very large number
105 
106 }
108  init();
109 }
110 
111 void ProgMovieFilterDose::initVoltage(double accelerationVoltage) {
112  if (accelerationVoltage < 301 && accelerationVoltage > 299.) {
113  acceleration_voltage = 300.0;
115  } else if (accelerationVoltage < 201.0 && accelerationVoltage > 199.0) {
116  acceleration_voltage = 200.0;
118  } else
120  "Bad acceleration voltage (must be 200 or 300 kV");
121 
122  }
123 
124 ProgMovieFilterDose::ProgMovieFilterDose(double accelerationVoltage) {
125  init();
126  initVoltage(accelerationVoltage);
127 }
128 
129 
131  int Ydim, int Xdim,
132  const MultidimArray<std::complex<double> > &FFT1,
133  const double dose_start, const double dose_finish) {
134  std::complex<double> complex_zero = 0;
135  double x, y;
136  double yy;
137  double current_critical_dose, current_optimal_dose;
138  int sizeX_2 = Xdim / 2;
139  double ixsize = 1.0 / Xdim;
140  int sizeY_2 = Ydim / 2;
141  double iysize = 1.0 / Ydim;
142  for (long int i = 0; i < YSIZE(FFT1); i++) { //i->y,j->x xmipp convention is oposite summove
143  FFT_IDX2DIGFREQ_FAST(i, Ydim, sizeY_2, iysize, y);
144  yy = y * y;
145  for (long int j = 0; j < XSIZE(FFT1); j++) {
146  FFT_IDX2DIGFREQ_FAST(j, Xdim, sizeX_2, ixsize, x);
147 #ifdef DEBUG_FFT_FREQ
148  std::cerr << "(j+1,i+1)(x,y)=" << j +1 << "," << i + 1<< " "
149  << x << " " << y << " = "
150  << DIRECT_A2D_ELEM(FFT1, i, j) << std::endl;
151 #endif
152  if (i == 0 && j == 0)
153  //ROB: I do not understand this step
154  //It forces the origin to 0
155  //Why not keep the value?
156  current_critical_dose = critical_dose_at_dc;
157  else
158  current_critical_dose = criticalDose(
159  sqrt(x * x + yy) / pixel_size);
160  current_optimal_dose = optimalDoseGivenCriticalDose(
161  current_critical_dose);
162  if (abs(dose_finish - current_optimal_dose)
163  < abs(dose_start - current_optimal_dose)) {
164  DIRECT_A2D_ELEM(FFT1, i, j ) *= doseFilter(dose_finish,
165  current_critical_dose);
166  } else
167  DIRECT_A2D_ELEM(FFT1, i, j ) = complex_zero;
168 
169  }
170  }
171 
172 }
174  show();
175  //read movie
176  MetaDataVec movie;
177  size_t Xdim, Ydim, Zdim, Ndim;
178 
179  //if input is an stack create a metadata.
182  else {
183  ImageGeneric movieStack;
185  movieStack.getDimensions(Xdim, Ydim, Zdim, Ndim);
186  if (user_supplied_input_filename.getExtension() == "mrc" and Ndim == 1)
187  Ndim = Zdim;
188  size_t id;
189  FileName fn;
190  for (size_t i = 0; i < Ndim; i++) {
191  id = movie.addObject();
193  movie.setValue(MDL_IMAGE, fn, id);
194  }
195  }
196  //movie.write("/tmp/movie.md");
199  if (user_supplied_last_frame < 0)
200  user_supplied_last_frame = movie.size() - 1;
201 
202  //Fourier transform
203  //apply filter frame, by frame
204  if (verbose) {
205  std::cout << "Computing Fourier transform of frames ..." << std::endl;
206  init_progress_bar(movie.size());
207  }
208  size_t n = 0;
209  FourierTransformer transformer;
210  FileName fnFrame;
211  FileName fnOutFrame;
212  Image<double> frame;
213  int mode = WRITE_OVERWRITE;
214 
216  for (size_t objId : movie.ids())
217  {
219  movie.getValue(MDL_IMAGE, fnFrame, objId);
220  frame.read(fnFrame);
221  // Now do the Fourier transform and filter
222  transformer.FourierTransform(frame(), FFT1, false);
223 #ifdef PRINT_ORIGINAL_IMAGE
224  std::cerr << "n= (original image)" << n << std::endl << frame() << std::endl;
225 #endif
226 #undef DEBUG
227 //#define DEBUG
228 #ifdef DEBUG
229  //same order than summovie
230  Image<double> VFourierMag;
231  //FFT_magnitude(FFT1,VFourierMag());
232  VFourierMag().resizeNoCopy(FFT1);
233  double * ptrv=(double *)MULTIDIM_ARRAY(FFT1);
234  int counter = 0;
235  double x,y;
236  int m1sizeX = XSIZE(frame()); int m1sizeY = YSIZE(frame());
237  int sizeX_2 = m1sizeX/2; double ixsize = 1.0/m1sizeX;
238  int sizeY_2 = m1sizeY/2; double iysize = 1.0/m1sizeY;
239  for (long int i=0; i<YSIZE(FFT1); i++) {
240  FFT_IDX2DIGFREQ_FAST(i, m1sizeY, sizeY_2,iysize , y);
241  for (long int j=0; j<XSIZE(FFT1); j++) { //i=y, j=x
242  FFT_IDX2DIGFREQ_FAST(j, m1sizeX, sizeX_2,ixsize , x);
243  std::cerr << "(x,y)=" << j +1 << "," << i + 1<< " = " <<
244  DIRECT_A2D_ELEM(FFT1, i, j) <<
245  x*x << " " << y*y << " " << (x*x+y*y) << std::endl;
246  }
247  }
248  exit(1);
250  {
251  counter ++;
252  double re=*ptrv;
253  double im=*(ptrv+1);
254  std::cerr << "DEBUG_JM: n re im: " << counter << " " << re << " " << im << std::endl;
255  DIRECT_MULTIDIM_ELEM(VFourierMag(), n) =
256  log(sqrt(re*re+im*im)+1);
257  ptrv+=2;
258  }
259  VFourierMag.write("/tmp/frame_mag_1.mrc");
260  frame.write("/tmp/frame_1.mrc");
261 #endif
262 #undef DEBUG
263 #ifdef PRINTFFT
264  std::cerr << "fourier before filter " << n << std::endl
265  << FFT1 << std::endl;
266 #endif
267  applyDoseFilterToImage((int)YSIZE(frame()), (int)XSIZE(frame()), FFT1,
268  (n * dose_per_frame) + pre_exposure_amount, //dose_star
269  ((n + 1) * dose_per_frame) + pre_exposure_amount //dose_end
270  );
271 #ifdef PRINTFFTAFTERFILTER
272  std::cerr << "Fourier after filter"<< std::endl << FFT1 << std::endl;
273 #endif
274  transformer.inverseFourierTransform();
275 #ifdef PRINTREALIMAGEAFTERDOEFILTERING
276  std::cerr << "fourier matrix after inverse (very likely garbage)" << std::endl
277  << FFT1 << std::endl;
278  std::cerr << "image after filter " << std::endl
279  << frame() << std::endl;
280 #endif
282  mode = WRITE_APPEND;
283  }
284  ++n;
285  if (verbose)
286  progress_bar(n);
287  }
288  if (verbose)
289  progress_bar(movie.size());
290 
291 }
FileName user_supplied_input_filename
void init_progress_bar(long total)
#define YSIZE(v)
double getDoubleParam(const char *param, int arg=0)
void applyDoseFilterToImage(int Ydim, int Xdim, const MultidimArray< std::complex< double > > &FFT1, const double dose_start, const double dose_finish)
Apply a dose filter to the image Fourier transform.
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
double criticalDose(double spatial_frequency)
Given a spatial frequency, return the critical dose in electrons per square Angstroms.
void sqrt(Image< double > &op)
static double * y
double optimalDoseGivenCriticalDose(double critical_dose)
Given the critical dose, return an estimate of the optimal dose (at which the SNR is maximised) ...
#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)
#define MULTIDIM_ARRAY(v)
void compose(const String &str, const size_t no, const String &ext="")
void abs(Image< double > &op)
virtual IdIteratorProxy< false > ids()
doublereal * x
size_t size() const override
#define i
String getExtension() const
#define FFT_IDX2DIGFREQ_FAST(idx, size, size_2, isize, freq)
Definition: xmipp_fft.h:54
void log(Image< double > &op)
const char * getParam(const char *param, int arg=0)
void initVoltage(double accelerationVoltage)
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
Incorrect argument received.
Definition: xmipp_error.h:113
FileName user_supplied_output_filename
#define XSIZE(v)
void progress_bar(long rlen)
void max(Image< double > &op1, const Image< double > &op2)
bool restore_power
Restore noise power after filtering?&#39;, &#39;Renormalise the summed image after filtering.
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
#define DIRECT_MULTIDIM_ELEM(v, n)
void addExampleLine(const char *example, bool verbatim=true)
int verbose
Verbosity level.
void mode
void FourierTransform(T &v, T1 &V, bool getCopy=true)
Definition: xmipp_fftw.h:166
#define j
bool getValue(MDObject &mdValueOut, size_t id) const override
bool isMetaData(bool failIfNotExists=true) const
void defineParams()
Define parameters.
void readParams()
Read argument from command line.
double doseFilter(double dose_at_end_of_frame, double critical_dose)
Compute the dose filter, which is the signal attenuation.
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
#define FIRST_IMAGE
void addUsageLine(const char *line, bool verbatim=false)
int getIntParam(const char *param, int arg=0)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false)
int * n
Name of an image (std::string)
void addParamsLine(const String &line)