Xmipp  v3.23.11-Nereus
transformations.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar S. Sorzano (coss@cnb.csic.es)
4  * Sjors H.W. Scheres
5  *
6  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21  * 02111-1307 USA
22  *
23  * All comments concerning this program package may be sent to the
24  * e-mail address 'xmipp@cnb.csic.es'
25  ***************************************************************************/
26 
27 #include "transformations.h"
28 #include "geometry.h"
29 #include "bilib/tboundaryconvention.h" // must be before other bilib includes
30 #include "bilib/tsplinebasis.h"
31 #include "bilib/kerneldiff1.h"
32 #include "bilib/changebasis.h"
33 #include "bilib/pyramidtools.h"
34 #include "xmipp_fft.h"
35 #include "bilib/kernel.h"
36 #include <algorithm>
37 #include "metadata_row_base.h"
38 #include "utils/half.hpp"
39 
40 template<typename T>
41 void produceSplineCoefficients(int SplineDegree,
43  const MultidimArray< T > &V1)
44 {
45 
46  coeffs.initZeros(ZSIZE(V1), YSIZE(V1), XSIZE(V1));
47  STARTINGX(coeffs) = STARTINGX(V1);
48  STARTINGY(coeffs) = STARTINGY(V1);
49  STARTINGZ(coeffs) = STARTINGZ(V1);
50 
51  int Status;
53  typeCast(V1, aux); // This will create a single volume!
54 
56  XSIZE(V1), YSIZE(V1), ZSIZE(V1),
57  CardinalSpline, BasicSpline, SplineDegree,
58  MirrorOffBounds, DBL_EPSILON, &Status);
59  if (Status)
60  REPORT_ERROR(ERR_UNCLASSIFIED, "Error in produceSplineCoefficients...");
61 }
62 
63 template <typename T>
64 void produceImageFromSplineCoefficients(int SplineDegree,
65  MultidimArray< T >& img,
66  const MultidimArray< double > &coeffs)
67 {
69  imgD.initZeros(ZSIZE(coeffs), YSIZE(coeffs), XSIZE(coeffs));
70  STARTINGX(img) = STARTINGX(coeffs);
71  STARTINGY(img) = STARTINGY(coeffs);
72  STARTINGZ(img) = STARTINGZ(coeffs);
73 
74  int Status;
75  MultidimArray< double > aux(coeffs);
76 
78  XSIZE(coeffs), YSIZE(coeffs), ZSIZE(coeffs),
79  BasicSpline, CardinalSpline, SplineDegree,
80  MirrorOnBounds, DBL_EPSILON, &Status);
81  if (Status)
82  REPORT_ERROR(ERR_UNCLASSIFIED, "Error in ImageFromSplineCoefficients...");
83  typeCast(imgD, img);
84 }
85 
86 template<typename T>
87 void reduceBSpline(int SplineDegree,
89  const MultidimArray<T> &V1)
90 {
91  double g[200]; // Coefficients of the reduce filter
92  long ng; // Number of coefficients of the reduce filter
93  double h[200]; // Coefficients of the expansion filter
94  long nh; // Number of coefficients of the expansion filter
95  short IsCentered; // Equal TRUE if the filter is a centered spline
96 
97  // Get the filter
98  const char *splineType="Centered Spline";
99  if (GetPyramidFilter(splineType, SplineDegree,
100  g, &ng, h, &nh, &IsCentered))
101  REPORT_ERROR(ERR_UNCLASSIFIED, "Unable to load the filter coefficients");
102 
104  typeCast(V1, aux);
105  if (V1.getDim() == 2)
106  {
107  if (XSIZE(aux) % 2 != 0 && YSIZE(aux) % 2 != 0)
108  aux.resize(YSIZE(aux) - 1, XSIZE(aux) - 1);
109  else if (YSIZE(aux) % 2 != 0)
110  aux.resize(YSIZE(aux) - 1, XSIZE(aux));
111  else if (XSIZE(aux) % 2 != 0)
112  aux.resize(YSIZE(aux), XSIZE(aux) - 1);
113 
114  V2.initZeros(YSIZE(aux) / 2, XSIZE(aux) / 2);
115  Reduce_2D(MULTIDIM_ARRAY(aux), XSIZE(aux), YSIZE(aux),
116  MULTIDIM_ARRAY(V2), g, ng, IsCentered);
117  }
118  else if (V1.getDim() == 3)
119  {
120  if (XSIZE(aux) % 2 != 0 && YSIZE(aux) % 2 != 0 && ZSIZE(aux) % 2 != 0)
121  aux.resize(ZSIZE(aux - 1), YSIZE(aux) - 1, XSIZE(aux) - 1);
122  else if (XSIZE(aux) % 2 != 0 && YSIZE(aux) % 2 != 0 && ZSIZE(aux) % 2 == 0)
123  aux.resize(ZSIZE(aux), YSIZE(aux) - 1, XSIZE(aux) - 1);
124  else if (XSIZE(aux) % 2 != 0 && YSIZE(aux) % 2 == 0 && ZSIZE(aux) % 2 != 0)
125  aux.resize(ZSIZE(aux) - 1, YSIZE(aux), XSIZE(aux) - 1);
126  else if (XSIZE(aux) % 2 != 0 && YSIZE(aux) % 2 == 0 && ZSIZE(aux) % 2 == 0)
127  aux.resize(ZSIZE(aux), YSIZE(aux), XSIZE(aux) - 1);
128  else if (XSIZE(aux) % 2 == 0 && YSIZE(aux) % 2 != 0 && ZSIZE(aux) % 2 != 0)
129  aux.resize(ZSIZE(aux) - 1, YSIZE(aux) - 1, XSIZE(aux));
130  else if (XSIZE(aux) % 2 == 0 && YSIZE(aux) % 2 != 0 && ZSIZE(aux) % 2 == 0)
131  aux.resize(ZSIZE(aux), YSIZE(aux) - 1, XSIZE(aux));
132  else if (XSIZE(aux) % 2 == 0 && YSIZE(aux) % 2 == 0 && ZSIZE(aux) % 2 != 0)
133  aux.resize(ZSIZE(aux) - 1, YSIZE(aux), XSIZE(aux));
134 
135  V2.initZeros(ZSIZE(aux) / 2, YSIZE(aux) / 2, XSIZE(aux) / 2);
136  Reduce_3D(MULTIDIM_ARRAY(aux), XSIZE(aux), YSIZE(aux), ZSIZE(aux),
137  MULTIDIM_ARRAY(V2), g, ng, IsCentered);
138  }
139  else
140  REPORT_ERROR(ERR_MULTIDIM_DIM,"reduceBSpline ERROR: only valid for 2D or 3D arrays");
141 }
142 
143 template<typename T>
144 void expandBSpline(int SplineDegree,
146  const MultidimArray<T> &V1)
147 {
148  double g[200]; // Coefficients of the reduce filter
149  long ng; // Number of coefficients of the reduce filter
150  double h[200]; // Coefficients of the expansion filter
151  long nh; // Number of coefficients of the expansion filter
152  short IsCentered; // Equal TRUE if the filter is a centered spline, FALSE otherwise */
153 
154  // Get the filter
155  if (GetPyramidFilter("Centered Spline", SplineDegree, g, &ng, h, &nh,
156  &IsCentered))
157  REPORT_ERROR(ERR_UNCLASSIFIED, "Unable to load the filter coefficients");
158 
160  typeCast(V1, aux);
161 
162  if (V1.getDim() == 2)
163  {
164  V2.initZeros(2 * YSIZE(aux), 2 * XSIZE(aux));
165  Expand_2D(MULTIDIM_ARRAY(aux), XSIZE(aux), YSIZE(aux),
166  MULTIDIM_ARRAY(V2), h, nh, IsCentered);
167  }
168  else if (V1.getDim() == 3)
169  {
170  V2.initZeros(2 * ZSIZE(aux), 2 * YSIZE(aux), 2 * XSIZE(aux));
171  Expand_3D(MULTIDIM_ARRAY(aux), XSIZE(aux), YSIZE(aux), ZSIZE(aux),
172  MULTIDIM_ARRAY(V2), h, nh, IsCentered);
173  }
174  else
175  REPORT_ERROR(ERR_MULTIDIM_DIM,"expandBSpline ERROR: only valid for 2D or 3D arrays");
176 }
177 
179  bool only_apply_shifts)
180 {
181  // This has only been implemented for 2D images...
182  double psi = 0, shiftX = 0., shiftY = 0., scale = 1.;
183  bool flip = false;
184 
185  imageGeo.getValue(MDL_ANGLE_PSI, psi);
186  imageGeo.getValue(MDL_SHIFT_X, shiftX);
187  imageGeo.getValue(MDL_SHIFT_Y, shiftY);
188  imageGeo.getValue(MDL_SCALE, scale);
189  imageGeo.getValue(MDL_FLIP, flip);
190 
191  psi = realWRAP(psi, 0., 360.);
192 
193  int dim = A.Xdim() - 1;
194  //This check the case when matrix A is not initialized with correct size
195  if (dim < 2 || dim > 3)
196  {
197  dim = 3;
198  A.resizeNoCopy(dim + 1, dim + 1);
199  }
200 
201  if (only_apply_shifts)
202  A.initIdentity();
203  else if (dim == 2) //2D geometry
204  rotation2DMatrix(psi, A, true);
205  else if (dim == 3)//3D geometry
206  {
207  double rot = 0., tilt = 0., shiftZ = 0.;
208  imageGeo.getValue(MDL_ANGLE_ROT, rot);
209  imageGeo.getValue(MDL_ANGLE_TILT, tilt);
210  imageGeo.getValue(MDL_SHIFT_Z, shiftZ);
211  Euler_angles2matrix(rot, tilt, psi, A, true);
212  dMij(A, 2, dim) = shiftZ;
213  }
214  dMij(A, 0, dim) = shiftX;
215  dMij(A, 1, dim) = shiftY;
216 
217  if (scale != 1.)
218  {
219  if (scale==0.) // Protection against badly formed metadatas
220  scale=1.0;
221  if (dim == 2)
222  {
223  M3x3_BY_CT(A, A, scale);
224  }
225  else if (dim == 3)
226  {
227  M4x4_BY_CT(A, A, scale);
228  }
229  dMij(A, dim, dim) = 1.;
230  }
231 
232  if (flip)
233  {
234  dMij(A, 0, 0) *= -1.;
235  dMij(A, 0, 1) *= -1.;
236  if (dim == 3)
237  dMij(A, 0, 2) *= -1.;
238  }
239 }
240 
241 void string2TransformationMatrix(const String &matrixStr, Matrix2D<double> &matrix, size_t dim)
242 {
243  matrix.resizeNoCopy(dim, dim);
244 
245  String matrixStrCopy(matrixStr);
246  char c;
247 
248  for (size_t i = 0; i < matrixStr.size(); i++)
249  {
250  c = matrixStr[i];
251  if (c == '[' or c == ']' or c == ',')
252  matrixStrCopy[i] = ' ';
253  }
254 
255  size_t n = 4; // EMX matrix are always 4x4
256  std::stringstream ss(matrixStrCopy);
257  size_t d_1 = dim - 1;
258 
259  for (size_t i = 0; i < n; ++i)
260  for (size_t j = 0; j < n; ++j)
261  {
262  //TODO validate that M(dim, dim) is 1
263  //if (i == dim-1 && j == dim-1)
264 
265  ss >> dMij(matrix, i < dim ? i : i-1, j < dim ? j : j-1);
266  }
267  dMij(matrix, d_1, d_1) = 1.;
268 
269 }
270 
271 template<typename T>
273  T &scale, T &shiftX,
274  T &shiftY, T &psi)
275 {
276  // FIXME DS this might not be true, but just to make sure
277  static_assert(std::is_floating_point<T>::value,
278  "Only float and double are allowed as template parameters");
279  //Calculate determinant for getting flip
280  flip = ((dMij(A, 0, 0) * dMij(A, 1, 1) - dMij(A, 0, 1) * dMij(A, 1, 0) ) < 0);
281  int sgn = flip ? -1 : 1;
282  T cosine = sgn * dMij(A, 0, 0);
283  T sine = sgn * dMij(A, 0, 1);
284  T scale2 = cosine * cosine + sine * sine;
285  scale = sqrt(scale2);
286  T invScale = 1 / scale;
287  shiftX = dMij(A, 0, 2) * invScale;
288  shiftY = dMij(A, 1, 2) * invScale;
289  psi = RAD2DEG(atan2(sine, cosine));
290 }
291 template void transformationMatrix2Parameters2D(const Matrix2D<float> &A, bool &flip, float &scale, float &shiftX, float &shiftY, float &psi);
292 template void transformationMatrix2Parameters2D(const Matrix2D<double> &A, bool &flip, double &scale, double &shiftX, double &shiftY, double &psi);
293 
294 
296  double &scale, double &shiftX,
297  double &shiftY, double &shiftZ,
298  double &rot, double &tilt, double &psi)
299 {
300  scale = sqrt(dMij(A,2,0)*dMij(A,2,0) \
301  + dMij(A,2,1)*dMij(A,2,1)\
302  + dMij(A,2,2)*dMij(A,2,2) );
303  double invScale = 1./ scale;
304 
305  Matrix2D<double> tmpMatrix(4,4);
306  M4x4_BY_CT(tmpMatrix, A, invScale);
307 
308  Matrix2D<double> eulerMatrix(3,3);
309 
310  FOR_ALL_ELEMENTS_IN_MATRIX2D(eulerMatrix)
311  dMij(eulerMatrix,i,j) = dMij(tmpMatrix, i, j);
312  //check determinant if -1 then flip = true
313  flip = tmpMatrix.det3x3() < 0;
314  if (flip)
315  {
316  dMij(eulerMatrix, 0, 0) *= -1.;
317  dMij(eulerMatrix, 0, 1) *= -1.;
318  dMij(eulerMatrix, 0, 2) *= -1.;
319  }
320  Euler_matrix2angles(eulerMatrix, rot, tilt, psi);
321 
322  shiftX = dMij(tmpMatrix,0,3);
323  shiftY = dMij(tmpMatrix,1,3);
324  shiftZ = dMij(tmpMatrix,2,3);
325 }
326 
327 #define ADD_IF_EXIST_NONZERO(label, value) if (imageGeo.containsLabel(label) || \
328  !XMIPP_EQUAL_ZERO(value))\
329  imageGeo.setValue(label, value);
331 {
332  bool flip = false;
333  double scale = 1, shiftX = 0, shiftY = 0, psi = 0, shiftZ = 0, rot = 0, tilt = 0;
334 
335  int dim = A.Xdim() - 1;
336 
337  if (dim == 2)
338  transformationMatrix2Parameters2D(A, flip, scale, shiftX, shiftY, psi);
339  else if (dim == 3)
340  {
341  transformationMatrix2Parameters3D(A, flip, scale, shiftX, shiftY, shiftZ,
342  rot, tilt, psi);
346  }
347 
351 
352  if (imageGeo.containsLabel(MDL_SCALE) || !XMIPP_EQUAL_REAL(scale, 1.))
353  imageGeo.setValue(MDL_SCALE, scale);
354 
355  if (imageGeo.containsLabel(MDL_FLIP) || flip)
356  imageGeo.setValue(MDL_FLIP, flip);
357 }
358 
359 /* Rotation 2D ------------------------------------------------------------- */
360 template<typename T>
361 void rotation2DMatrix(T ang, Matrix2D<T> &result, bool homogeneous)
362 {
363  // FIXME DS this might not be true, but just to make sure
364  static_assert(std::is_floating_point<T>::value,
365  "Only float and double are allowed as template parameters");
366 
367  T rad = DEG2RAD(ang);
368  T cosine = cos(rad);
369  T sine = sin(rad);
370 
371  if (homogeneous)
372  {
373  result.resizeNoCopy(3,3); // sizes will be tested inside
374  // now we have 3x3 matrix row wise matrix
375  result.mdata[0] = cosine;
376  result.mdata[1] = sine;
377  result.mdata[2] = 0;
378 
379  result.mdata[3] = -sine;
380  result.mdata[4] = cosine;
381  result.mdata[5] = 0;
382 
383  result.mdata[6] = 0;
384  result.mdata[7] = 0;
385  result.mdata[8] = 1;
386  } else {
387  result.resizeNoCopy(2,2); // sizes will be tested inside
388  // now we have 2x2 matrix row wise matrix
389  result.mdata[0] = cosine;
390  result.mdata[1] = sine;
391 
392  result.mdata[2] = -sine;
393  result.mdata[3] = cosine;
394  }
395 }
396 
397 template void rotation2DMatrix(float ang, Matrix2D<float> &result, bool homogeneous);
398 template void rotation2DMatrix(double ang, Matrix2D<double> &result, bool homogeneous);
399 
400 
401 /* Translation 2D ---------------------------------------------------------- */
402 template void translation2DMatrix(const Matrix1D<float>&, Matrix2D<float>&, bool inverse);
403 template void translation2DMatrix(const Matrix1D<double>&, Matrix2D<double>&, bool inverse);
404 template<typename T>
405 void translation2DMatrix(const Matrix1D<T> &translation,
406  Matrix2D<T> &resMatrix,
407  bool inverse)
408 {
409  if (VEC_XSIZE(translation) != 2)
410  REPORT_ERROR(ERR_MATRIX_SIZE, "Translation2D_matrix: vector is not in R2");
411 
412  resMatrix.initIdentity(3);
413  if (inverse)
414  {
415  dMij(resMatrix,0, 2) = -XX(translation);
416  dMij(resMatrix,1, 2) = -YY(translation);
417  }
418  else
419  {
420  dMij(resMatrix,0, 2) = XX(translation);
421  dMij(resMatrix,1, 2) = YY(translation);
422  }
423 }
424 
425 /* Rotation 3D around the system axes -------------------------------------- */
426 void rotation3DMatrix(double ang, char axis, Matrix2D< double > &result,
427  bool homogeneous)
428 {
429  if (homogeneous)
430  {
431  result.initZeros(4,4);
432  dMij(result,3, 3) = 1;
433  }
434  else
435  result.initZeros(3,3);
436 
437  double cosine, sine;
438  ang = DEG2RAD(ang);
439  cosine = cos(ang);
440  sine = sin(ang);
441 
442  switch (axis)
443  {
444  case 'Z':
445  dMij(result,0, 0) = cosine;
446  dMij(result,0, 1) = sine;
447  dMij(result,1, 0) = -sine;
448  dMij(result,1, 1) = cosine;
449  dMij(result,2, 2) = 1;
450  break;
451  case 'Y':
452  dMij(result,0, 0) = cosine;
453  dMij(result,0, 2) = sine;
454  dMij(result,2, 0) = -sine;
455  dMij(result,2, 2) = cosine;
456  dMij(result,1, 1) = 1;
457  break;
458  case 'X':
459  dMij(result,1, 1) = cosine;
460  dMij(result,1, 2) = sine;
461  dMij(result,2, 1) = -sine;
462  dMij(result,2, 2) = cosine;
463  dMij(result,0, 0) = 1;
464  break;
465  default:
466  REPORT_ERROR(ERR_VALUE_INCORRECT, "rotation3DMatrix: Unknown axis");
467  }
468 }
469 
470 /* Align a vector with Z axis */
472  bool homogeneous)
473 {
474  if (axis.size() != 3)
475  REPORT_ERROR(ERR_MATRIX_SIZE, "alignWithZ: Axis is not in R3");
476  if (homogeneous)
477  {
478  result.initZeros(4,4);
479  dMij(result,3, 3) = 1;
480  }
481  else
482  result.initZeros(3,3);
483  Matrix1D<double> Axis(axis);
484  Axis.selfNormalize();
485 
486  // Compute length of the projection on YZ plane
487  double proj_mod = sqrt(YY(Axis) * YY(Axis) + ZZ(Axis) * ZZ(Axis));
488  if (proj_mod > XMIPP_EQUAL_ACCURACY)
489  { // proj_mod!=0
490  // Build Matrix result, which makes the turning axis coincident with Z
491  dMij(result,0, 0) = proj_mod;
492  dMij(result,0, 1) = -XX(Axis) * YY(Axis) / proj_mod;
493  dMij(result,0, 2) = -XX(Axis) * ZZ(Axis) / proj_mod;
494  dMij(result,1, 0) = 0;
495  dMij(result,1, 1) = ZZ(Axis) / proj_mod;
496  dMij(result,1, 2) = -YY(Axis) / proj_mod;
497  dMij(result,2, 0) = XX(Axis);
498  dMij(result,2, 1) = YY(Axis);
499  dMij(result,2, 2) = ZZ(Axis);
500  }
501  else
502  {
503  // I know that the Axis is the X axis, EITHER POSITIVE OR NEGATIVE!!
504  dMij(result,0, 0) = 0;
505  dMij(result,0, 1) = 0;
506  dMij(result,0, 2) = (XX(Axis) > 0)? -1 : 1;
507  dMij(result,1, 0) = 0;
508  dMij(result,1, 1) = 1;
509  dMij(result,1, 2) = 0;
510  dMij(result,2, 0) = (XX(Axis) > 0)? 1 : -1;
511  dMij(result,2, 1) = 0;
512  dMij(result,2, 2) = 0;
513  }
514 }
515 
516 /* Rotation 3D around any axis -------------------------------------------- */
517 void rotation3DMatrix(double ang, const Matrix1D<double> &axis,
518  Matrix2D<double> &result, bool homogeneous)
519 {
520 #ifdef NEVERDEFINED
521  // Compute a matrix which makes the turning axis coincident with Z
522  // And turn around this axis
523  Matrix2D<double> A, R;
524  alignWithZ(axis, A, homogeneous);
525  rotation3DMatrix(ang, 'Z', R, homogeneous);
526  result = A.transpose() * R * A;
527 #else
528  // http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
529  if (homogeneous)
530  result.initIdentity(4);
531  else
532  result.initIdentity(3);
533  double s,c;
534  //sincos(-DEG2RAD(ang),&s,&c);
535  s = sin(-DEG2RAD(ang));
536  c = cos(-DEG2RAD(ang));
537  double c1=1-c;
538  double x=XX(axis);
539  double y=YY(axis);
540  double z=ZZ(axis);
541  double xy=x*y;
542  double xz=x*z;
543  double yz=y*z;
544  double x2=x*x;
545  double y2=y*y;
546  double z2=z*z;
547  dMij(result,0,0)=c+x2*c1;
548  dMij(result,0,1)=xy*c1-z*s;
549  dMij(result,0,2)=xz*c1+y*s;
550  dMij(result,1,0)=xy*c1+z*s;
551  dMij(result,1,1)=c+y2*c1;
552  dMij(result,1,2)=yz*c1-x*s;
553  dMij(result,2,0)=xz*c1-y*s;
554  dMij(result,2,1)=yz*c1+x*s;
555  dMij(result,2,2)=c+z2*c1;
556 #endif
557 }
558 
559 /* Translation 3D ---------------------------------------------------------- */
560 template void translation3DMatrix(const Matrix1D<float> &translation, Matrix2D<float> &resMatrix, bool inverse);
561 template void translation3DMatrix(const Matrix1D<double> &translation, Matrix2D<double> &resMatrix, bool inverse);
562 template<typename T>
563 void translation3DMatrix(const Matrix1D<T> &translation, Matrix2D<T> &resMatrix, bool inverse)
564 {
565  if (VEC_XSIZE(translation) != 3)
566  REPORT_ERROR(ERR_MATRIX_SIZE, "Translation3D_matrix: vector is not in R3");
567 
568  resMatrix.initIdentity(4);
569  if (inverse)
570  {
571  dMij(resMatrix,0, 3) = -XX(translation);
572  dMij(resMatrix,1, 3) = -YY(translation);
573  dMij(resMatrix,2, 3) = -ZZ(translation);
574  }
575  else
576  {
577  dMij(resMatrix,0, 3) = XX(translation);
578  dMij(resMatrix,1, 3) = YY(translation);
579  dMij(resMatrix,2, 3) = ZZ(translation);
580  }
581 }
582 
583 /* Scale 3D ---------------------------------------------------------------- */
585  bool homogeneous)
586 {
587  if (VEC_XSIZE(sc) != 3)
588  REPORT_ERROR(ERR_MATRIX_SIZE, "Scale3D_matrix: vector is not in R3");
589 
590  if (homogeneous)
591  {
592  result.initZeros(4,4);
593  dMij(result,3, 3) = 1;
594  }
595  else
596  result.initZeros(3,3);
597  dMij(result,0, 0) = XX(sc);
598  dMij(result,1, 1) = YY(sc);
599  dMij(result,2, 2) = ZZ(sc);
600 }
601 
602 #define DELTA_THRESHOLD 10e-7
603 bool getLoopRange(double value, double min, double max, double delta,
604  int loopLimit, int &minIter, int &maxIter)
605 {
606  bool validRange=true;// Return value. TRUE if input value is into range boundaries.
607 
608  // Value is under lower boundary.
609  if (value < min)
610  {
611  // If delta is negative -> moving to lower values and never into valid range.
612  if (delta <= DELTA_THRESHOLD)
613  {
614  validRange = false;
615  }
616  // Compute first and last iterations into valid values.
617  else
618  {
619  minIter = (int) (fabs(min - value) / delta);
620  minIter++;
621  maxIter = (int) (fabs(max - value) / delta);
622  }
623  }
624  // Value is over upper boundary.
625  else if (value >= max)
626  {
627  // If delta is negative -> moving to lower values and never into valid range.
628  if (delta >= -DELTA_THRESHOLD)
629  {
630  validRange = false;
631  }
632  // Compute first and last iterations into valid values.
633  else
634  {
635  minIter = (int) (fabs(value - max) / -delta);
636  minIter++;
637  maxIter = (int) (fabs(value - min) / -delta);
638  }
639  }
640  // First value into valid range.
641  else
642  {
643  // Compute first and last iterations into valid values.
644  if (delta > DELTA_THRESHOLD)
645  {
646  minIter = 0;
647  maxIter = (int) (fabs(max - value) / delta);
648  }
649  // Compute first and last iterations into valid values.
650  else if (delta < -DELTA_THRESHOLD)
651  {
652  minIter = 0;
653  maxIter = (int) (fabs(value - min) / -delta);
654  }
655  // If delta is zero then always in valid range.
656  else
657  {
658  minIter = 0;
659  maxIter = loopLimit;
660  }
661  }
662 
663  return(validRange);
664 }
665 
666 // Special case for complex numbers
667 template<>
668 void applyGeometry(int SplineDegree,
669  MultidimArray< std::complex<double> >& V2,
670  const MultidimArray< std::complex<double> >& V1,
671  const Matrix2D< double > &A, bool inv,
672  bool wrap, std::complex<double> outside,
673  MultidimArray<double> *BcoeffsPtr)
674 {
675 
676  if (SplineDegree > 1)
677  {
678  MultidimArray<double> re, im, rotre, rotim;
680  double outre, outim;
681  re.resize(ZSIZE(V1), YSIZE(V1), XSIZE(V1));
682  im.resize(ZSIZE(V1), YSIZE(V1), XSIZE(V1));
683  outre = outside.real();
684  outim = outside.imag();
685  oneImg=V1;
688  MULTIDIM_SIZE(oneImg));
689  applyGeometry(SplineDegree, rotre, re, A, inv, wrap, outre);
690  applyGeometry(SplineDegree, rotim, im, A, inv, wrap, outim);
691  V2.resize(oneImg);
693  MULTIDIM_ARRAY(V2), MULTIDIM_SIZE(re));
694  }
695  else
696  { //FIXME I do not think you want to recall your self
697  REPORT_ERROR(ERR_NOT_IMPLEMENTED,"I do not think you want to recall your self");
698  // applyGeometry(SplineDegree, V2, V1, A, inv, wrap, outside); // this was causing crash of the sonarcloud analyzer
699  }
700 }
701 
702 // Special case for complex numbers
703 template<>
704 void selfApplyGeometry(int Splinedegree,
705  MultidimArray< std::complex<double> > &V1,
706  const Matrix2D<double> &A, bool inv,
707  bool wrap, std::complex<double> outside)
708 {
710  applyGeometry(Splinedegree, V1, aux, A, inv, wrap, outside);
711 }
712 
713 void applyGeometry(int SplineDegree,
715  const MultidimArrayGeneric &V1,
716  const Matrix2D< double > &A, bool inv,
717  bool wrap, double outside)
718 {
719 #define APPLYGEO(type) applyGeometry(SplineDegree,(*(MultidimArray<type>*)(V2.im)), \
720  (*(MultidimArray<type>*)(V1.im)), A, inv, wrap, (type) outside);
722 #undef APPLYGEO
723 
724 }
725 
726 // Special case for complex arrays
727 void produceSplineCoefficients(int SplineDegree,
728  MultidimArray< double > &coeffs,
729  const MultidimArray< std::complex<double> > &V1)
730 {
731  // TODO Implement
732  REPORT_ERROR(ERR_NOT_IMPLEMENTED,"Spline coefficients of a complex matrix is not implemented.");
733 }
734 
735 
736 void selfScaleToSize(int SplineDegree,
738  int Xdim, int Ydim, int Zdim)
739 {
740 #define SELFSCALETOSIZE(type) selfScaleToSize(SplineDegree,MULTIDIM_ARRAY_TYPE(V1,type), \
741  Xdim,Ydim,Zdim);
743 #undef SELFSCALETOSIZE
744 }
745 
746 void scaleToSize(int SplineDegree,
748  int Xdim, int Ydim, int Zdim)
749 {
750  if (V1.datatype != V2.datatype)
751  REPORT_ERROR(ERR_PARAM_INCORRECT, "scaleToSize: MultidimArrayGeneric requires same datatype");
752 #define SCALETOSIZE(type) scaleToSize(SplineDegree,MULTIDIM_ARRAY_TYPE(V2,type), \
753  MULTIDIM_ARRAY_TYPE(V1,type),Xdim,Ydim,Zdim);
755 #undef SCALETOSIZE
756 }
757 
758 // Special case for complex arrays
759 void scaleToSize(int SplineDegree,
760  MultidimArray< std::complex<double> > &V2,
761  const MultidimArray< std::complex<double> > &V1,
762  int Xdim, int Ydim, int Zdim)
763 {
764  if (SplineDegree > 1)
765  {
766  MultidimArray< double > re, im, aux;
768 
769  re.resize(ZSIZE(V1), YSIZE(V1), XSIZE(V1));
770  im.resize(ZSIZE(V1), YSIZE(V1), XSIZE(V1));
771 
772  oneImg=V1;
775  MULTIDIM_SIZE(oneImg));
776  aux = re;
777  scaleToSize(SplineDegree, re, aux, Ydim, Xdim, Zdim);
778  aux = im;
779  scaleToSize(SplineDegree, im, aux, Ydim, Xdim, Zdim);
781  MULTIDIM_ARRAY(V2), MULTIDIM_SIZE(re));
782  }
783  else
784  scaleToSize(SplineDegree, V2, V1, Xdim, Ydim, Zdim);
785 
786 }
787 
788 // Special case for complex arrays
789 void selfScaleToSize(int SplineDegree,
790  MultidimArray< std::complex<double> > &V1,
791  int Xdim, int Ydim, int Zdim)
792 {
794  scaleToSize(SplineDegree, V1, aux, Xdim, Ydim, Zdim);
795 }
796 
798 void selfPyramidReduce(int SplineDegree,
800  int levels)
801 {
802 #define SELFPYRAMIDREDUCE(type) selfPyramidReduce(SplineDegree, \
803  *((MultidimArray<type>*)(V1.im)), levels);
805 #undef SELFPYRAMIDREDUCE
806 }
807 
809 void selfPyramidExpand(int SplineDegree,
811  int levels)
812 {
813 #define SELFPYRAMIDEXPAND(type) selfPyramidExpand(SplineDegree, \
814  *((MultidimArray<type>*)(V1.im)), levels);
816 #undef SELFPYRAMIDEXPAND
817 }
818 
819 void pyramidExpand(int SplineDegree,
821  const MultidimArrayGeneric &V1,
822  int levels)
823 {
824  if (V1.datatype != V2.datatype)
825  REPORT_ERROR(ERR_PARAM_INCORRECT, "pyramidExpand: MultidimArrayGeneric requires same datatype");
826 #define PYRAMIDEXPAND(type) pyramidExpand(SplineDegree,MULTIDIM_ARRAY_TYPE(V2,type),\
827  MULTIDIM_ARRAY_TYPE(V1,type), levels);
829 #undef PYRAMIDEXPAND
830 }
831 
832 void pyramidReduce(int SplineDegree,
834  const MultidimArrayGeneric &V1,
835  int levels)
836 {
837  if (V1.datatype != V2.datatype)
838  REPORT_ERROR(ERR_PARAM_INCORRECT, "pyramidReduce: MultidimArrayGeneric requires same datatype");
839 #define PYRAMIDREDUCE(type) pyramidReduce(SplineDegree,MULTIDIM_ARRAY_TYPE(V2,type),\
840  MULTIDIM_ARRAY_TYPE(V1,type), levels);
842 #undef PYRAMIDREDUCE
843 }
844 
854  double x, double y, double z,
855  int SplineDegree)
856 {
857  int SplineDegree_1 = SplineDegree - 1;
858  double aux;
859 
860  // Logical to physical
861  z -= STARTINGZ(vol);
862  y -= STARTINGY(vol);
863  x -= STARTINGX(vol);
864 
865  int l1 = CEIL(x - SplineDegree_1);
866  int l2 = l1 + SplineDegree;
867 
868  int m1 = CEIL(y - SplineDegree_1);
869  int m2 = m1 + SplineDegree;
870 
871  int n1 = CEIL(z - SplineDegree_1);
872  int n2 = n1 + SplineDegree;
873 
874  double zyxsum = 0.0;
875  int Zdim=(int)ZSIZE(vol);
876  int Ydim=(int)YSIZE(vol);
877  int Xdim=(int)XSIZE(vol);
878  for (int n = n1; n <= n2; n++)
879  {
880  int equivalent_n=n;
881  if (n<0)
882  equivalent_n=-n-1;
883  else if (n>=Zdim)
884  equivalent_n=2*Zdim-n-1;
885  double yxsum = 0.0;
886  for (int m = m1; m <= m2; m++)
887  {
888  int equivalent_m=m;
889  if (m<0)
890  equivalent_m=-m-1;
891  else if (m>=Ydim)
892  equivalent_m=2*Ydim-m-1;
893  double xsum = 0.0;
894  for (int l = l1; l <= l2; l++)
895  {
896  double xminusl = x - (double) l;
897  int equivalent_l=l;
898  if (l<0)
899  equivalent_l=-l-1;
900  else if (l>=Xdim)
901  equivalent_l=2*Xdim-l-1;
902  double Coeff = (double) DIRECT_A3D_ELEM(vol, equivalent_n,
903  equivalent_m,
904  equivalent_l );
905  switch (SplineDegree)
906  {
907  case 2:
908  xsum += Coeff * Bspline02(xminusl);
909  break;
910  case 3:
911  BSPLINE03DIFF1(aux,xminusl);
912  xsum += Coeff * aux;
913  break;
914  case 4:
915  xsum += Coeff * Bspline04(xminusl);
916  break;
917  case 5:
918  xsum += Coeff * Bspline05(xminusl);
919  break;
920  case 6:
921  xsum += Coeff * Bspline06(xminusl);
922  break;
923  case 7:
924  xsum += Coeff * Bspline07(xminusl);
925  break;
926  case 8:
927  xsum += Coeff * Bspline08(xminusl);
928  break;
929  case 9:
930  xsum += Coeff * Bspline09(xminusl);
931  break;
932  }
933  }
934 
935  double yminusm = y - (double) m;
936  switch (SplineDegree)
937  {
938  case 2:
939  yxsum += xsum * Bspline02(yminusm);
940  break;
941  case 3:
942  BSPLINE03(aux,yminusm);
943  yxsum += xsum * aux;
944  break;
945  case 4:
946  yxsum += xsum * Bspline04(yminusm);
947  break;
948  case 5:
949  yxsum += xsum * Bspline05(yminusm);
950  break;
951  case 6:
952  yxsum += xsum * Bspline06(yminusm);
953  break;
954  case 7:
955  yxsum += xsum * Bspline07(yminusm);
956  break;
957  case 8:
958  yxsum += xsum * Bspline08(yminusm);
959  break;
960  case 9:
961  yxsum += xsum * Bspline09(yminusm);
962  break;
963  }
964  }
965 
966  double zminusn = z - (double) n;
967  switch (SplineDegree)
968  {
969  case 2:
970  zyxsum += yxsum * Bspline02(zminusn);
971  break;
972  case 3:
973  BSPLINE03(aux,zminusn);
974  zyxsum += yxsum * aux;
975  break;
976  case 4:
977  zyxsum += yxsum * Bspline04(zminusn);
978  break;
979  case 5:
980  zyxsum += yxsum * Bspline05(zminusn);
981  break;
982  case 6:
983  zyxsum += yxsum * Bspline06(zminusn);
984  break;
985  case 7:
986  zyxsum += yxsum * Bspline07(zminusn);
987  break;
988  case 8:
989  zyxsum += yxsum * Bspline08(zminusn);
990  break;
991  case 9:
992  zyxsum += yxsum * Bspline09(zminusn);
993  break;
994  }
995  }
996 
997  return zyxsum;
998 }
999 
1009  double x, double y, double z,
1010  int SplineDegree)
1011 {
1012  int SplineDegree_1 = SplineDegree - 1;
1013  double aux;
1014 
1015  // Logical to physical
1016  z -= STARTINGZ(vol);
1017  y -= STARTINGY(vol);
1018  x -= STARTINGX(vol);
1019 
1020  int l1 = CEIL(x - SplineDegree_1);
1021  int l2 = l1 + SplineDegree;
1022 
1023  int m1 = CEIL(y - SplineDegree_1);
1024  int m2 = m1 + SplineDegree;
1025 
1026  int n1 = CEIL(z - SplineDegree_1);
1027  int n2 = n1 + SplineDegree;
1028 
1029  double zyxsum = 0.0;
1030  int Zdim=(int)ZSIZE(vol);
1031  int Ydim=(int)YSIZE(vol);
1032  int Xdim=(int)XSIZE(vol);
1033  for (int n = n1; n <= n2; n++)
1034  {
1035  int equivalent_n=n;
1036  if (n<0)
1037  equivalent_n=-n-1;
1038  else if (n>=Zdim)
1039  equivalent_n=2*Zdim-n-1;
1040  double yxsum = 0.0;
1041  for (int m = m1; m <= m2; m++)
1042  {
1043  int equivalent_m=m;
1044  if (m<0)
1045  equivalent_m=-m-1;
1046  else if (m>=Ydim)
1047  equivalent_m=2*Ydim-m-1;
1048  double xsum = 0.0;
1049  for (int l = l1; l <= l2; l++)
1050  {
1051  double xminusl = x - (double) l;
1052  int equivalent_l=l;
1053  if (l<0)
1054  equivalent_l=-l-1;
1055  else if (l>=Xdim)
1056  equivalent_l=2*Xdim-l-1;
1057  double Coeff = (double) DIRECT_A3D_ELEM(vol, equivalent_n,
1058  equivalent_m,
1059  equivalent_l );
1060  double aux;
1061  switch (SplineDegree)
1062  {
1063  case 2:
1064  xsum += Coeff * Bspline02(xminusl);
1065  break;
1066  case 3:
1067  BSPLINE03(aux,xminusl);
1068  xsum += Coeff * aux;
1069  break;
1070  case 4:
1071  xsum += Coeff * Bspline04(xminusl);
1072  break;
1073  case 5:
1074  xsum += Coeff * Bspline05(xminusl);
1075  break;
1076  case 6:
1077  xsum += Coeff * Bspline06(xminusl);
1078  break;
1079  case 7:
1080  xsum += Coeff * Bspline07(xminusl);
1081  break;
1082  case 8:
1083  xsum += Coeff * Bspline08(xminusl);
1084  break;
1085  case 9:
1086  xsum += Coeff * Bspline09(xminusl);
1087  break;
1088  }
1089  }
1090 
1091  double yminusm = y - (double) m;
1092  switch (SplineDegree)
1093  {
1094  case 2:
1095  yxsum += xsum * Bspline02(yminusm);
1096  break;
1097  case 3:
1098  BSPLINE03DIFF1(aux,yminusm);
1099  yxsum += xsum * aux;
1100  break;
1101  case 4:
1102  yxsum += xsum * Bspline04(yminusm);
1103  break;
1104  case 5:
1105  yxsum += xsum * Bspline05(yminusm);
1106  break;
1107  case 6:
1108  yxsum += xsum * Bspline06(yminusm);
1109  break;
1110  case 7:
1111  yxsum += xsum * Bspline07(yminusm);
1112  break;
1113  case 8:
1114  yxsum += xsum * Bspline08(yminusm);
1115  break;
1116  case 9:
1117  yxsum += xsum * Bspline09(yminusm);
1118  break;
1119  }
1120  }
1121 
1122  double zminusn = z - (double) n;
1123  switch (SplineDegree)
1124  {
1125  case 2:
1126  zyxsum += yxsum * Bspline02(zminusn);
1127  break;
1128  case 3:
1129  BSPLINE03(aux,zminusn);
1130  zyxsum += yxsum * aux;
1131  break;
1132  case 4:
1133  zyxsum += yxsum * Bspline04(zminusn);
1134  break;
1135  case 5:
1136  zyxsum += yxsum * Bspline05(zminusn);
1137  break;
1138  case 6:
1139  zyxsum += yxsum * Bspline06(zminusn);
1140  break;
1141  case 7:
1142  zyxsum += yxsum * Bspline07(zminusn);
1143  break;
1144  case 8:
1145  zyxsum += yxsum * Bspline08(zminusn);
1146  break;
1147  case 9:
1148  zyxsum += yxsum * Bspline09(zminusn);
1149  break;
1150  }
1151  }
1152 
1153  return zyxsum;
1154 }
1155 
1165  double x, double y, double z,
1166  int SplineDegree)
1167 {
1168  int SplineDegree_1 = SplineDegree - 1;
1169  double aux;
1170 
1171  // Logical to physical
1172  z -= STARTINGZ(vol);
1173  y -= STARTINGY(vol);
1174  x -= STARTINGX(vol);
1175 
1176  int l1 = CEIL(x - SplineDegree_1);
1177  int l2 = l1 + SplineDegree;
1178 
1179  int m1 = CEIL(y - SplineDegree_1);
1180  int m2 = m1 + SplineDegree;
1181 
1182  int n1 = CEIL(z - SplineDegree_1);
1183  int n2 = n1 + SplineDegree;
1184 
1185  double zyxsum = 0.0;
1186  int Zdim=(int)ZSIZE(vol);
1187  int Ydim=(int)YSIZE(vol);
1188  int Xdim=(int)XSIZE(vol);
1189  for (int n = n1; n <= n2; n++)
1190  {
1191  int equivalent_n=n;
1192  if (n<0)
1193  equivalent_n=-n-1;
1194  else if (n>=Zdim)
1195  equivalent_n=2*Zdim-n-1;
1196  double yxsum = 0.0;
1197  for (int m = m1; m <= m2; m++)
1198  {
1199  int equivalent_m=m;
1200  if (m<0)
1201  equivalent_m=-m-1;
1202  else if (m>=Ydim)
1203  equivalent_m=2*Ydim-m-1;
1204  double xsum = 0.0;
1205  for (int l = l1; l <= l2; l++)
1206  {
1207  double xminusl = x - (double) l;
1208  int equivalent_l=l;
1209  if (l<0)
1210  equivalent_l=-l-1;
1211  else if (l>=Xdim)
1212  equivalent_l=2*Xdim-l-1;
1213  double Coeff = (double) DIRECT_A3D_ELEM(vol, equivalent_n,
1214  equivalent_m,
1215  equivalent_l );
1216  double aux;
1217  switch (SplineDegree)
1218  {
1219  case 2:
1220  xsum += Coeff * Bspline02(xminusl);
1221  break;
1222  case 3:
1223  BSPLINE03(aux,xminusl);
1224  xsum += Coeff * aux;
1225  break;
1226  case 4:
1227  xsum += Coeff * Bspline04(xminusl);
1228  break;
1229  case 5:
1230  xsum += Coeff * Bspline05(xminusl);
1231  break;
1232  case 6:
1233  xsum += Coeff * Bspline06(xminusl);
1234  break;
1235  case 7:
1236  xsum += Coeff * Bspline07(xminusl);
1237  break;
1238  case 8:
1239  xsum += Coeff * Bspline08(xminusl);
1240  break;
1241  case 9:
1242  xsum += Coeff * Bspline09(xminusl);
1243  break;
1244  }
1245  }
1246 
1247  double yminusm = y - (double) m;
1248  switch (SplineDegree)
1249  {
1250  case 2:
1251  yxsum += xsum * Bspline02(yminusm);
1252  break;
1253  case 3:
1254  BSPLINE03(aux,yminusm);
1255  yxsum += xsum * aux;
1256  break;
1257  case 4:
1258  yxsum += xsum * Bspline04(yminusm);
1259  break;
1260  case 5:
1261  yxsum += xsum * Bspline05(yminusm);
1262  break;
1263  case 6:
1264  yxsum += xsum * Bspline06(yminusm);
1265  break;
1266  case 7:
1267  yxsum += xsum * Bspline07(yminusm);
1268  break;
1269  case 8:
1270  yxsum += xsum * Bspline08(yminusm);
1271  break;
1272  case 9:
1273  yxsum += xsum * Bspline09(yminusm);
1274  break;
1275  }
1276  }
1277 
1278  double zminusn = z - (double) n;
1279  switch (SplineDegree)
1280  {
1281  case 2:
1282  zyxsum += yxsum * Bspline02(zminusn);
1283  break;
1284  case 3:
1285  BSPLINE03DIFF1(aux,zminusn);
1286  zyxsum += yxsum * aux;
1287  break;
1288  case 4:
1289  zyxsum += yxsum * Bspline04(zminusn);
1290  break;
1291  case 5:
1292  zyxsum += yxsum * Bspline05(zminusn);
1293  break;
1294  case 6:
1295  zyxsum += yxsum * Bspline06(zminusn);
1296  break;
1297  case 7:
1298  zyxsum += yxsum * Bspline07(zminusn);
1299  break;
1300  case 8:
1301  zyxsum += yxsum * Bspline08(zminusn);
1302  break;
1303  case 9:
1304  zyxsum += yxsum * Bspline09(zminusn);
1305  break;
1306  }
1307  }
1308 
1309  return zyxsum;
1310 }
1311 
1313  MultidimArray<double> &radialImg)
1314 {
1315  Matrix1D<int> center(2);
1316  center.initZeros();
1317  MultidimArray<int> distance, radial_count;
1318  MultidimArray<double> radial_mean;
1319  int dim;
1320  radialAveragePrecomputeDistance(img, center, distance, dim);
1321  fastRadialAverage(img, distance, dim, radial_mean, radial_count);
1322 
1323  radialImg.initZeros(img);
1325  {
1326  int d=DIRECT_MULTIDIM_ELEM(distance,n);
1327  DIRECT_MULTIDIM_ELEM(radialImg,n)=A1D_ELEM(radial_mean,d);
1328  }
1329 }
1330 
1331 
1332 void rotation3DMatrixFromIcoOrientations(const char* icoFrom, const char* icoTo,
1333  Matrix2D<double> &R)
1334 {
1335  std::vector<char> symLabel;
1336  symLabel.push_back((int)icoFrom[1]);
1337  symLabel.push_back((int)icoTo[1]);
1338  Matrix1D<double> xyz(3);
1339  Matrix2D<double> Rfrom, Rto;
1340 
1341  for(int i=0; i<2; i++)
1342  {
1343  switch (symLabel[i])
1344  {
1345  case '1':
1346  xyz = vectorR3(0.0, 90.0, 0.0);
1347  break;
1348  case '2':
1349  xyz = vectorR3(0.0, 0.0, 0.0);
1350  break;
1351  case '3':
1352  xyz = vectorR3(0.0, 31.7175, 0.0);
1353  break;
1354  case '4':
1355  xyz = vectorR3(0.0, -31.7175, 0.0);
1356  break;
1357 /* case '5':
1358  xyz = vectorR3(31.7175, 90.0, 0.0); // not aviable yet
1359  break;
1360  case '6':
1361  xyz = vectorR3(-31.7175, 90.0, 0.0); // not aviable yet
1362  break;*/
1363  default:
1364  REPORT_ERROR(ERR_PARAM_INCORRECT, "Incorrect standard icosahedral orientation");
1365  }
1366  if (i==0)
1367  Euler_angles2matrix(XX(xyz), YY(xyz), ZZ(xyz), Rfrom, true);
1368  else
1369  Euler_angles2matrix(XX(xyz), YY(xyz), ZZ(xyz), Rto, true);
1370  }
1371  R = Rto * Rfrom.transpose();
1372 }
1373 
1374 template<typename T>
1376  Matrix1D< int >& center_of_rot,
1377  MultidimArray< T >& radial_mean,
1378  MultidimArray< int >& radial_count,
1379  bool rounding)
1380 {
1381  Matrix1D< double > idx(3);
1382 
1383  size_t sizemax = std::max({XSIZE(m), YSIZE(m), ZSIZE(m)});
1384  double scalex = double(XSIZE(m)/sizemax);
1385  double scaley = double(YSIZE(m)/sizemax);
1386  double scalez = double(ZSIZE(m)/sizemax);
1387 
1388  // If center_of_rot was written for 2D image
1389  if (center_of_rot.size() < 3)
1390  center_of_rot.resize(3);
1391 
1392  // First determine the maximum distance that one should expect, to set the
1393  // dimension of the radial average vector
1394  MultidimArray< int > distances(8);
1395 
1396  const double z0 = STARTINGZ(m) - ZZ(center_of_rot);
1397  const double y0 = STARTINGY(m) - YY(center_of_rot);
1398  const double x0 = STARTINGX(m) - XX(center_of_rot);
1399 
1400  const double xf = FINISHINGX(m) - XX(center_of_rot);
1401  const double yf = FINISHINGY(m) - YY(center_of_rot);
1402  const double zf = FINISHINGZ(m) - ZZ(center_of_rot);
1403 
1404  distances(0) = (int) floor(sqrt(x0 * x0 + y0 * y0 + z0 * z0));
1405  distances(1) = (int) floor(sqrt(xf * xf + y0 * y0 + z0 * z0));
1406  distances(2) = (int) floor(sqrt(xf * xf + yf * yf + z0 * z0));
1407  distances(3) = (int) floor(sqrt(x0 * x0 + yf * yf + z0 * z0));
1408  distances(4) = (int) floor(sqrt(x0 * x0 + yf * yf + zf * zf));
1409  distances(5) = (int) floor(sqrt(xf * xf + yf * yf + zf * zf));
1410  distances(6) = (int) floor(sqrt(xf * xf + y0 * y0 + zf * zf));
1411  distances(7) = (int) floor(sqrt(x0 * x0 + y0 * y0 + zf * zf));
1412 
1413  int dim = CEIL(distances.computeMax()) + 1;
1414  if (rounding)
1415  dim++;
1416 
1417  // Define the vectors
1418  radial_mean.initZeros(dim);
1419  radial_count.initZeros(dim);
1420 
1421  // Perform the radial sum and count pixels that contribute to every
1422  // distance
1424  {
1425  ZZ(idx) = scalez * (k - ZZ(center_of_rot));
1426  YY(idx) = scaley * (i - YY(center_of_rot));
1427  XX(idx) = scalex * (j - XX(center_of_rot));
1428 
1429  // Determine distance to the center
1430  double mod = sqrt(ZZ(idx)*ZZ(idx)+YY(idx)*YY(idx)+XX(idx)*XX(idx));
1431  int distance = rounding ? (int) round(mod) : (int) floor(mod);
1432 
1433  // Sum the value to the pixels with the same distance
1434  DIRECT_MULTIDIM_ELEM(radial_mean,distance) += A3D_ELEM(m, k, i, j);
1435 
1436  // Count the pixel
1437  DIRECT_MULTIDIM_ELEM(radial_count,distance)++;
1438  }
1439 
1440  // Perform the mean
1442  if (DIRECT_MULTIDIM_ELEM(radial_count,i) > 0)
1443  DIRECT_MULTIDIM_ELEM(radial_mean,i) /= DIRECT_MULTIDIM_ELEM(radial_count,i);
1444 }
1445 
1446 
1449 
1462 template void produceSplineCoefficients<half_float::half>(int, MultidimArray<double>&, MultidimArray<half_float::half> const&);
1463 
1464 template void radialAverageNonCubic<double>(const MultidimArray<double>& m, Matrix1D< int >& center_of_rot, MultidimArray<double>& radial_mean, MultidimArray< int >& radial_count, bool rounding);
1465 
#define FOR_ALL_ELEMENTS_IN_MATRIX2D(m)
Definition: matrix2d.h:104
template void produceSplineCoefficients< unsigned int >(int, MultidimArray< double > &, MultidimArray< unsigned int > const &)
void selfApplyGeometry(int Splinedegree, MultidimArray< std::complex< double > > &V1, const Matrix2D< double > &A, bool inv, bool wrap, std::complex< double > outside)
Just to locate unclassified errors.
Definition: xmipp_error.h:192
size_t Xdim() const
Definition: matrix2d.h:575
Rotation angle of an image (double,degrees)
#define DBL_EPSILON
#define YSIZE(v)
void min(Image< double > &op1, const Image< double > &op2)
double Bspline05(double Argument)
Parameter incorrect.
Definition: xmipp_error.h:181
template void produceSplineCoefficients< long >(int, MultidimArray< double > &, MultidimArray< long > const &)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
template void expandBSpline< double >(int, MultidimArray< double > &, const MultidimArray< double > &)
Case or algorithm not implemented yet.
Definition: xmipp_error.h:177
template void translation2DMatrix(const Matrix1D< float > &, Matrix2D< float > &, bool inverse)
#define SCALETOSIZE(type)
__host__ __device__ float2 floor(const float2 v)
void string2TransformationMatrix(const String &matrixStr, Matrix2D< double > &matrix, size_t dim)
void transformationMatrix2Parameters2D(const Matrix2D< T > &A, bool &flip, T &scale, T &shiftX, T &shiftY, T &psi)
#define FINISHINGX(v)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
size_t size() const
Definition: matrix1d.h:508
void geo2TransformationMatrix(const MDRow &imageGeo, Matrix2D< double > &A, bool only_apply_shifts)
void transformationMatrix2Geo(const Matrix2D< double > &A, MDRow &imageGeo)
Problem with matrix size.
Definition: xmipp_error.h:152
template void produceImageFromSplineCoefficients< double >(int, MultidimArray< double > &, MultidimArray< double > const &)
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
int Expand_3D(double *In, long int NxIn, long int NyIn, long int NzIn, double *Out, double h[], long int nh, short FlagCentered)
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
doublereal * c
doublereal * g
#define MULTIDIM_SIZE(v)
void fastRadialAverage(const MultidimArray< T > &m, const MultidimArray< int > &distance, int dim, MultidimArray< T > &radial_mean, MultidimArray< int > &radial_count)
#define DEG2RAD(d)
Definition: xmipp_macros.h:312
double interpolatedElementBSplineDiffZ(MultidimArray< double > &vol, double x, double y, double z, int SplineDegree)
template void produceSplineCoefficients< bool >(int, MultidimArray< double > &, MultidimArray< bool > const &)
#define SELFPYRAMIDREDUCE(type)
void sqrt(Image< double > &op)
void pyramidReduce(int SplineDegree, MultidimArrayGeneric &V2, const MultidimArrayGeneric &V1, int levels)
Tilting angle of an image (double,degrees)
static double * y
Shift for the image in the X axis (double)
#define APPLYGEO(type)
Matrix1D< double > vectorR3(double x, double y, double z)
Definition: matrix1d.cpp:892
void applyGeometry(int SplineDegree, MultidimArray< std::complex< double > > &V2, const MultidimArray< std::complex< double > > &V1, const Matrix2D< double > &A, bool inv, bool wrap, std::complex< double > outside, MultidimArray< double > *BcoeffsPtr)
int Expand_2D(double *In, long int NxIn, long int NyIn, double *Out, double h[], long int nh, short FlagCentered)
#define SELFPYRAMIDEXPAND(type)
template void produceSplineCoefficients< char >(int, MultidimArray< double > &, MultidimArray< char > const &)
#define A1D_ELEM(v, i)
#define MULTIDIM_ARRAY(v)
template void reduceBSpline< double >(int, MultidimArray< double > &, MultidimArray< double > const &)
Special label to be used when gathering MDs in MpiMetadataPrograms.
T * mdata
Definition: matrix2d.h:395
void selfNormalize()
Definition: matrix1d.cpp:723
Matrix2D< T > transpose() const
Definition: matrix2d.cpp:1314
#define SELFSCALETOSIZE(type)
#define z0
#define FINISHINGZ(v)
#define BSPLINE03DIFF1(y, x)
Definition: kerneldiff1.h:60
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY1D(v)
#define STARTINGX(v)
doublereal * x
#define i
void selfScaleToSize(int SplineDegree, MultidimArrayGeneric &V1, int Xdim, int Ydim, int Zdim)
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 selfPyramidExpand(int SplineDegree, MultidimArrayGeneric &V1, int levels)
int Reduce_2D(double *In, long int NxIn, long int NyIn, double *Out, double w[], long int nw, short FlagCentered)
void radialAverageNonCubic(const MultidimArray< T > &m, Matrix1D< int > &center_of_rot, MultidimArray< T > &radial_mean, MultidimArray< int > &radial_count, bool rounding)
doublereal * d
#define XMIPP_EQUAL_REAL(x, y)
Definition: xmipp_macros.h:122
double Bspline04(double Argument)
void rotation3DMatrix(double ang, char axis, Matrix2D< double > &result, bool homogeneous)
void resizeNoCopy(int Ydim, int Xdim)
Definition: matrix2d.h:534
#define STARTINGY(v)
template void produceSplineCoefficients< int >(int, MultidimArray< double > &, MultidimArray< int > const &)
int Reduce_3D(double *In, long int NxIn, long int NyIn, long int NzIn, double *Out, double w[], long int nw, short FlagCentered)
#define A3D_ELEM(V, k, i, j)
#define FOR_ALL_ELEMENTS_IN_ARRAY3D(V)
void expandBSpline(int SplineDegree, MultidimArray< double > &V2, const MultidimArray< T > &V1)
T & getValue(MDLabel label)
void RealImag2Complex(const MultidimArray< double > &real, const MultidimArray< double > &imag, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:114
#define y0
char axis
#define x0
void transformationMatrix2Parameters3D(const Matrix2D< double > &A, bool &flip, double &scale, double &shiftX, double &shiftY, double &shiftZ, double &rot, double &tilt, double &psi)
#define XX(v)
Definition: matrix1d.h:85
template void produceSplineCoefficients< unsigned short >(int, MultidimArray< double > &, MultidimArray< unsigned short > const &)
template void translation3DMatrix(const Matrix1D< float > &translation, Matrix2D< float > &resMatrix, bool inverse)
#define CEIL(x)
Definition: xmipp_macros.h:225
#define dMij(m, i, j)
Definition: matrix2d.h:139
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
Flip the image? (bool)
void produceSplineCoefficients(int SplineDegree, MultidimArray< double > &coeffs, const MultidimArray< T > &V1)
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
#define XSIZE(v)
template void produceSplineCoefficients< short >(int, MultidimArray< double > &, MultidimArray< short > const &)
void max(Image< double > &op1, const Image< double > &op2)
#define FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(v)
void rotation3DMatrixFromIcoOrientations(const char *icoFrom, const char *icoTo, Matrix2D< double > &R)
double Bspline07(double Argument)
void radiallySymmetrize(const MultidimArray< double > &img, MultidimArray< double > &radialImg)
#define ZSIZE(v)
template void produceSplineCoefficients< float >(int, MultidimArray< double > &, MultidimArray< float > const &)
double z
#define DIRECT_MULTIDIM_ELEM(v, n)
double Bspline08(double Argument)
#define M3x3_BY_CT(M2, M1, k)
Definition: matrix2d.h:248
scaling factor for an image or volume (double)
void pyramidExpand(int SplineDegree, MultidimArrayGeneric &V2, const MultidimArrayGeneric &V1, int levels)
void scale3DMatrix(const Matrix1D< double > &sc, Matrix2D< double > &result, bool homogeneous)
#define PYRAMIDREDUCE(type)
template void produceSplineCoefficients< unsigned char >(int, MultidimArray< double > &, MultidimArray< unsigned char > const &)
void initZeros()
Definition: matrix1d.h:592
void mod(const MultidimArray< T > &x, MultidimArray< T > &m, double y)
void radialAveragePrecomputeDistance(const MultidimArray< T > &m, Matrix1D< int > &center_of_rot, MultidimArray< int > &distance, int &dim, const bool &rounding=false)
#define DIRECT_A3D_ELEM(v, k, i, j)
T det3x3() const
determinat of 3x3 matrix
Definition: matrix2d.h:1061
#define PYRAMIDEXPAND(type)
void rotation2DMatrix(T ang, Matrix2D< T > &result, bool homogeneous)
#define j
void scaleToSize(int SplineDegree, MultidimArrayGeneric &V2, const MultidimArrayGeneric &V1, int Xdim, int Ydim, int Zdim)
#define YY(v)
Definition: matrix1d.h:93
int m
TYPE distance(struct Point_T *p, struct Point_T *q)
Definition: point.cpp:28
void setValue(MDLabel label, const T &d, bool addLabel=true)
#define FINISHINGY(v)
double Bspline02(double Argument)
int round(double x)
Definition: ap.cpp:7245
virtual bool containsLabel(MDLabel label) const =0
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
#define RAD2DEG(r)
Definition: xmipp_macros.h:320
double interpolatedElementBSplineDiffX(MultidimArray< double > &vol, double x, double y, double z, int SplineDegree)
std::string String
Definition: xmipp_strings.h:34
double psi(const double x)
void Euler_matrix2angles(const Matrix2D< double > &A, double &alpha, double &beta, double &gamma, bool homogeneous)
Definition: geometry.cpp:839
#define M4x4_BY_CT(M2, M1, k)
Definition: matrix2d.h:263
bool getLoopRange(double value, double min, double max, double delta, int loopLimit, int &minIter, int &maxIter)
Shift for the image in the Z axis (double)
template void produceSplineCoefficients< unsigned long >(int, MultidimArray< double > &, MultidimArray< unsigned long > const &)
void initZeros()
Definition: matrix2d.h:626
#define realWRAP(x, x0, xF)
Definition: xmipp_macros.h:304
#define ADD_IF_EXIST_NONZERO(label, value)
double Bspline09(double Argument)
template void produceSplineCoefficients< double >(int, MultidimArray< double > &, MultidimArray< double > const &)
int ChangeBasisVolume(double *VolumeSource, double *VolumeDestination, long Nx, long Ny, long Nz, enum TSplineBasis FromBasis, enum TSplineBasis ToBasis, long Degree, enum TBoundaryConvention Convention, double Tolerance, int *Status)
void reduceBSpline(int SplineDegree, MultidimArray< double > &V2, const MultidimArray< T > &V1)
void produceImageFromSplineCoefficients(int SplineDegree, MultidimArray< T > &img, const MultidimArray< double > &coeffs)
template void radialAverageNonCubic< double >(const MultidimArray< double > &m, Matrix1D< int > &center_of_rot, MultidimArray< double > &radial_mean, MultidimArray< int > &radial_count, bool rounding)
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
double interpolatedElementBSplineDiffY(MultidimArray< double > &vol, double x, double y, double z, int SplineDegree)
Shift for the image in the Y axis (double)
void initZeros(const MultidimArray< T1 > &op)
void alignWithZ(const Matrix1D< double > &axis, Matrix2D< double > &result, bool homogeneous)
#define DELTA_THRESHOLD
void selfPyramidReduce(int SplineDegree, MultidimArrayGeneric &V1, int levels)
double Bspline06(double Argument)
Incorrect value received.
Definition: xmipp_error.h:195
#define STARTINGZ(v)
int * n
void Complex2RealImag(const MultidimArray< std::complex< double > > &in, MultidimArray< double > &real, MultidimArray< double > &imag)
Definition: xmipp_fft.cpp:103
#define ZZ(v)
Definition: matrix1d.h:101
#define BSPLINE03(y, x)
Definition: kernel.h:83
void initIdentity()
Definition: matrix2d.h:673
T computeMax() const
#define SWITCHDATATYPE(datatype, OP)
double * delta
int GetPyramidFilter(const char *Filter, long int Order, double g[], long int *ng, double h[], long int *nh, short *FlagCentered)