Xmipp  v3.23.11-Nereus
ctf_enhance_psd.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors:
4  *
5  * Carlos Oscar S. Sorzano (coss@cnb.csic.es)
6  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7  *
8  * and
9  *
10  * Slavica Jonic (slavica.jonic@impmc.jussieu.fr)
11  * UPMC, Paris 6
12  *
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27  * 02111-1307 USA
28  *
29  * All comments concerning this program package may be sent to the
30  * e-mail address 'xmipp@cnb.csic.es'
31  ***************************************************************************/
32 
33 #include "ctf_enhance_psd.h"
34 //
35 #include "data/fourier_filter.h"
36 #include "core/histogram.h"
37 #include "core/xmipp_image.h"
38 
39 /* Read parameters --------------------------------------------------------- */
41 {
43  method = getParam("--method");
44  if (method == "filter")
45  {
46  filter_w1 = getDoubleParam("--method", 1);
47  filter_w2 = getDoubleParam("--method", 2);
48  decay_width = getDoubleParam("--method", 3);
49  }
50  else
51  {
52  N0 = getIntParam("--method", 1);
53  NF = getIntParam("--method", 2);
54  }
55  mask_w1 = getDoubleParam("--m1");
56  mask_w2 = getDoubleParam("--m2");
57 }
58 
59 /* Usage ------------------------------------------------------------------- */
61 {
63  defaultComments["-i"].clear();
64  defaultComments["-i"].addComment("Metadata with PSDs or a single PSD");
67  "Enhances the visibility of the Thon rings in a Power Spectrum Density (PSD).");
68  addSeeAlsoLine("ctf_estimate_from_micrograph");
69  addParamsLine("[--method <mth=filter>] : Choose enhancing method");
70  addParamsLine(" where <mth>");
71  addParamsLine(" filter <freq_low=0.05> <freq_high=0.2> <freq_decay=0.02>: Ad hoc filters. The algorithm is fully described at [[http://www.ncbi.nlm.nih.gov/pubmed/16987671][this article]]");
72  addParamsLine(" : The frequency limits define a raised-cosine bandpass filter, frequencies are normalized to 0.5");
73  addParamsLine(" spht <N0=1> <NF=10> : Spiral phase transform normalization.");
74  addParamsLine(" : N0 and NF define the minimum and maximum number of fringes in the CTF");
75  addParamsLine("==+ Output parameters");
76  addParamsLine(" [--dont_center] : By default, the output is centered");
77  addParamsLine(" [--dont_log] : Don't take log10 before working");
78  addParamsLine("==+ Output mask parameters");
79  addParamsLine(" [--m1 <freq_low=0.025>] : Low freq. for frequency mask, max 0.5");
80  addParamsLine(" [--m2 <freq_high=0.3>] : High freq. for frequency mask, max 0.5");
81  addExampleLine("xmipp_ctf_enhance_psd -i myPSD.psd -o myPSD_enhanced.psd");
82 }
83 
84 /* Show -------------------------------------------------------------------- */
86 {
88  std::cout << "Filter w1: " << filter_w1 << std::endl << "Filter w2: "
89  << filter_w2 << std::endl << "Filter decay: " << decay_width
90  << std::endl << "Mask w1: " << mask_w1 << std::endl
91  << "Mask w2: " << mask_w2 << std::endl;
92 }
93 
94 /* Apply ------------------------------------------------------------------- */
95 void ProgCTFEnhancePSD::processImage(const FileName &fnImg, const FileName &fnImgOut,
96  const MDRow &rowIn,MDRow &rowOut)
97 {
98  Image<double> PSD;
99  PSD.read(fnImg);
100  if (ZSIZE(PSD()) != 1)
101  REPORT_ERROR(ERR_MATRIX_DIM,"This program is not intended for volumes");
102  if (method=="filter")
103  applyFilter(PSD());
104  else
105  applySPHT(PSD());
106  PSD.write(fnImgOut);
107 }
108 
109 //#define DEBUG
111 {
112  // Take the logarithm
114  A2D_ELEM(PSD, i, j) = log10(1 + A2D_ELEM(PSD, i, j));
115 
116  // Remove single outliers
117  CenterFFT(PSD, true);
119  medianFilter3x3(PSD, aux);
120  PSD = aux;
121 
122  // Reject other outliers
123  reject_outliers(PSD, 2);
124 
125  // Band pass filter
126  FourierFilter Filter;
127  Filter.FilterShape = RAISED_COSINE;
128  Filter.FilterBand = BANDPASS;
129  Filter.w1 = filter_w1;
130  Filter.w2 = filter_w2;
131  Filter.raised_w = decay_width;
132  PSD.setXmippOrigin();
133  Filter.generateMask(PSD);
134  Filter.applyMaskSpace(PSD);
135  STARTINGX(PSD) = STARTINGY(PSD) = 0;
136  CenterFFT(PSD, false);
137 
138  // Mask the input PSD
139  MultidimArray<int> mask;
140  mask.resize(PSD);
141  Matrix1D<double> freq(2); // Frequencies for Fourier plane
142  double limit0_2 = mask_w1;
143  limit0_2 = limit0_2 * limit0_2;
144  double limitF_2 = mask_w2;
145  limitF_2 = limitF_2 * limitF_2;
146  for (int i = STARTINGY(PSD); i <= FINISHINGY(PSD); ++i)
147  {
148  FFT_IDX2DIGFREQ(i, YSIZE(PSD), YY(freq));
149  double freqy2 = YY(freq) * YY(freq);
150  for (int j = STARTINGX(PSD); j <= FINISHINGX(PSD); ++j)
151  {
152  FFT_IDX2DIGFREQ(j, XSIZE(PSD), XX(freq));
153  double freq2 = XX(freq) * XX(freq) + freqy2;
154  if (freq2 < limit0_2 || freq2 > limitF_2)
155  A2D_ELEM(PSD, i, j) = 0;
156  else
157  A2D_ELEM(mask, i, j) = 1;
158  }
159  }
160 
161  //Compute the mean and the standard deviation under a tighter mask
162  //close to the border and normalize the PSD image
163  MultidimArray<int> tighterMask;
164  tighterMask.resizeNoCopy(PSD);
165  limit0_2 = mask_w2 * 0.9;
166  limit0_2 = limit0_2 * limit0_2;
167  limitF_2 = mask_w2;
168  limitF_2 = limitF_2 * limitF_2;
169  for (int i = STARTINGY(PSD); i <= FINISHINGY(PSD); ++i)
170  {
171  FFT_IDX2DIGFREQ(i, YSIZE(PSD), YY(freq));
172  double freqy2 = YY(freq) * YY(freq);
173  for (int j = STARTINGX(PSD); j <= FINISHINGX(PSD); ++j)
174  {
175  FFT_IDX2DIGFREQ(j, XSIZE(PSD), XX(freq));
176  double freq2 = XX(freq) * XX(freq) + freqy2;
177  A2D_ELEM(tighterMask, i, j) = freq2 > limit0_2 && freq2 < limitF_2;
178  }
179  }
180 
181  double avg, stddev;
182  PSD.computeAvgStdev_within_binary_mask(tighterMask, avg, stddev);
183  double istddev = 1.0 / stddev;
185  if (A2D_ELEM(mask, i, j))
186  A2D_ELEM(PSD, i, j) = (A2D_ELEM(PSD, i, j) - avg) * istddev;
187 
188  // Mask again
189  limit0_2 = mask_w1;
190  limit0_2 = limit0_2 * limit0_2;
191  limitF_2 = mask_w2 * 0.9;
192  limitF_2 = limitF_2 * limitF_2;
193  for (int i = STARTINGY(PSD); i <= FINISHINGY(PSD); ++i)
194  {
195  FFT_IDX2DIGFREQ(i, YSIZE(PSD), YY(freq));
196  double freqy2 = YY(freq) * YY(freq);
197  for (int j = STARTINGX(PSD); j <= FINISHINGX(PSD); ++j)
198  {
199  FFT_IDX2DIGFREQ(j, XSIZE(PSD), XX(freq));
200  double freq2 = XX(freq) * XX(freq) + freqy2;
201  if (freq2 < limit0_2 || freq2 > limitF_2)
202  A2D_ELEM(PSD, i, j) = 0;
203  }
204  }
205 
206  CenterFFT(PSD, true);
207 }
208 
210 {
211  FourierTransformer transformer;
213  transformer.FourierTransform(PSD, PSDfourier, false);
214 
215  transformer.inverseFourierTransform();
216 }
217 #undef DEBUG
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
int N0
Minimum number of fringes.
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
double getDoubleParam(const char *param, int arg=0)
double filter_w2
Bandpass filter high frequency (in Fourier space, max 0.5)
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
#define FINISHINGX(v)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void resizeNoCopy(const MultidimArray< T1 > &v)
String method
Method.
#define BANDPASS
double mask_w1
Lower frequency for the mask (in Fourier space, max 0.5)
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 STARTINGX(v)
void computeAvgStdev_within_binary_mask(const MultidimArray< int > &mask, double &avg, double &stddev) const
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
void addSeeAlsoLine(const char *seeAlso)
double mask_w2
Higher frequency for the mask (in Fourier space, max 0.5)
#define STARTINGY(v)
void CenterFFT(MultidimArray< T > &v, bool forward)
Definition: xmipp_fft.h:291
const char * getParam(const char *param, int arg=0)
#define XX(v)
Definition: matrix1d.h:85
Problem with matrix dimensions.
Definition: xmipp_error.h:150
void reject_outliers(T &v, double percentil_out=0.25)
Definition: histogram.h:605
#define XSIZE(v)
#define RAISED_COSINE
#define ZSIZE(v)
void addExampleLine(const char *example, bool verbatim=true)
double decay_width
Decay width (raised cosine)
void log10(Image< double > &op)
void FourierTransform(T &v, T1 &V, bool getCopy=true)
Definition: xmipp_fftw.h:166
__device__ float FFT_IDX2DIGFREQ(int idx, int size)
#define j
#define YY(v)
Definition: matrix1d.h:93
#define FINISHINGY(v)
void show() const override
void processImage(const FileName &fnImg, const FileName &fnImgOut, const MDRow &rowIn, MDRow &rowOut)
double filter_w1
Bandpass filter low frequency (in Fourier space, max 0.5)
void medianFilter3x3(MultidimArray< T > &m, MultidimArray< T > &out)
Definition: filters.h:1088
void applyFilter(MultidimArray< double > &PSD)
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
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)
int getIntParam(const char *param, int arg=0)
void generateMask(MultidimArray< double > &v)
int NF
Maximum number of fringes.
void addParamsLine(const String &line)
void applyMaskSpace(MultidimArray< double > &v)
void applySPHT(MultidimArray< double > &PSD)
std::map< String, CommentList > defaultComments
Definition: xmipp_program.h:83