Xmipp  v3.23.11-Nereus
ctf_correct_wiener3d.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Sjors H.W. Scheres (scheres@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 <fstream>
27 #include "ctf_correct_wiener3d.h"
28 
29 constexpr int OVERSAMPLE = 8;
30 /* Read parameters from command line. -------------------------------------- */
32 {
33  fnIn = getParam("-i");
34  fnRoot = getParam("--oroot");
35  minFreq = getDoubleParam("--minFreq");
36  wienerConstant = getDoubleParam("--wienerConstant");
37  isFlipped = checkParam("--phase_flipped");
38 }
39 
40 /* Show -------------------------------------------------------------------- */
42 {
43  if (verbose==0)
44  return;
45  std::cout
46  << "Input file: " << fnIn << std::endl
47  << "Output rootname: " << fnRoot << std::endl
48  << "Wiener constant: " << wienerConstant << std::endl
49  << "Phase flipped: " << isFlipped << std::endl
50  ;
51  if (minFreq>0)
52  std::cout << "Apply Wiener filter only beyond: " << minFreq << std::endl;
53 }
54 
55 /* Usage ------------------------------------------------------------------- */
57 {
58  addUsageLine("Wiener filtering of volumes");
59  addUsageLine("+The program combines a set of volumes, each one with its one CTF and produces a deconvolved Wiener volume");
60 
61  addParamsLine(" -i <metadataFile> : Metadata with the volumes, ctfs, number of images in that group");
62  addParamsLine(" :+The metadata labels are _image, _CTFModel, _class_count");
63  addParamsLine(" --oroot <file> : Output rootname ");
64  addParamsLine(" :+oroot+_deconvolved.vol contains the combination of all volumes");
65  addParamsLine(" :+oroot+_ctffiltered_group01.vol contains each volume obtained after filtering the deconvolved one");
66  addParamsLine(" :+With verbose==2: oroot+_wien01.txt contains the Wiener filters in Fourier");
67  addParamsLine(" [--minFreq <Ang=-1>] : Apply Wiener filter only beyond this resolution (in Angstrom)");
68  addParamsLine(" [--phase_flipped] : Use this if the maps were reconstructed from phase corrected images ");
69  addParamsLine(" [--wienerConstant <K=0.05>] : Wiener constant (to be multiplied by the total number of images) ");
70  addExampleLine("xmipp_ctf_correct_wiener3d -i ctf_correct3d.xmd --oroot volumeCorrected");
71  addExampleLine("In the following link you can find an example of input file:",false);
72  addExampleLine(" ",false);
73  addExampleLine("http://sourceforge.net/p/testxmipp/code/ci/master/tree/input/ctf_correct3d.xmd?format=raw",false);
74 }
75 
76 /* Produce Side information ------------------------------------------------ */
78 {
79  // Read the CTFdat
80  ctfdat.read(fnIn);
81 
82  // Get dimensions of the volumes
83  size_t id = ctfdat.firstRowId();
84  FileName fnVol, fnCTF;
85  ctfdat.getValue(MDL_IMAGE,fnVol, id);
86  ctfdat.getValue(MDL_CTF_MODEL,fnCTF, id);
87  Image<double> V;
88  V.read(fnVol, HEADER);
89  size_t Ndim;
90  V.getDimensions(Xdim,Ydim,Zdim,Ndim);
91 }
92 
93 /* Make 3D CTF ------------------------------------------------------------- */
94 void ProgCtfCorrectAmplitude3D::generateCTF1D(const FileName &fnCTF, size_t nr_steps,
95  MultidimArray<double> &CTF1D)
96 {
97  // Read the CTF
98  ctf.FilterBand = CTF;
99  ctf.ctf.enable_CTFnoise = false;
100  ctf.ctf.read(fnCTF);
102 
103  double maxres = ( 0.5 * sqrt(3.) ) / ctf.ctf.Tm;
104  double stepsize = maxres / (double)nr_steps;
105  CTF1D.resizeNoCopy(nr_steps);
106  double freq = 0.;
107 
108  freq=0.;
109  for (size_t step=0; step < nr_steps; step++)
110  {
111  if ( (minFreq < 0) || (1./freq < minFreq) )
112  {
113  ctf.ctf.precomputeValues(freq, 0.0);
114  A1D_ELEM(CTF1D,step)=ctf.ctf.getValueAt();
115  if (isFlipped)
116  A1D_ELEM(CTF1D,step)=fabs(CTF1D(step));
117  }
118  else
119  A1D_ELEM(CTF1D,step)=1.;
120  freq+=stepsize;
121  }
122 }
123 
124 /* Make Wiener filters ------------------------------------------------------------- */
126 {
127  MultidimArray<double> CTF1D, sumterm;
128  std::ofstream fh;
129  double res;
130  double tot_nr_imgs = 0;
131  // Oversample the 1D CTF and Wiener filter vectors OVERSAMPLE times
132  // Use 0.55*sqrt(3) to make sure all pixels fit in...
133  auto nr_steps= (size_t)ceil(OVERSAMPLE * 0.55 * sqrt((double)(Zdim*Zdim + Ydim*Ydim + Xdim*Xdim)));
134 
135  Vctfs1D.clear();
136  Vwien1D.clear();
137  int ii = 0;
138  FileName fnVol, fnCTF;
139  for (size_t objId : ctfdat.ids())
140  {
141  // Calculate 1D CTF
142  ctfdat.getValue(MDL_IMAGE,fnVol,objId);
143  ctfdat.getValue(MDL_CTF_MODEL,fnCTF,objId);
144  generateCTF1D(fnCTF,nr_steps,CTF1D);
145  Vctfs1D.push_back(CTF1D);
146 
147  // Get the number of images contributing to this group
148  size_t NumberOfImages;
149  ctfdat.getValue(MDL_CLASS_COUNT,NumberOfImages,objId);
150  tot_nr_imgs += NumberOfImages;
151 
152  // Calculate denominator of the Wiener filter
153  if (ii==0)
154  sumterm.resizeNoCopy(CTF1D);
156  {
157  double CTF1Di=A1D_ELEM(CTF1D,i);
158  A1D_ELEM(sumterm,i) += NumberOfImages * CTF1Di * CTF1Di;
159  }
160  ii++;
161  }
162 
163  // Add (normalized) Wiener filter constant
164  sumterm += tot_nr_imgs*wienerConstant;
165 
166  double maxwien=0, minwien=1e38;
167  ii=0;
168  for (size_t objId : ctfdat.ids())
169  {
170  size_t NumberOfImages;
171  ctfdat.getValue(MDL_CLASS_COUNT,NumberOfImages,objId);
172  CTF1D=Vctfs1D[ii];
173  CTF1D*=NumberOfImages;
174  CTF1D/=sumterm;
175  Vwien1D.push_back(CTF1D);
176 
177  // Write CTF and Wiener filter curves to disc
178  if (verbose>2)
179  {
180  FileName fn_tmp;
181  fn_tmp = fnRoot + "_wien";
182  fn_tmp.compose(fn_tmp, ii+1, "txt");
183  fh.open(fn_tmp.c_str(), std::ios::out);
184  if (!fh)
185  REPORT_ERROR(ERR_IO_NOWRITE, fn_tmp);
186  for (size_t step = 0; step < nr_steps; step++)
187  {
188  res = (step * sqrt(3.) ) /
189  (OVERSAMPLE * sqrt( (double) (Zdim*Zdim + Ydim*Ydim + Xdim*Xdim) ) );
190  if (res<=0.5)
191  fh << res << " " << Vwien1D[ii](step) << " " << Vctfs1D[ii](step) << "\n";
192  }
193  fh.close();
194  }
195  ii++;
196  }
197 
198  // Some output to screen
199  std::cerr <<" ---------------------------------------------------"<<std::endl;
200  std::cerr <<" + Number of defocus groups = "<<ctfdat.size()<<std::endl;
201  std::cerr <<" + Total number of images = "<<tot_nr_imgs<<std::endl;
202  std::cerr <<" + Normalized Wiener constant = "<<tot_nr_imgs*wienerConstant<<std::endl;
203  std::cerr <<" + Minimum Wiener filter value = "<<minwien<<std::endl;
204  std::cerr <<" + Maximum Wiener filter value = "<<maxwien<<std::endl;
205  std::cerr <<" ---------------------------------------------------"<<std::endl;
206 }
207 
208 /* Make deconvolved volume -------------------------------------------------- */
210 {
211  Image<double> V;
212  FileName fnVol, fnCTF;
214  Matrix1D<int> idx(3);
215  Matrix1D<double> freq(3);
216 
217  int ii = 0;
218  double Xdim2=Xdim*Xdim;
219  double Ydim2=Ydim*Ydim;
220  double Zdim2=Zdim*Zdim;
221  for (size_t objId : ctfdat.ids())
222  {
223  ctfdat.getValue(MDL_IMAGE,fnVol,objId);
224  ctfdat.getValue(MDL_CTF_MODEL,fnCTF,objId);
225  V.read(fnVol);
226  FourierTransform(V(),fft);
227  if (ii == 0)
228  fft_out.initZeros(fft);
229  MultidimArray<double>& Vwien1D_ii=Vwien1D[ii];
231  {
232  XX(idx) = j;
233  YY(idx) = i;
234  ZZ(idx) = k;
235  FFT_idx2digfreq(fft, idx, freq);
236  auto ires= (int)round(OVERSAMPLE*sqrt(XX(freq)*XX(freq)*Xdim2+
237  YY(freq)*YY(freq)*Ydim2+
238  ZZ(freq)*ZZ(freq)*Zdim2));
239  A3D_ELEM(fft_out,k,i,j)+=A1D_ELEM(Vwien1D_ii,ires)*A3D_ELEM(fft,k,i,j);
240  }
241  ii++;
242  }
243 
244  // Inverse Fourier Transform
245  InverseFourierTransform(fft_out,V());
246  fnVol=fnRoot+"_deconvolved.vol";
247  V.write(fnVol);
248 
249  // Calculate CTF-affected volumes
250  ii = 0;
251  for (size_t objId : ctfdat.ids())
252  {
253  ctfdat.getValue(MDL_IMAGE,fnVol,objId);
254  ctfdat.getValue(MDL_CTF_MODEL,fnCTF,objId);
255  MultidimArray<double>& Vwien1D_ii=Vwien1D[ii];
257  {
258  XX(idx) = j;
259  YY(idx) = i;
260  ZZ(idx) = k;
261  FFT_idx2digfreq(fft, idx, freq);
262  auto ires= (int)round(OVERSAMPLE*sqrt(XX(freq)*XX(freq)*Xdim2+
263  YY(freq)*YY(freq)*Ydim2+
264  ZZ(freq)*ZZ(freq)*Zdim2));
265  A3D_ELEM(fft,k,i,j)+=A1D_ELEM(Vwien1D_ii,ires)*A3D_ELEM(fft_out,k,i,j);
266  }
267  ii++;
268 
269  fnVol=fnRoot+"_ctffiltered_group";
270  fnVol.compose(fnVol,ii,"vol");
271  InverseFourierTransform(fft,V());
272  V.write(fnVol);
273  }
274 }
275 
276 /* Correct a set of images ------------------------------------------------- */
278 {
279  produceSideInfo();
281  generateVolumes();
282 }
double getDoubleParam(const char *param, int arg=0)
CTFDescription ctf
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
void generateCTF1D(const FileName &fnCTF, size_t nr_steps, MultidimArray< double > &CTF1D)
void resizeNoCopy(const MultidimArray< T1 > &v)
void sqrt(Image< double > &op)
Couldn&#39;t write to file.
Definition: xmipp_error.h:140
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 A1D_ELEM(v, i)
void compose(const String &str, const size_t no, const String &ext="")
Name for the CTF Model (std::string)
FileName fnIn
Metadata with volume, ctf and number of images in that volume.
std::vector< MultidimArray< double > > Vctfs1D
The 3D CTFs and Wiener filters.
double minFreq
Low resolution cutoff to apply Wiener filter.
double wienerConstant
Wiener filter constant.
void InverseFourierTransform(const MultidimArray< std::complex< double > > &in, MultidimArray< double > &out)
Definition: xmipp_fft.cpp:155
virtual IdIteratorProxy< false > ids()
bool isFlipped
Flag for phase flipped images.
void FFT_idx2digfreq(T &v, const Matrix1D< int > &idx, Matrix1D< double > &freq)
Definition: xmipp_fft.h:80
size_t size() const override
#define i
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
void read(const FileName &fn, bool disable_if_not_K=true)
Definition: ctf.cpp:1220
#define A3D_ELEM(V, k, i, j)
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
FileName fnRoot
Rootname for output files.
const char * getParam(const char *param, int arg=0)
#define XX(v)
Definition: matrix1d.h:85
double getValueAt(bool show=false) const
Compute CTF at (U,V). Continuous frequencies.
Definition: ctf.h:1050
#define CTF
size_t firstRowId() const override
double Tm
Sampling rate (A/pixel)
Definition: ctf.h:240
void addExampleLine(const char *example, bool verbatim=true)
FourierFilter ctf
Side Info: CTF.
void precomputeValues(double X, double Y)
Precompute values for a given frequency.
Definition: ctf.h:1002
int verbose
Verbosity level.
void FourierTransform(const MultidimArray< double > &in, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:124
#define j
#define YY(v)
Definition: matrix1d.h:93
bool getValue(MDObject &mdValueOut, size_t id) const override
constexpr int OVERSAMPLE
#define FOR_ALL_ELEMENTS_IN_ARRAY1D(v)
int round(double x)
Definition: ap.cpp:7245
Number of images assigned to the same class as this image.
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)
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
bool enable_CTFnoise
Enable CTFnoise part.
Definition: ctf.h:273
MetaDataVec ctfdat
Side Info: ctfdat.
Name of an image (std::string)
#define ZZ(v)
Definition: matrix1d.h:101
size_t Zdim
Dimensions of the volumes.
void addParamsLine(const String &line)
void getDimensions(size_t &Xdim, size_t &Ydim, size_t &Zdim, size_t &Ndim) const
std::vector< MultidimArray< double > > Vwien1D