Xmipp  v3.23.11-Nereus
psd_estimator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: David Strelak (davidstrelak@gmail.com)
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 "psd_estimator.h"
27 
28 #include "data/fftwT.h"
29 #include "data/dimensions.h"
30 #include "data/rectangle.h"
32 #include "core/histogram.h"
33 
34 template<typename T>
35 std::vector<Rectangle<Point2D<size_t>>> PSDEstimator<T>::getPatchesLocation(
36  const std::pair<size_t, size_t> &borders,
37  const Dimensions &micrograph,
38  const Dimensions &patch,
39  float overlap) {
40  assert(micrograph.x() >= patch.x());
41  assert(micrograph.y() >= patch.y());
42  assert((2 * borders.first + patch.x()) <= micrograph.x());
43  assert((2 * borders.second + patch.y()) <= micrograph.y());
44  assert(overlap >= 0.f);
45  assert(overlap < 1.f);
46 
47  size_t stepX = std::max((1 - overlap) * patch.x(), 1.f);
48  size_t stepY = std::max((1 - overlap) * patch.y(), 1.f);
49 
50  size_t maxX = micrograph.x() - borders.first - patch.x();
51  size_t maxY = micrograph.y() - borders.second - patch.y();
52 
53  auto result = std::vector<Rectangle<Point2D<size_t>>>();
54 
55  size_t y = borders.second;
56  while (y < (maxY + stepY)) {
57  size_t ys = std::min(y, maxY);
58  size_t ye = ys + patch.y() - 1;
59  size_t x = borders.first;
60  while (x < (maxX + stepX)) {
61  size_t xs = std::min(x, maxX);
62  size_t xe = xs + patch.x() - 1;
63  auto tl = Point2D<size_t>(xs, ys);
64  auto br = Point2D<size_t>(xe, ye);
65  result.emplace_back(tl, br);
66  x += stepX;
67  }
68  y += stepY;
69  }
70  return result;
71 }
72 
73 template<typename T>
75  float overlap, const Dimensions &patchDim, MultidimArray<T> &psd,
76  unsigned fftThreads, bool normalize) {
77  using transformer = FFTwT<T>;
78  // get patch positions
79  auto patches = getPatchesLocation({0, 0},
80  Dimensions(micrograph.xdim, micrograph.ydim),
81  patchDim,
82  overlap);
83 
84  auto settings = FFTSettings<T>(patchDim);
85 
86  // prepare data for FT - set proper sizes and allocate aligned dat for faster execution
87  auto *data = reinterpret_cast<T*>(transformer::allocateAligned(settings.sBytesSingle()));
88  auto patchData = MultidimArray<T>(1, 1, patchDim.y(), patchDim.x(), data);
89 
90  MultidimArray<T> smoother;
92  smoother.resetOrigin();
93 
94  auto patchFS = (std::complex<T>*)transformer::allocateAligned(settings.fBytesBatch());
95  auto magnitudes = new T[settings.fElemsBatch()](); // initialize to zero
96 
97  auto hw = CPU(fftThreads);
98  auto plan = transformer::createPlan(hw, settings, true);
99 
100  for (auto &p : patches) {
101  // get patch data
102  window2D(micrograph, patchData,
103  p.tl.y, p.tl.x, p.br.y, p.br.x);
104  // normalize, otherwise we would get 'white cross'
105  patchData.statisticsAdjust((T)0, (T)1);
106  patchData.resetOrigin();
107  // apply edge attenuation
108  patchData *= smoother;
109  // perform FFT
110  transformer::fft(plan, patchData.data, patchFS);
111  // get average of amplitudes
112  for (size_t n = 0; n < settings.fElemsBatch(); ++n) {
113  auto v = patchFS[n]; // / (T)settings.sDim().xyz();
114  auto mag = sqrt((v.real() * v.real()) + (v.imag() * v.imag()));
115  magnitudes[n] += mag;
116  }
117  }
118 
119  // create other half
120  psd.resizeNoCopy(patchData);
121  half2whole(magnitudes, psd.data, settings, [&](bool mirror, T val){return val;});
122 
123  if (normalize) {
124  auto min_val = std::numeric_limits<T>::max();
126  {
127  auto pixval=A2D_ELEM(psd,i,j);
128  if (pixval > 0 && pixval < min_val)
129  min_val = pixval;
130  }
131  min_val = 10 * log10(min_val);
133  {
134  auto pixval=A2D_ELEM(psd,i,j);
135  if (pixval > 0)
136  A2D_ELEM(psd,i,j) = 10 * log10(pixval);
137  else
138  A2D_ELEM(psd,i,j) = min_val;
139  }
140  reject_outliers(psd);
141  }
142 
143  delete[] magnitudes;
144  transformer::release(patchFS);
145  transformer::release(plan);
146  transformer::release(data);
147 
148 }
149 
150 // explicit instantiation
151 template class PSDEstimator<float>;
152 template class PSDEstimator<double>;
void min(Image< double > &op1, const Image< double > &op2)
#define A2D_ELEM(v, i, j)
void resizeNoCopy(const MultidimArray< T1 > &v)
void sqrt(Image< double > &op)
static double * y
static void constructPieceSmoother(const MultidimArray< T > &piece, MultidimArray< T > &pieceSmoother)
doublereal * x
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
CUDA_HD constexpr size_t x() const
Definition: dimensions.h:51
double * f
void reject_outliers(T &v, double percentil_out=0.25)
Definition: histogram.h:605
quaternion_type< T > normalize(quaternion_type< T > q)
Definition: point.cpp:278
void max(Image< double > &op1, const Image< double > &op2)
CUDA_HD constexpr size_t y() const
Definition: dimensions.h:60
void log10(Image< double > &op)
void window2D(const MultidimArray< T > &Ibig, MultidimArray< T > &Ismall, size_t y0, size_t x0, size_t yF, size_t xF)
#define j
static void estimatePSD(const MultidimArray< T > &micrograph, float overlap, const Dimensions &tileDim, MultidimArray< T > &psd, unsigned fftThreads, bool normalize)
Definition: cpu.h:37
static std::vector< Rectangle< Point2D< size_t > > > getPatchesLocation(const std::pair< size_t, size_t > &borders, const Dimensions &micrograph, const Dimensions &patch, float overlap)
int * n
Definition: fftwT.h:60