Xmipp  v3.23.11-Nereus
polar.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 #include "polar.h"
26 #include "core/transformations.h"
27 
29 {
30  for (size_t i=0; i<transformers.size(); ++i)
31  delete transformers[i];
32 }
33 
35  Polar<std::complex<double> > &out, Polar_fftw_plans &plans,
36  bool conjugated) {
38  out.clear();
39  for (int iring = 0; iring < in.getRingNo(); iring++) {
40 
41  plans.arrays[iring] = in.rings[iring];
42  (plans.transformers[iring])->FourierTransform();
43  (plans.transformers[iring])->getFourierAlias(Fring);
44  if (conjugated) {
45  auto *ptrFring_i = (double*) &DIRECT_A1D_ELEM(Fring,0);
46  ++ptrFring_i;
47  for (size_t i = 0; i < XSIZE(Fring); ++i, ptrFring_i += 2)
48  (*ptrFring_i) *= -1;
49  }
50  out.rings.push_back(Fring);
51  }
52  out.mode = in.mode;
53  out.ring_radius = in.ring_radius;
54 }
55 
56 template<typename T>
57 void Polar<T>::ensureAngleCache(int firstRing, int lastRing) {
58  if ((m_lastFirstRing != firstRing) || (m_lastLastRing != lastRing) || (m_lastMode != mode)) {
59  // update info
60  m_lastFirstRing = firstRing;
61  m_lastLastRing = lastRing;
62  m_lastMode = mode;
63  auto noOfRings = getNoOfRings(firstRing, lastRing);
64  m_lastSinRadius.resize(noOfRings);
65  m_lastCosRadius.resize(noOfRings);
66  double angle = m_lastMode == FULL_CIRCLES ? TWOPI : PI;
67 
68  for (int r = 0; r < noOfRings; ++r) {
69  float radius = r + firstRing;
70  auto noOfSamples = getNoOfSamples(angle, radius);
71  auto &s = m_lastSinRadius.at(r);
72  auto &c = m_lastCosRadius.at(r);
73  s.resize(noOfSamples);
74  c.resize(noOfSamples);
75  float dphi = angle / (float)noOfSamples;
76  for (int i = 0; i < noOfSamples; ++i) {
77  float phi = i * dphi;
78  s.at(i) = sin(phi) * radius;
79  c.at(i) = cos(phi) * radius;
80  }
81  }
82  }
83 }
84 template void Polar<double>::ensureAngleCache(int, int);
85 
86 
87 void inverseFourierTransformRings(Polar<std::complex<double> > & in,
88  Polar<double> &out, Polar_fftw_plans &plans, bool conjugated) {
89  out.clear();
90  for (int iring = 0; iring < in.getRingNo(); iring++) {
91  (plans.transformers[iring])->setFourier(in.rings[iring]);
92  (plans.transformers[iring])->inverseFourierTransform(); // fReal points to plans.arrays[iring]
93  out.rings.push_back(plans.arrays[iring]);
94  }
95  out.mode = in.mode;
96  out.ring_radius = in.ring_radius;
97 }
98 
99 void rotationalCorrelation(const Polar<std::complex<double> > &M1,
100  const Polar<std::complex<double> > &M2, MultidimArray<double> &angles,
102  int nrings = M1.getRingNo();
103  if (nrings != M2.getRingNo()) {
104  char errorMsg[256];
105  sprintf(
106  errorMsg,
107  "rotationalCorrelation: polar structures have unequal number of rings:\
108  nrings %d and M2.getRingNo %d",
109  nrings, M2.getRingNo());
110  std::cerr << errorMsg << std::endl;
112  }
113  // Fsum should already be set with the right size in the local_transformer
114  // (i.e. through a FourierTransform of corr)
116  memset((double*) MULTIDIM_ARRAY(aux.Fsum), 0,
117  2 * MULTIDIM_SIZE(aux.Fsum) * sizeof(double));
118 
119  // Multiply M1 and M2 over all rings and sum
120  // Assume M2 is already complex conjugated!
121  std::complex<double> auxC;
122  for (int iring = 0; iring < nrings; iring++) {
123  double w = (2. * PI * M1.ring_radius[iring]);
124  int imax = M1.getSampleNo(iring);
125  const MultidimArray<std::complex<double> > &M1_iring = M1.rings[iring];
126  const MultidimArray<std::complex<double> > &M2_iring = M2.rings[iring];
127  auto *ptr1 = (double*) MULTIDIM_ARRAY(M1_iring);
128  auto *ptr2 = (double*) MULTIDIM_ARRAY(M2_iring);
129  auto *ptrFsum = (double *) MULTIDIM_ARRAY(aux.Fsum);
130  for (int i = 0; i < imax; i++) {
131  double a = *ptr1++;
132  double b = *ptr1++;
133  double c = *ptr2++;
134  double d = *ptr2++;
135  *(ptrFsum++) += w * (a * c - b * d);
136  *(ptrFsum++) += w * (b * c + a * d);
137  }
138  }
139 
140  // Inverse FFT to get real-space correlations
141  // The local_transformer should already have corr as setReal!!
143 
144  angles.resize(XSIZE(aux.local_transformer.getReal()));
145  double Kaux = 360. / XSIZE(angles);
146  for (size_t i = 0; i < XSIZE(angles); i++)
147  DIRECT_A1D_ELEM(angles,i) = (double) i * Kaux;
148 }
149 
150 // Compute the Polar Fourier transform --------------------------
151 
152 template<bool NORMALIZE>
154  Polar<double> &inAux,
155  Polar<std::complex<double> > &out, bool conjugated, int first_ring,
156  int last_ring, Polar_fftw_plans *&plans, int BsplineOrder) {
157  if (BsplineOrder == 1)
158  inAux.getPolarFromCartesianBSpline(in, first_ring, last_ring, 1);
159  else {
161  produceSplineCoefficients(3, Maux, in);
162  inAux.getPolarFromCartesianBSpline(Maux, first_ring, last_ring,
163  BsplineOrder);
164  }
165  if (NORMALIZE) {
166  double mean;
167  double stddev;
168  inAux.computeAverageAndStddev(mean, stddev);
169  inAux.normalize(mean, stddev);
170  }
171  if (plans == nullptr) {
172  plans = new Polar_fftw_plans();
173  inAux.calculateFftwPlans(*plans);
174  }
175  fourierTransformRings(inAux, out, *plans, conjugated);
176 }
178  Polar<double>&, Polar<std::complex<double> >&, bool, int, int,
179  Polar_fftw_plans*&, int);
180 
181 
182 template<bool NORMALIZE>
184  Polar<std::complex<double> > &out, bool conjugated, int first_ring,
185  int last_ring, Polar_fftw_plans *&plans, int BsplineOrder) {
186  Polar<double> polarIn;
187  polarFourierTransform<NORMALIZE>(in, polarIn, out, conjugated, first_ring, last_ring, plans, BsplineOrder);
188 }
190  Polar<std::complex<double> > &out, bool conjugated, int first_ring,
191  int last_ring, Polar_fftw_plans *&plans, int BsplineOrder);
193  Polar<std::complex<double> > &out, bool conjugated, int first_ring,
194  int last_ring, Polar_fftw_plans *&plans, int BsplineOrder);
195 
196 // Compute the normalized Polar Fourier transform --------------------------
198  Polar<std::complex<double> > &out, bool conjugated,
199  Polar_fftw_plans *&plans) {
200  double mean;
201  double stddev;
202  polarIn.computeAverageAndStddev(mean, stddev);
203  polarIn.normalize(mean, stddev);
204  if (plans == nullptr) {
205  plans = new Polar_fftw_plans();
206  polarIn.calculateFftwPlans(*plans);
207  }
208  fourierTransformRings(polarIn, out, *plans, conjugated);
209 }
210 
211 // Best rotation -----------------------------------------------------------
212 double best_rotation(const Polar<std::complex<double> > &I1,
213  const Polar<std::complex<double> > &I2, RotationalCorrelationAux &aux) {
214  MultidimArray<double> angles;
215  rotationalCorrelation(I1, I2, angles, aux);
216 
217  // Compute the maximum of correlation (inside local_transformer)
218  const MultidimArray<double> &corr = aux.local_transformer.getReal();
219  int imax = 0;
220  double maxval = DIRECT_MULTIDIM_ELEM(corr,0);
221  double* ptr = nullptr;
222  unsigned long int n;
224  if (*ptr > maxval) {
225  maxval = *ptr;
226  imax = n;
227  }
228 
229  // Return the corresponding angle
230  return DIRECT_A1D_ELEM(angles,imax);
231 }
232 
233 // Align rotationally ------------------------------------------------------
235  RotationalCorrelationAux &aux, int splineOrder, int wrap) {
236  I1.setXmippOrigin();
237  I2.setXmippOrigin();
238 
239  Polar_fftw_plans *plans = nullptr;
240  Polar<std::complex<double> > polarFourierI2;
241  Polar<std::complex<double> > polarFourierI1;
242  polarFourierTransform<true>(I1, polarFourierI1, false, XSIZE(I1) / 5,
243  XSIZE(I1) / 2, plans);
244  polarFourierTransform<true>(I2, polarFourierI2, true, XSIZE(I2) / 5,
245  XSIZE(I2) / 2, plans);
246 
247  MultidimArray<double> rotationalCorr;
248  rotationalCorr.resize(2 * polarFourierI2.getSampleNoOuterRing() - 1);
249  aux.local_transformer.setReal(rotationalCorr);
250  double bestRot = best_rotation(polarFourierI1, polarFourierI2, aux);
251 
252  MultidimArray<double> tmp = I2;
253  rotate(splineOrder, I2, tmp, -bestRot, 'Z', wrap);
254 
255 }
256 
257 // Cartesian to polar -----------------------------------------------------
259  MultidimArray<double> &out, double Rmin, double Rmax, double deltaR,
260  float angMin, double angMax, float deltaAng) {
261  auto NAngSteps = (size_t)floor((angMax - angMin) / deltaAng);
262  auto NRSteps = (size_t)floor((Rmax - Rmin) / deltaR);
263  out.initZeros(NAngSteps, NRSteps);
264  for (size_t i = 0; i < NAngSteps; ++i) {
265  float angle = angMin + i * deltaAng;
266  float s = sin(angle);
267  float c = cos(angle);
268  for (size_t j = 0; j < NRSteps; ++j) {
269  float R = Rmin + j * deltaR;
270  A2D_ELEM(out,i,j) = in.interpolatedElement2D(R * c, R * s);
271  }
272  }
273 }
274 
275 // Cartesian to polar -----------------------------------------------------
277  MultidimArray<double> &out, Matrix1D<double> &R, double zoomFactor,
278  double Rmin, double Rmax, int NRSteps, float angMin, double angMax,
279  int NAngSteps) {
280  /* Octave
281  * r=0:64;plot(r,d.^(r/d),r,r,d*((r/d).^2.8));
282  */
283  float deltaAng = (angMax - angMin + 1) / NAngSteps;
284  double deltaR = (Rmax - Rmin + 1) / NRSteps;
285  out.initZeros(NAngSteps, NRSteps);
286  if (VEC_XSIZE(R) == 0) {
287  R.initZeros(NRSteps);
288  double Rrange = Rmax - Rmin;
289  for (int j = 0; j < NRSteps; ++j)
290  VEC_ELEM(R,j) = Rmin
291  + Rrange * pow(j * deltaR / Rrange, zoomFactor);
292  }
293  for (int i = 0; i < NAngSteps; ++i) {
294  float angle = angMin + i * deltaAng;
295  float s = sin(angle);
296  float c = cos(angle);
297  for (int j = 0; j < NRSteps; ++j) {
298  float Rj = VEC_ELEM(R,j);
299  A2D_ELEM(out,i,j) = in.interpolatedElement2D(Rj * c, Rj * s);
300  }
301  }
302 }
303 
304 // Cartesian to cylindrical -----------------------------------------------
306  MultidimArray<double> &out, double Rmin, double Rmax, double deltaR,
307  float angMin, double angMax, float deltaAng, Matrix1D<double> &axis) {
308  auto NAngSteps = (size_t)floor((angMax - angMin) / deltaAng);
309  auto NRSteps = (size_t)floor((Rmax - Rmin) / deltaR);
310  out.initZeros(ZSIZE(in), NAngSteps, NRSteps);
311  STARTINGZ(out) = STARTINGZ(in);
312  STARTINGY(out) = STARTINGX(out) = 0;
313 
314  // Calculate rotation matrix
316  if (XX(axis)!=0.0 || YY(axis)!=0.0)
317  {
318  // 1) Calculate rotation axis v=(0,0,1) x axis
319  Matrix1D<double> v(3);
320  XX(v)=-YY(axis);
321  YY(v)=XX(axis);
322 
323  // 2) Calculate rotation angle (0,0,1).axis=module(axis).cos(ang)
324  double rotAng=acos(ZZ(axis)/axis.module());
325 
326  // 3) Calculate matrix
327  rotation3DMatrix(RAD2DEG(rotAng), v, M, false);
328  }
329 
330  Matrix1D<double> p(3);
331  Matrix1D<double> pc(3);
333  for (size_t i = 0; i < NAngSteps; ++i) {
334  float angle = angMin + i * deltaAng;
335  float s = sin(angle);
336  float c = cos(angle);
337  for (int k = STARTINGZ(in); k <= FINISHINGZ(in); ++k) {
338  ZZ(p)=k;
339  for (size_t j = 0; j < NRSteps; ++j) {
340  float R = Rmin + j * deltaR;
341  YY(p) = R * s;
342  XX(p) = R * c;
343  if (MAT_XSIZE(M)>0)
344  {
345  M3x3_BY_V3x1(pc,M,p);
346  A3D_ELEM(out,k,i,j) = in.interpolatedElement3D(XX(pc),YY(pc),ZZ(pc));
347  }
348  else
349  A3D_ELEM(out,k,i,j) = in.interpolatedElement3D(XX(p),YY(p),ZZ(p));
350  }
351  }
352  }
353 }
354 
355 // Cartesian to cylindrical -----------------------------------------------
357  MultidimArray<double> &out, double Rmin, double Rmax, double deltaR,
358  double deltaRot, double deltaTilt) {
359  auto NRotSteps = (size_t)floor(2*PI / deltaRot);
360  auto NTiltSteps = (size_t)floor(PI / deltaRot);
361  auto NRSteps = (size_t)floor((Rmax - Rmin) / deltaR);
362  out.initZeros(NRSteps, NRotSteps, NTiltSteps);
363  STARTINGZ(out) = STARTINGY(out) = STARTINGX(out) = 0;
364 
365  Matrix1D<double> p(3);
366  for (size_t i = 0; i < NRotSteps; ++i) {
367  float rot = i * deltaRot;
368  float c = cos(rot);
369  float s = sin(rot);
370  for (size_t j = 0; j < NRotSteps; ++j) {
371  float tilt = j * deltaTilt;
372  float stilt = sin(tilt);
373  float ctilt = cos(tilt);
374  float sc = stilt * c;
375  float ss = stilt * s;
376  for (size_t k = 0; k<NRSteps; ++k) {
377  float R = Rmin + k * deltaR;
378  ZZ(p)=R*ctilt;
379  YY(p)=R*ss;
380  XX(p)=R*sc;
381  A3D_ELEM(out,k,i,j) = in.interpolatedElement3D(XX(p),YY(p),ZZ(p));
382  }
383  }
384  }
385 }
#define A2D_ELEM(v, i, j)
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
std::vector< FourierTransformer * > transformers
Definition: polar.h:55
double module() const
Definition: matrix1d.h:983
__host__ __device__ float2 floor(const float2 v)
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
void image_convertCartesianToPolar_ZoomAtCenter(const MultidimArray< double > &in, MultidimArray< double > &out, Matrix1D< double > &R, double zoomFactor, double Rmin, double Rmax, int NRSteps, float angMin, double angMax, int NAngSteps)
Definition: polar.cpp:276
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
doublereal * c
#define MULTIDIM_SIZE(v)
void inverseFourierTransformRings(Polar< std::complex< double > > &in, Polar< double > &out, Polar_fftw_plans &plans, bool conjugated)
Definition: polar.cpp:87
void rotationalCorrelation(const Polar< std::complex< double > > &M1, const Polar< std::complex< double > > &M2, MultidimArray< double > &angles, RotationalCorrelationAux &aux)
Definition: polar.cpp:99
void computeAverageAndStddev(double &avg, double &stddev, int mode=FULL_CIRCLES) const
Definition: polar.h:488
void alignRotationally(MultidimArray< double > &I1, MultidimArray< double > &I2, RotationalCorrelationAux &aux, int splineOrder, int wrap)
Definition: polar.cpp:234
#define MULTIDIM_ARRAY(v)
void normalizedPolarFourierTransform(Polar< double > &polarIn, Polar< std::complex< double > > &out, bool conjugated, Polar_fftw_plans *&plans)
Definition: polar.cpp:197
#define TWOPI
Definition: xmipp_macros.h:111
doublereal * w
template void polarFourierTransform< false >(const MultidimArray< double > &in, Polar< std::complex< double > > &out, bool conjugated, int first_ring, int last_ring, Polar_fftw_plans *&plans, int BsplineOrder)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY_ptr(v, n, ptr)
#define FINISHINGZ(v)
~Polar_fftw_plans()
Destructor.
Definition: polar.cpp:28
#define STARTINGX(v)
#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
#define rotate(a, i, j, k, l)
doublereal * d
constexpr int FULL_CIRCLES
Definition: polar.h:40
void rotation3DMatrix(double ang, char axis, Matrix2D< double > &result, bool homogeneous)
T interpolatedElement2D(double x, double y, T outside_value=(T) 0) const
#define STARTINGY(v)
const MultidimArray< double > & getReal() const
Definition: xmipp_fftw.cpp:118
#define A3D_ELEM(V, k, i, j)
#define DIRECT_A1D_ELEM(v, i)
#define M2
double best_rotation(const Polar< std::complex< double > > &I1, const Polar< std::complex< double > > &I2, RotationalCorrelationAux &aux)
Definition: polar.cpp:212
doublereal * b
#define M1
char axis
#define XX(v)
Definition: matrix1d.h:85
void setReal(MultidimArray< double > &img)
Definition: xmipp_fftw.cpp:129
void getPolarFromCartesianBSpline(const MultidimArray< T > &M1, int first_ring, int last_ring, int BsplineOrder=3, double xoff=0., double yoff=0., double oversample1=1., int mode1=FULL_CIRCLES)
Definition: polar.h:625
MultidimArray< std::complex< double > > Fsum
Definition: polar.h:795
int in
void volume_convertCartesianToSpherical(const MultidimArray< double > &in, MultidimArray< double > &out, double Rmin, double Rmax, double deltaR, double deltaRot, double deltaTilt)
Definition: polar.cpp:356
std::vector< double > ring_radius
Definition: polar.h:74
void produceSplineCoefficients(int SplineDegree, MultidimArray< double > &coeffs, const MultidimArray< T > &V1)
#define XSIZE(v)
#define ZSIZE(v)
#define DIRECT_MULTIDIM_ELEM(v, n)
T interpolatedElement3D(double x, double y, double z, T outside_value=(T) 0) const
void mode
void FourierTransform(const MultidimArray< double > &in, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:124
void initZeros()
Definition: matrix1d.h:592
Polar_fftw_plans()
Empty constructor.
Definition: polar.h:58
int mode
Definition: polar.h:72
#define j
void normalize(double average, double stddev)
Definition: polar.h:536
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
#define YY(v)
Definition: matrix1d.h:93
void fourierTransformRings(Polar< double > &in, Polar< std::complex< double > > &out, Polar_fftw_plans &plans, bool conjugated)
Definition: polar.cpp:34
template void polarFourierTransform< true >(MultidimArray< double > const &, Polar< double > &, Polar< std::complex< double > > &, bool, int, int, Polar_fftw_plans *&, int)
FourierTransformer local_transformer
Definition: polar.h:794
void polarFourierTransform(const MultidimArray< double > &in, Polar< double > &inAux, Polar< std::complex< double > > &out, bool conjugated, int first_ring, int last_ring, Polar_fftw_plans *&plans, int BsplineOrder)
Definition: polar.cpp:153
#define RAD2DEG(r)
Definition: xmipp_macros.h:320
#define MAT_XSIZE(m)
Definition: matrix2d.h:120
void getFourierAlias(T &V)
Definition: xmipp_fftw.h:207
int getRingNo() const
Definition: polar.h:326
std::vector< MultidimArray< T > > rings
Definition: polar.h:75
void image_convertCartesianToPolar(MultidimArray< double > &in, MultidimArray< double > &out, double Rmin, double Rmax, double deltaR, float angMin, double angMax, float deltaAng)
Definition: polar.cpp:258
void initZeros(const MultidimArray< T1 > &op)
#define PI
Definition: tools.h:43
void calculateFftwPlans(Polar_fftw_plans &out)
Definition: polar.h:708
Incorrect value received.
Definition: xmipp_error.h:195
#define STARTINGZ(v)
int * n
#define ZZ(v)
Definition: matrix1d.h:101
doublereal * a
std::vector< MultidimArray< double > > arrays
Definition: polar.h:56
void clear()
Definition: polar.h:295
void volume_convertCartesianToCylindrical(const MultidimArray< double > &in, MultidimArray< double > &out, double Rmin, double Rmax, double deltaR, float angMin, double angMax, float deltaAng, Matrix1D< double > &axis)
Definition: polar.cpp:305
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403