Xmipp  v3.23.11-Nereus
transformations.h
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 #ifndef CORE_TRANSFORMATIONS_H
28 #define CORE_TRANSFORMATIONS_H
29 
30 #include "matrix2d.h"
31 #include "multidim_array.h"
32 #include "multidim_array_generic.h"
34 
35 
36 class MDRow;
37 
40 
41 
46 void geo2TransformationMatrix(const MDRow &imageHeader, Matrix2D<double> &A,
47  bool only_apply_shifts = false);
48 
49 bool getLoopRange( double value, double min, double max, double delta, int loopLimit, int &minIter, int &maxIter);
50 
59 void string2TransformationMatrix(const String &matrixStr, Matrix2D<double> &matrix, size_t dim=4);
60 
62 template<typename T>
63 void transformationMatrix2Parameters2D(const Matrix2D<T> &A, bool &flip,
64  T &scale, T &shiftX, T &shiftY,
65  T &psi);
66 
68 void transformationMatrix2Parameters3D(const Matrix2D<double> &A, bool &flip,
69  double &scale, double &shiftX, double &shiftY,
70  double &shiftZ, double &rot, double &tilt, double &psi);
71 
74 void transformationMatrix2Geo(const Matrix2D<double> &A, MDRow & imageGeo);
75 
86 template<typename T>
87 void rotation2DMatrix(T ang, Matrix2D<T> &m, bool homogeneous=true);
88 
100 template<typename T>
101 void translation2DMatrix(const Matrix1D<T> &translation, Matrix2D<T> &resMatrix, bool inverse=false);
102 
135 void rotation3DMatrix(double ang, char axis, Matrix2D< double > &m,
136  bool homogeneous=true);
137 
150  bool homogeneous=true);
151 
167 void alignWithZ(const Matrix1D< double >& axis, Matrix2D< double > &m, bool homogeneous=true);
168 
180 template<typename T>
181 void translation3DMatrix(const Matrix1D<T> &translation, Matrix2D<T> &resMatrix, bool inverse=false);
182 
190  bool homogeneous=true);
191 
195 void rotation3DMatrixFromIcoOrientations(const char* icoFrom, const char* icoTo, Matrix2D<double> &R);
196 
197 namespace applyGeometryImpl {
198 
199 template<typename T1,typename T, bool wrap>
201  MultidimArray<T>& __restrict__ V2,
202  const MultidimArray<T1>& __restrict__ V1,
203  const Matrix2D<double> &Aref)
204 {
205  // 2D transformation
206  const double Aref00=MAT_ELEM(Aref,0,0);
207  const double Aref10=MAT_ELEM(Aref,1,0);
208 
209  // Find center and limits of image
210  const double cen_y = (int)(YSIZE(V2) / 2);
211  const double cen_x = (int)(XSIZE(V2) / 2);
212  const double cen_yp = (int)(YSIZE(V1) / 2);
213  const double cen_xp = (int)(XSIZE(V1) / 2);
214  const double minxp = -cen_xp;
215  const double minyp = -cen_yp;
216  const double minxpp = minxp-XMIPP_EQUAL_ACCURACY;
217  const double minypp = minyp-XMIPP_EQUAL_ACCURACY;
218  const double maxxp = XSIZE(V1) - cen_xp - 1;
219  const double maxyp = YSIZE(V1) - cen_yp - 1;
220  const double maxxpp = maxxp+XMIPP_EQUAL_ACCURACY;
221  const double maxypp = maxyp+XMIPP_EQUAL_ACCURACY;
222  const int Xdim = XSIZE(V1);
223  const int Ydim = YSIZE(V1);
224 
225  // Now we go from the output image to the input image, ie, for any pixel
226  // in the output image we calculate which are the corresponding ones in
227  // the original image, make an interpolation with them and put this value
228  // at the output pixel
229 
230 #ifdef DEBUG_APPLYGEO
231  std::cout << "A\n" << Aref << std::endl
232  << "(cen_x ,cen_y )=(" << cen_x << "," << cen_y << ")\n"
233  << "(cen_xp,cen_yp)=(" << cen_xp << "," << cen_yp << ")\n"
234  << "(min_xp,min_yp)=(" << minxp << "," << minyp << ")\n"
235  << "(max_xp,max_yp)=(" << maxxp << "," << maxyp << ")\n";
236 #endif
237  // Calculate position of the beginning of the row in the output image
238  const double x = -cen_x;
239  double y = -cen_y;
240  for (size_t i = 0; i < YSIZE(V2); i++)
241  {
242  // Calculate this position in the input image according to the
243  // geometrical transformation
244  // they are related by
245  // coords_output(=x,y) = A * coords_input (=xp,yp)
246  double xp = x * MAT_ELEM(Aref, 0, 0) + y * MAT_ELEM(Aref, 0, 1) + MAT_ELEM(Aref, 0, 2);
247  double yp = x * MAT_ELEM(Aref, 1, 0) + y * MAT_ELEM(Aref, 1, 1) + MAT_ELEM(Aref, 1, 2);
248 
249  // Loop over j is splitted according to wrap (wrap==true is not
250  // vectorizable) and also according to SplineDegree value
251  // (I have not fully analyzed vector dependences for
252  // SplineDegree==3 and else branch)
253  if (wrap)
254  {
255  // This is original implementation
256  for (int j=0; j<XSIZE(V2) ;j++)
257  {
258 #ifdef DEBUG_APPLYGEO
259 
260  std::cout << "Computing (" << i << "," << j << ")\n";
261  std::cout << " (y, x) =(" << y << "," << x << ")\n"
262  << " before wrapping (y',x')=(" << yp << "," << xp << ") "
263  << std::endl;
264 #endif
265  bool x_isOut = XMIPP_RANGE_OUTSIDE_FAST(xp, minxpp, maxxpp);
266  bool y_isOut = XMIPP_RANGE_OUTSIDE_FAST(yp, minypp, maxypp);
267 
268  if (x_isOut)
269  {
270  xp = realWRAP(xp, minxp - 0.5, maxxp + 0.5);
271  }
272 
273  if (y_isOut)
274  {
275  yp = realWRAP(yp, minyp - 0.5, maxyp + 0.5);
276  }
277 
278 #ifdef DEBUG_APPLYGEO
279 
280  std::cout << " after wrapping (y',x')=(" << yp << "," << xp << ") "
281  << std::endl;
282  std::cout << " Interp = " << interp << std::endl;
283  // The following line sounds dangerous...
284  //x++;
285 #endif
286 
287  // Linear interpolation
288  // Calculate the integer position in input image, be
289  // careful that it is not the nearest but the one
290  // at the top left corner of the interpolation square.
291  // Ie, (0.7,0.7) would give (0,0)
292  // Calculate also weights for point m1+1,n1+1
293  double wx = xp + cen_xp;
294  double wy = yp + cen_yp;
295  int m1 = (int) wx;
296  int n1 = (int) wy;
297  int n2 = n1 + 1;
298  int m2 = m1 + 1;
299  wx = wx - m1;
300  wy = wy - n1;
301  double wx_1 = 1 - wx;
302  double wy_1 = 1 - wy;
303 
304  // m2 and n2 can be out by 1 so wrap must be check here
305  if (m2 >= Xdim)
306  m2 = 0;
307  if (n2 >= Ydim)
308  n2 = 0;
309 
310 #ifdef DEBUG_APPLYGEO
311  std::cout << " From (" << n1 << "," << m1 << ") and ("
312  << n2 << "," << m2 << ")\n";
313  std::cout << " wx= " << wx << " wy= " << wy
314  << std::endl;
315 #endif
316 
317  // Perform interpolation
318  double v1 = wy_1 * wx_1 * DIRECT_A2D_ELEM(V1, n1, m1);
319  double v2 = wy_1 * wx * DIRECT_A2D_ELEM(V1, n1, m2);
320  double v3 = wx_1 * wy * DIRECT_A2D_ELEM(V1, n2, m1);
321  double v4 = wx * wy * DIRECT_A2D_ELEM(V1, n2, m2);
322 
323  dAij(V2, i, j) = (T) (v1 + v2 + v3 + v4);
324 #ifdef DEBUG_APPYGEO
325  std::cout << " val= " << dAij(V2, i, j) << std::endl;
326 #endif
327 
328  // Compute new point inside input image
329  xp += Aref00;
330  yp += Aref10;
331  }
332  } /* wrap == true */
333  else
334  {
335 
336  // Inner loop boundaries.
337  int globalMin=0, globalMax=XSIZE(V2);
338 
339  // First and last iteration with valid values for x and y coordinates.
340  int minX, maxX, minY, maxY;
341 
342  // Compute valid iterations in x and y coordinates. If one of them is always out
343  // of boundaries then the inner loop is not executed this iteration.
344  if (!getLoopRange( xp, minxpp, maxxpp, Aref00, XSIZE(V2), minX, maxX) ||
345  !getLoopRange( yp, minypp, maxypp, Aref10, XSIZE(V2), minY, maxY))
346  {
347  y++;
348  continue;
349  }
350  else
351  {
352  // Compute initial iteration.
353  globalMin = minX;
354  if (minX < minY)
355  {
356  globalMin = minY;
357  }
358 
359  // Compute last iteration.
360  globalMax = maxX;
361  if (maxX > maxY)
362  {
363  globalMax = maxY;
364  }
365  globalMax++;
366 
367  // Check max iteration is not higher than image.
368  if ((globalMax >= 0) && ((size_t)globalMax > XSIZE(V2)))
369  {
370  globalMax = XSIZE(V2);
371  }
372 
373  xp += globalMin*Aref00;
374  yp += globalMin*Aref10;
375  }
376 
377 
378  #pragma simd reduction (+:xp,yp)
379  for (int j=globalMin; j<globalMax ;j++)
380  {
381 #ifdef DEBUG_APPLYGEO
382 
383  std::cout << "Computing (" << i << "," << j << ")\n";
384  std::cout << " (y, x) =(" << y << "," << x << ")\n"
385  << " before wrapping (y',x')=(" << yp << "," << xp << ") "
386  << std::endl;
387 
388  std::cout << " after wrapping (y',x')=(" << yp << "," << xp << ") "
389  << std::endl;
390  std::cout << " Interp = " << interp << std::endl;
391  // The following line sounds dangerous...
392  //x++;
393 #endif
394 
395  // Linear interpolation
396 
397  // Calculate the integer position in input image, be careful
398  // that it is not the nearest but the one at the top left corner
399  // of the interpolation square. Ie, (0.7,0.7) would give (0,0)
400  // Calculate also weights for point m1+1,n1+1
401  double wx = xp + cen_xp;
402  int m1 = (int) wx;
403  wx = wx - m1;
404  int m2 = m1 + 1;
405  double wy = yp + cen_yp;
406  int n1 = (int) wy;
407  wy = wy - n1;
408  int n2 = n1 + 1;
409 
410 #ifdef DEBUG_APPLYGEO
411  std::cout << " From (" << n1 << "," << m1 << ") and ("
412  << n2 << "," << m2 << ")\n";
413  std::cout << " wx= " << wx << " wy= " << wy << std::endl;
414 #endif
415 
416  // Perform interpolation
417  // if wx == 0 means that the rightest point is useless for this
418  // interpolation, and even it might not be defined if m1=xdim-1
419  // The same can be said for wy.
420  double wx_1 = (1-wx);
421  double wy_1 = (1-wy);
422  double aux2=wy_1* wx_1 ;
423  double tmp = aux2 * DIRECT_A2D_ELEM(V1, n1, m1);
424 
425  if ((wx != 0) && ((m2 < 0) || ((size_t)m2 < V1.xdim)))
426  tmp += (wy_1-aux2) * DIRECT_A2D_ELEM(V1, n1, m2);
427 
428  if ((wy != 0) && ((n2 < 0) || ((size_t)n2 < V1.ydim)))
429  {
430  aux2=wy * wx_1;
431  tmp += aux2 * DIRECT_A2D_ELEM(V1, n2, m1);
432 
433  if ((wx != 0) && ((m2 < 0) || ((size_t)m2 < V1.xdim)))
434  tmp += (wy-aux2) * DIRECT_A2D_ELEM(V1, n2, m2);
435  }
436 
437  dAij(V2, i, j) = (T) tmp;
438 
439 #ifdef DEBUG_APPYGEO
440  std::cout << " val= " << dAij(V2, i, j) << std::endl;
441 #endif
442 
443  // Compute new point inside input image
444  xp += Aref00;
445  yp += Aref10;
446  }
447  } /* wrap == false */
448 
449  y++;
450  }
451 }
452 
453 
454 } // namespace applyGeometryImpl
455 
456 
530 template<typename T1,typename T, typename T2>
531 void applyGeometry(int SplineDegree,
532  MultidimArray<T>& __restrict__ V2,
533  const MultidimArray<T1>& __restrict__ V1,
534  const Matrix2D< T2 > &At, bool inv,
535  bool wrap, T outside = T(0), MultidimArray<double> *BcoeffsPtr=NULL)
536 {
537 #ifndef RELEASE_MODE
538  if (&V1 == (MultidimArray<T1>*)&V2)
539  REPORT_ERROR(ERR_VALUE_INCORRECT,"ApplyGeometry: Input array cannot be the same as output array");
540 
541  if ( V1.getDim()==2 && ((MAT_XSIZE(At) != 3) || (MAT_YSIZE(At) != 3)) )
542  REPORT_ERROR(ERR_MATRIX_SIZE,"ApplyGeometry: 2D transformation matrix is not 3x3");
543 
544  if ( V1.getDim()==3 && ((MAT_XSIZE(At) != 4) || (MAT_YSIZE(At) != 4)) )
545  REPORT_ERROR(ERR_MATRIX_SIZE,"ApplyGeometry: 3D transformation matrix is not 4x4");
546 #endif
547 
548  if (At.isIdentity() && ( XSIZE(V2) == 0 || SAME_SHAPE3D(V1,V2) ) )
549  {
550  typeCast(V1,V2);
551  return;
552  }
553 
554  if (XSIZE(V1) == 0)
555  {
556  V2.clear();
557  return;
558  }
559 
560  MultidimArray<double> Bcoeffs;
561  MultidimArray<double> *BcoeffsToUse=NULL;
562  Matrix2D<double> A, Ainv;
563  typeCast(At, A);
564  const Matrix2D<double> * Aptr=&A;
565  if (!inv)
566  {
567  Ainv = A.inv();
568  Aptr=&Ainv;
569  }
570  const Matrix2D<double> &Aref=*Aptr;
571 
572  // For scalings the output matrix is resized outside to the final
573  // size instead of being resized inside the routine with the
574  // same size as the input matrix
575  if (XSIZE(V2) == 0)
576  V2.resizeNoCopy(V1);
577 
578  if (outside != 0.)
579  {
580  // Initialize output matrix with value=outside
582  DIRECT_MULTIDIM_ELEM(V2, n) = outside;
583  }
584  else
585  V2.initZeros();
586 
587  if (V1.getDim() == 2)
588  {
589  // this version should be slightly more optimized than the general one bellow
590  if (1 == SplineDegree) {
591  if (wrap) {
592  applyGeometryImpl::applyGeometry2DDegree1<T1, T, true>(V2, V1, Aref);
593  } else {
594  applyGeometryImpl::applyGeometry2DDegree1<T1, T, false>(V2, V1, Aref);
595  }
596  return;
597  }
598 
599  // 2D transformation
600  double Aref00=MAT_ELEM(Aref,0,0);
601  double Aref10=MAT_ELEM(Aref,1,0);
602 
603  // Find center and limits of image
604  double cen_y = (int)(YSIZE(V2) / 2);
605  double cen_x = (int)(XSIZE(V2) / 2);
606  double cen_yp = (int)(YSIZE(V1) / 2);
607  double cen_xp = (int)(XSIZE(V1) / 2);
608  double minxp = -cen_xp;
609  double minyp = -cen_yp;
610  double minxpp = minxp-XMIPP_EQUAL_ACCURACY;
611  double minypp = minyp-XMIPP_EQUAL_ACCURACY;
612  double maxxp = XSIZE(V1) - cen_xp - 1;
613  double maxyp = YSIZE(V1) - cen_yp - 1;
614  double maxxpp = maxxp+XMIPP_EQUAL_ACCURACY;
615  double maxypp = maxyp+XMIPP_EQUAL_ACCURACY;
616  size_t Xdim = XSIZE(V1);
617  size_t Ydim = YSIZE(V1);
618 
619  if (SplineDegree > 1)
620  {
621  // Build the B-spline coefficients
622  if (BcoeffsPtr!=NULL)
623  BcoeffsToUse=BcoeffsPtr;
624  else
625  {
626  produceSplineCoefficients(SplineDegree, Bcoeffs, V1); //Bcoeffs is a single image
627  BcoeffsToUse = &Bcoeffs;
628  }
629  STARTINGX(*BcoeffsToUse) = (int) minxp;
630  STARTINGY(*BcoeffsToUse) = (int) minyp;
631  }
632 
633  // Now we go from the output image to the input image, ie, for any pixel
634  // in the output image we calculate which are the corresponding ones in
635  // the original image, make an interpolation with them and put this value
636  // at the output pixel
637 
638 #ifdef DEBUG_APPLYGEO
639  std::cout << "A\n" << Aref << std::endl
640  << "(cen_x ,cen_y )=(" << cen_x << "," << cen_y << ")\n"
641  << "(cen_xp,cen_yp)=(" << cen_xp << "," << cen_yp << ")\n"
642  << "(min_xp,min_yp)=(" << minxp << "," << minyp << ")\n"
643  << "(max_xp,max_yp)=(" << maxxp << "," << maxyp << ")\n";
644 #endif
645  // Calculate position of the beginning of the row in the output image
646  double x = -cen_x;
647  double y = -cen_y;
648  for (size_t i = 0; i < YSIZE(V2); i++)
649  {
650  // Calculate this position in the input image according to the
651  // geometrical transformation
652  // they are related by
653  // coords_output(=x,y) = A * coords_input (=xp,yp)
654  double xp = x * MAT_ELEM(Aref, 0, 0) + y * MAT_ELEM(Aref, 0, 1) + MAT_ELEM(Aref, 0, 2);
655  double yp = x * MAT_ELEM(Aref, 1, 0) + y * MAT_ELEM(Aref, 1, 1) + MAT_ELEM(Aref, 1, 2);
656 
657  // Inner loop boundaries.
658  int globalMin=0, globalMax=XSIZE(V2);
659 
660  if (!wrap)
661  {
662  // First and last iteration with valid values for x and y coordinates.
663  int minX, maxX, minY, maxY;
664 
665  // Compute valid iterations in x and y coordinates. If one of them is always out
666  // of boundaries then the inner loop is not executed this iteration.
667  if (!getLoopRange( xp, minxpp, maxxpp, Aref00, XSIZE(V2), minX, maxX) ||
668  !getLoopRange( yp, minypp, maxypp, Aref10, XSIZE(V2), minY, maxY))
669  {
670  y++;
671  continue;
672  }
673  else
674  {
675  // Compute initial iteration.
676  globalMin = minX;
677  if (minX < minY)
678  {
679  globalMin = minY;
680  }
681 
682  // Compute last iteration.
683  globalMax = maxX;
684  if (maxX > maxY)
685  {
686  globalMax = maxY;
687  }
688  globalMax++;
689 
690  // Check max iteration is not higher than image.
691  if ((globalMax >= 0) && ((size_t)globalMax > XSIZE(V2)))
692  {
693  globalMax = XSIZE(V2);
694  }
695 
696  xp += globalMin*Aref00;
697  yp += globalMin*Aref10;
698  }
699  }
700 
701  // Loop over j is splitted according to wrap (wrap==true is not
702  // vectorizable) and also according to SplineDegree value
703  // (I have not fully analyzed vector dependences for
704  // SplineDegree==3 and else branch)
705  if (wrap)
706  {
707  // This is original implementation
708  for (int j=globalMin; j<globalMax ;j++)
709  {
710 #ifdef DEBUG_APPLYGEO
711 
712  std::cout << "Computing (" << i << "," << j << ")\n";
713  std::cout << " (y, x) =(" << y << "," << x << ")\n"
714  << " before wrapping (y',x')=(" << yp << "," << xp << ") "
715  << std::endl;
716 #endif
717  bool x_isOut = XMIPP_RANGE_OUTSIDE_FAST(xp, minxpp, maxxpp);
718  bool y_isOut = XMIPP_RANGE_OUTSIDE_FAST(yp, minypp, maxypp);
719 
720  if (x_isOut)
721  {
722  xp = realWRAP(xp, minxp - 0.5, maxxp + 0.5);
723  }
724 
725  if (y_isOut)
726  {
727  yp = realWRAP(yp, minyp - 0.5, maxyp + 0.5);
728  }
729 
730 #ifdef DEBUG_APPLYGEO
731 
732  std::cout << " after wrapping (y',x')=(" << yp << "," << xp << ") "
733  << std::endl;
734  std::cout << " Interp = " << interp << std::endl;
735  // The following line sounds dangerous...
736  //x++;
737 #endif
738 
739  if (SplineDegree==1)
740  {
741  // Linear interpolation
742 
743  // Calculate the integer position in input image, be
744  // careful that it is not the nearest but the one
745  // at the top left corner of the interpolation square.
746  // Ie, (0.7,0.7) would give (0,0)
747  // Calculate also weights for point m1+1,n1+1
748  double wx = xp + cen_xp;
749  int m1 = (int) wx;
750  wx = wx - m1;
751  int m2 = m1 + 1;
752  double wy = yp + cen_yp;
753  int n1 = (int) wy;
754  wy = wy - n1;
755  int n2 = n1 + 1;
756 
757  // m2 and n2 can be out by 1 so wrap must be check here
758  if ((m2 >= 0) && ((size_t)m2 >= Xdim))
759  m2 = 0;
760  if ((n2 >=0) && ((size_t)n2 >= Ydim))
761  n2 = 0;
762 
763 #ifdef DEBUG_APPLYGEO
764  std::cout << " From (" << n1 << "," << m1 << ") and ("
765  << n2 << "," << m2 << ")\n";
766  std::cout << " wx= " << wx << " wy= " << wy
767  << std::endl;
768 #endif
769 
770  // Perform interpolation
771  // if wx == 0 means that the rightest point is useless
772  // for this interpolation, and even it might not be
773  // defined if m1=xdim-1
774  // The same can be said for wy.
775  double wx_1 = (1-wx);
776  double wy_1 = (1-wy);
777  double aux2=wy_1* wx_1 ;
778  double tmp = aux2 * DIRECT_A2D_ELEM(V1, n1, m1);
779 
780  if ((wx != 0) && ((m2 < 0) || ((size_t)m2 < V1.xdim)))
781  tmp += (wy_1-aux2) * DIRECT_A2D_ELEM(V1, n1, m2);
782 
783  if ((wy != 0) && ((n2 < 0) || ((size_t)n2 < V1.ydim)))
784  {
785  aux2=wy * wx_1;
786  tmp += aux2 * DIRECT_A2D_ELEM(V1, n2, m1);
787 
788  if ((wx != 0) && ((m2 < 0) || ((size_t)m2 < V1.xdim)))
789  tmp += (wy-aux2) * DIRECT_A2D_ELEM(V1, n2, m2);
790  }
791 
792  dAij(V2, i, j) = (T) tmp;
793  }
794  else if (SplineDegree==0)
795  {
796  dAij(V2, i, j) = (T) A2D_ELEM(V1,(int)trunc(yp),(int)trunc(xp));
797  }
798  else if (SplineDegree==3)
799  {
800  // B-spline interpolation
801  dAij(V2, i, j) = (T) BcoeffsToUse->interpolatedElementBSpline2D_Degree3(xp, yp);
802  }
803  else
804  {
805  // B-spline interpolation
806  dAij(V2, i, j) = (T) BcoeffsToUse->interpolatedElementBSpline2D(xp, yp, SplineDegree);
807  }
808 #ifdef DEBUG_APPYGEO
809  std::cout << " val= " << dAij(V2, i, j) << std::endl;
810 #endif
811 
812  // Compute new point inside input image
813  xp += Aref00;
814  yp += Aref10;
815  }
816  } /* wrap == true */
817  else
818  {
819  if (SplineDegree==1)
820  {
821  #pragma simd reduction (+:xp,yp)
822  for (int j=globalMin; j<globalMax ;j++)
823  {
824 #ifdef DEBUG_APPLYGEO
825 
826  std::cout << "Computing (" << i << "," << j << ")\n";
827  std::cout << " (y, x) =(" << y << "," << x << ")\n"
828  << " before wrapping (y',x')=(" << yp << "," << xp << ") "
829  << std::endl;
830 
831  std::cout << " after wrapping (y',x')=(" << yp << "," << xp << ") "
832  << std::endl;
833  std::cout << " Interp = " << interp << std::endl;
834  // The following line sounds dangerous...
835  //x++;
836 #endif
837 
838  // Linear interpolation
839 
840  // Calculate the integer position in input image, be careful
841  // that it is not the nearest but the one at the top left corner
842  // of the interpolation square. Ie, (0.7,0.7) would give (0,0)
843  // Calculate also weights for point m1+1,n1+1
844  double wx = xp + cen_xp;
845  int m1 = (int) wx;
846  wx = wx - m1;
847  int m2 = m1 + 1;
848  double wy = yp + cen_yp;
849  int n1 = (int) wy;
850  wy = wy - n1;
851  int n2 = n1 + 1;
852 
853 #ifdef DEBUG_APPLYGEO
854  std::cout << " From (" << n1 << "," << m1 << ") and ("
855  << n2 << "," << m2 << ")\n";
856  std::cout << " wx= " << wx << " wy= " << wy << std::endl;
857 #endif
858 
859  // Perform interpolation
860  // if wx == 0 means that the rightest point is useless for this
861  // interpolation, and even it might not be defined if m1=xdim-1
862  // The same can be said for wy.
863  double wx_1 = (1-wx);
864  double wy_1 = (1-wy);
865  double aux2=wy_1* wx_1 ;
866  double tmp = aux2 * DIRECT_A2D_ELEM(V1, n1, m1);
867 
868  if ((wx != 0) && ((m2 < 0) || ((size_t)m2 < V1.xdim)))
869  tmp += (wy_1-aux2) * DIRECT_A2D_ELEM(V1, n1, m2);
870 
871  if ((wy != 0) && ((n2 < 0) || ((size_t)n2 < V1.ydim)))
872  {
873  aux2=wy * wx_1;
874  tmp += aux2 * DIRECT_A2D_ELEM(V1, n2, m1);
875 
876  if ((wx != 0) && ((m2 < 0) || ((size_t)m2 < V1.xdim)))
877  tmp += (wy-aux2) * DIRECT_A2D_ELEM(V1, n2, m2);
878  }
879 
880  dAij(V2, i, j) = (T) tmp;
881 
882 #ifdef DEBUG_APPYGEO
883  std::cout << " val= " << dAij(V2, i, j) << std::endl;
884 #endif
885 
886  // Compute new point inside input image
887  xp += Aref00;
888  yp += Aref10;
889  }
890  }
891  else if (SplineDegree==0)
892  {
893  #pragma simd reduction (+:xp,yp)
894  for (int j=globalMin; j<globalMax ;j++)
895  {
896 #ifdef DEBUG_APPLYGEO
897 
898  std::cout << "Computing (" << i << "," << j << ")\n";
899  std::cout << " (y, x) =(" << y << "," << x << ")\n"
900  << " before wrapping (y',x')=(" << yp << "," << xp << ") "
901  << std::endl;
902 
903  std::cout << " after wrapping (y',x')=(" << yp << "," << xp << ") "
904  << std::endl;
905  std::cout << " Interp = " << interp << std::endl;
906  // The following line sounds dangerous...
907  //x++;
908 #endif
909  dAij(V2, i, j) = (T) A2D_ELEM(V1,(int)trunc(yp),(int)trunc(xp));
910 
911 #ifdef DEBUG_APPYGEO
912  std::cout << " val= " << dAij(V2, i, j) << std::endl;
913 #endif
914 
915  // Compute new point inside input image
916  xp += Aref00;
917  yp += Aref10;
918  }
919  }
920  else if (SplineDegree==3)
921  {
922  for (int j=globalMin; j<globalMax ;j++)
923  {
924 #ifdef DEBUG_APPLYGEO
925 
926  std::cout << "Computing (" << i << "," << j << ")\n";
927  std::cout << " (y, x) =(" << y << "," << x << ")\n"
928  << " before wrapping (y',x')=(" << yp << "," << xp << ") "
929  << std::endl;
930 
931  std::cout << " after wrapping (y',x')=(" << yp << "," << xp << ") "
932  << std::endl;
933  std::cout << " Interp = " << interp << std::endl;
934  // The following line sounds dangerous...
935  //x++;
936 #endif
937 
938  // B-spline interpolation
939  dAij(V2, i, j) = (T) BcoeffsToUse->interpolatedElementBSpline2D_Degree3(xp, yp);
940 
941 #ifdef DEBUG_APPYGEO
942  std::cout << " val= " << dAij(V2, i, j) << std::endl;
943 #endif
944 
945  // Compute new point inside input image
946  xp += Aref00;
947  yp += Aref10;
948  }
949  }
950  else
951  {
952  for (int j=globalMin; j<globalMax ;j++)
953  {
954 #ifdef DEBUG_APPLYGEO
955 
956  std::cout << "Computing (" << i << "," << j << ")\n";
957  std::cout << " (y, x) =(" << y << "," << x << ")\n"
958  << " before wrapping (y',x')=(" << yp << "," << xp << ") "
959  << std::endl;
960 
961  std::cout << " after wrapping (y',x')=(" << yp << "," << xp << ") "
962  << std::endl;
963  std::cout << " Interp = " << interp << std::endl;
964  // The following line sounds dangerous...
965  //x++;
966 #endif
967 
968  // B-spline interpolation
969  dAij(V2, i, j) = (T) BcoeffsToUse->interpolatedElementBSpline2D(xp, yp, SplineDegree);
970 #ifdef DEBUG_APPYGEO
971  std::cout << " val= " << dAij(V2, i, j) << std::endl;
972 #endif
973 
974  // Compute new point inside input image
975  xp += Aref00;
976  yp += Aref10;
977  }
978  }
979  } /* wrap == false */
980 
981  y++;
982  }
983  }
984  else
985  {
986  // 3D transformation
987  size_t m1, n1, o1, m2, n2, o2;
988  double x, y, z, xp, yp, zp;
989  double minxp, minyp, maxxp, maxyp, minzp, maxzp;
990  double cen_x, cen_y, cen_z, cen_xp, cen_yp, cen_zp;
991  double wx, wy, wz;
992  double Aref00=MAT_ELEM(Aref,0,0);
993  double Aref10=MAT_ELEM(Aref,1,0);
994  double Aref20=MAT_ELEM(Aref,2,0);
995 
996  // Find center of MultidimArray
997  cen_z = (int)(V2.zdim / 2);
998  cen_y = (int)(V2.ydim / 2);
999  cen_x = (int)(V2.xdim / 2);
1000  cen_zp = (int)(V1.zdim / 2);
1001  cen_yp = (int)(V1.ydim / 2);
1002  cen_xp = (int)(V1.xdim / 2);
1003  minxp = -cen_xp;
1004  minyp = -cen_yp;
1005  minzp = -cen_zp;
1006  maxxp = V1.xdim - cen_xp - 1;
1007  maxyp = V1.ydim - cen_yp - 1;
1008  maxzp = V1.zdim - cen_zp - 1;
1009 
1010 #ifdef DEBUG
1011 
1012  std::cout << "Geometry 2 center=("
1013  << cen_z << "," << cen_y << "," << cen_x << ")\n"
1014  << "Geometry 1 center=("
1015  << cen_zp << "," << cen_yp << "," << cen_xp << ")\n"
1016  << " min=("
1017  << minzp << "," << minyp << "," << minxp << ")\n"
1018  << " max=("
1019  << maxzp << "," << maxyp << "," << maxxp << ")\n"
1020  ;
1021 #endif
1022 
1023  if (SplineDegree > 1)
1024  {
1025  // Build the B-spline coefficients
1026  if (BcoeffsPtr!=NULL)
1027  BcoeffsToUse=BcoeffsPtr;
1028  else
1029  {
1030  produceSplineCoefficients(SplineDegree, Bcoeffs, V1); //Bcoeffs is a single image
1031  BcoeffsToUse = &Bcoeffs;
1032  }
1033  STARTINGX(*BcoeffsToUse) = (int) minxp;
1034  STARTINGY(*BcoeffsToUse) = (int) minyp;
1035  STARTINGZ(*BcoeffsToUse) = (int) minzp;
1036  }
1037 
1038  // Now we go from the output MultidimArray to the input MultidimArray, ie, for any
1039  // voxel in the output MultidimArray we calculate which are the corresponding
1040  // ones in the original MultidimArray, make an interpolation with them and put
1041  // this value at the output voxel
1042 
1043  // V2 is not initialised to 0 because all its pixels are rewritten
1044  for (size_t k = 0; k < V2.zdim; k++)
1045  for (size_t i = 0; i < V2.ydim; i++)
1046  {
1047  // Calculate position of the beginning of the row in the output
1048  // MultidimArray
1049  x = -cen_x;
1050  y = i - cen_y;
1051  z = k - cen_z;
1052 
1053  // Calculate this position in the input image according to the
1054  // geometrical transformation they are related by
1055  // coords_output(=x,y) = A * coords_input (=xp,yp)
1056  xp = x * MAT_ELEM(Aref, 0, 0) + y * MAT_ELEM(Aref, 0, 1) + z * MAT_ELEM(Aref, 0, 2) + MAT_ELEM(Aref, 0, 3);
1057  yp = x * MAT_ELEM(Aref, 1, 0) + y * MAT_ELEM(Aref, 1, 1) + z * MAT_ELEM(Aref, 1, 2) + MAT_ELEM(Aref, 1, 3);
1058  zp = x * MAT_ELEM(Aref, 2, 0) + y * MAT_ELEM(Aref, 2, 1) + z * MAT_ELEM(Aref, 2, 2) + MAT_ELEM(Aref, 2, 3);
1059 
1060  for (size_t j = 0; j < V2.xdim; j++)
1061  {
1062  bool interp;
1063  double tmp;
1064 
1065 #ifdef DEBUG
1066 
1067  bool show_debug = false;
1068  if ((i == 0 && j == 0 && k == 0) ||
1069  (i == V2.ydim - 1 && j == V2.xdim - 1 && k == V2.zdim - 1))
1070  show_debug = true;
1071 
1072  if (show_debug)
1073  std::cout << "(x,y,z)-->(xp,yp,zp)= "
1074  << "(" << x << "," << y << "," << z << ") "
1075  << "(" << xp << "," << yp << "," << zp << ")\n";
1076 #endif
1077 
1078  // If the point is outside the volume, apply a periodic
1079  // extension of the volume, what exits by one side enters by
1080  // the other
1081  interp = true;
1082  bool x_isOut = XMIPP_RANGE_OUTSIDE(xp, minxp, maxxp);
1083  bool y_isOut = XMIPP_RANGE_OUTSIDE(yp, minyp, maxyp);
1084  bool z_isOut = XMIPP_RANGE_OUTSIDE(zp, minzp, maxzp);
1085 
1086  if (wrap)
1087  {
1088  if (x_isOut)
1089  xp = realWRAP(xp, minxp - 0.5, maxxp + 0.5);
1090 
1091  if (y_isOut)
1092  yp = realWRAP(yp, minyp - 0.5, maxyp + 0.5);
1093 
1094  if (z_isOut)
1095  zp = realWRAP(zp, minzp - 0.5, maxzp + 0.5);
1096  }
1097  else if (x_isOut || y_isOut || z_isOut)
1098  interp = false;
1099 
1100  if (interp)
1101  {
1102  if (SplineDegree == 1)
1103  {
1104  // Linear interpolation
1105 
1106  // Calculate the integer position in input volume, be
1107  // careful that it is not the nearest but the one at the
1108  // top left corner of the interpolation square. Ie,
1109  // (0.7,0.7) would give (0,0)
1110  // Calculate also weights for point m1+1,n1+1
1111  wx = xp + cen_xp;
1112  m1 = (int) wx;
1113  wx = wx - m1;
1114  m2 = m1 + 1;
1115  wy = yp + cen_yp;
1116  n1 = (int) wy;
1117  wy = wy - n1;
1118  n2 = n1 + 1;
1119  wz = zp + cen_zp;
1120  o1 = (int) wz;
1121  wz = wz - o1;
1122  o2 = o1 + 1;
1123 
1124 #ifdef DEBUG
1125 
1126  if (show_debug)
1127  {
1128  std::cout << "After wrapping(xp,yp,zp)= "
1129  << "(" << xp << "," << yp << "," << zp << ")\n";
1130  std::cout << "(m1,n1,o1)-->(m2,n2,o2)="
1131  << "(" << m1 << "," << n1 << "," << o1 << ") "
1132  << "(" << m2 << "," << n2 << "," << o2 << ")\n";
1133  std::cout << "(wx,wy,wz)="
1134  << "(" << wx << "," << wy << "," << wz << ")\n";
1135  }
1136 #endif
1137 
1138  // Perform interpolation
1139  // if wx == 0 means that the rightest point is useless for
1140  // this interpolation, and even it might not be defined if
1141  // m1=xdim-1
1142  // The same can be said for wy.
1143  double wx_1=1-wx;
1144  double wy_1=1-wy;
1145  double wz_1=1-wz;
1146 
1147  double aux1=wz_1 * wy_1;
1148  double aux2=aux1*wx_1;
1149  tmp = aux2 * DIRECT_A3D_ELEM(V1, o1, n1, m1);
1150 
1151  if (wx != 0 && m2 < V1.xdim)
1152  tmp += (aux1-aux2)* DIRECT_A3D_ELEM(V1, o1, n1, m2);
1153 
1154  if (wy != 0 && n2 < V1.ydim)
1155  {
1156  aux1=wz_1 * wy;
1157  aux2=aux1*wx_1;
1158  tmp += aux2 * DIRECT_A3D_ELEM(V1, o1, n2, m1);
1159  if (wx != 0 && m2 < V1.xdim)
1160  tmp += (aux1-aux2) * DIRECT_A3D_ELEM(V1, o1, n2, m2);
1161  }
1162 
1163  if (wz != 0 && o2 < V1.zdim)
1164  {
1165  aux1=wz * wy_1;
1166  aux2=aux1*wx_1;
1167  tmp += aux2 * DIRECT_A3D_ELEM(V1, o2, n1, m1);
1168  if (wx != 0 && m2 < V1.xdim)
1169  tmp += (aux1-aux2) * DIRECT_A3D_ELEM(V1, o2, n1, m2);
1170  if (wy != 0 && n2 < V1.ydim)
1171  {
1172  aux1=wz * wy;
1173  aux2=aux1*wx_1;
1174  tmp += aux2 * DIRECT_A3D_ELEM(V1, o2, n2, m1);
1175  if (wx != 0 && m2 < V1.xdim)
1176  tmp += (aux1-aux2) * DIRECT_A3D_ELEM(V1, o2, n2, m2);
1177  }
1178  }
1179 
1180 #ifdef DEBUG
1181  if (show_debug)
1182  std::cout <<
1183  "tmp1=" << DIRECT_A3D_ELEM(V1, o1, n1, m1) << " "
1184  << (T)(wz_1 *wy_1 *wx_1 * DIRECT_A3D_ELEM(V1, o1, n1, m1))
1185  << std::endl <<
1186  "tmp2=" << DIRECT_A3D_ELEM(V1, o1, n1, m2) << " "
1187  << (T)(wz_1 *wy_1 * wx * DIRECT_A3D_ELEM(V1, o1, n1, m2))
1188  << std::endl <<
1189  "tmp3=" << DIRECT_A3D_ELEM(V1, o1, n2, m1) << " "
1190  << (T)(wz_1 * wy *wx_1 * DIRECT_A3D_ELEM(V1, o1, n2, m1))
1191  << std::endl <<
1192  "tmp4=" << DIRECT_A3D_ELEM(V1, o1, n2, m2) << " "
1193  << (T)(wz_1 * wy * wx * DIRECT_A3D_ELEM(V1, o2, n1, m1))
1194  << std::endl <<
1195  "tmp6=" << DIRECT_A3D_ELEM(V1, o2, n1, m2) << " "
1196  << (T)(wz * wy_1 * wx * DIRECT_A3D_ELEM(V1, o2, n1, m2))
1197  << std::endl <<
1198  "tmp7=" << DIRECT_A3D_ELEM(V1, o2, n2, m1) << " "
1199  << (T)(wz * wy *wx_1 * DIRECT_A3D_ELEM(V1, o2, n2, m1))
1200  << std::endl <<
1201  "tmp8=" << DIRECT_A3D_ELEM(V1, o2, n2, m2) << " "
1202  << (T)(wz * wy * wx * DIRECT_A3D_ELEM(V1, o2, n2, m2))
1203  << std::endl <<
1204  "tmp= " << tmp << std::endl;
1205 #endif
1206 
1207  dAkij(V2 , k, i, j) = (T)tmp;
1208  }
1209  else if (SplineDegree==0)
1210  {
1211  dAkij(V2, k, i, j)=(T)A3D_ELEM(V1,(int)trunc(zp),(int)trunc(yp),(int)trunc(xp));
1212  }
1213  else
1214  {
1215  // B-spline interpolation
1216  dAkij(V2, k, i, j) =
1217  (T) BcoeffsToUse->interpolatedElementBSpline3D(xp, yp, zp, SplineDegree);
1218  }
1219  }
1220  else
1221  dAkij(V2, k, i, j) = outside;
1222 
1223  // Compute new point inside input image
1224  xp += Aref00;
1225  yp += Aref10;
1226  zp += Aref20;
1227  }
1228  }
1229  }
1230 }
1231 
1232 // Special case for input MultidimArrayGeneric
1233 template<typename T>
1234 void applyGeometry(int SplineDegree,
1235  MultidimArray<T>& V2,
1236  const MultidimArrayGeneric& V1,
1237  const Matrix2D< double > &A, bool inv,
1238  bool wrap, T outside = 0)
1239 {
1240 #define APPLYGEO(type) applyGeometry(SplineDegree,V2, (*(MultidimArray<type>*)(V1.im)), A, inv, wrap, outside);
1242 #undef APPLYGEO
1243 }
1244 
1245 
1246 
1252 template<typename T>
1253 void selfApplyGeometry(int SplineDegree,
1254  MultidimArray<T>& V1,
1255  const Matrix2D< double > &A, bool inv,
1256  bool wrap, T outside = 0)
1257 {
1258  MultidimArray<T> aux = V1;
1259  V1.initZeros();
1260  applyGeometry(SplineDegree, V1, aux, A, inv, wrap, outside);
1261 }
1262 
1263 //Special cases for complex arrays
1264 template<>
1265 void applyGeometry(int SplineDegree,
1266  MultidimArray< std::complex<double> >& V2,
1267  const MultidimArray< std::complex<double> >& V1,
1268  const Matrix2D< double > &A, bool inv,
1269  bool wrap, std::complex<double> outside, MultidimArray<double> *BcoeffsPtr);
1270 
1271 //Special cases for complex arrays
1272 template<>
1273 void selfApplyGeometry(int SplineDegree,
1274  MultidimArray< std::complex<double> >& V1,
1275  const Matrix2D< double > &A, bool inv,
1276  bool wrap, std::complex<double> outside);
1277 
1278 // Special cases for MultidimArrayGeneric
1279 void applyGeometry(int SplineDegree,
1281  const MultidimArrayGeneric &V1,
1282  const Matrix2D< double > &A, bool inv,
1283  bool wrap, double outside);
1284 
1285 
1292 template<typename T>
1293 void produceSplineCoefficients(int SplineDegree,
1294  MultidimArray< double > &coeffs,
1295  const MultidimArray< T > &V1);
1296 
1297 // Special case for complex arrays
1298 void produceSplineCoefficients(int SplineDegree,
1299  MultidimArray< double > &coeffs,
1300  const MultidimArray< std::complex<double> > &V1);
1301 
1306 template <typename T>
1307 void produceImageFromSplineCoefficients(int SplineDegree,
1308  MultidimArray< T >& img,
1309  const MultidimArray< double > &coeffs);
1310 
1322 template<typename T>
1323 void rotate(int SplineDegree,
1324  MultidimArray<T>& V2,
1325  const MultidimArray<T>& V1,
1326  double ang, char axis = 'Z',
1327  bool wrap = xmipp_transformation::DONT_WRAP, T outside = 0)
1328 {
1329  Matrix2D< double > tmp;
1330  if (V1.getDim()==2)
1331  {
1332  rotation2DMatrix(ang,tmp);
1333  }
1334  else if (V1.getDim()==3)
1335  {
1336  rotation3DMatrix(ang, axis, tmp);
1337  }
1338  else
1339  REPORT_ERROR(ERR_MULTIDIM_DIM,"rotate ERROR: rotate only valid for 2D or 3D arrays");
1340 
1341  applyGeometry(SplineDegree, V2, V1, tmp, xmipp_transformation::IS_NOT_INV, wrap, outside);
1342 }
1343 
1349 template<typename T>
1350 void selfRotate(int SplineDegree,
1351  MultidimArray<T>& V1,
1352  double ang, char axis = 'Z',
1353  bool wrap = xmipp_transformation::DONT_WRAP, T outside = 0)
1354 {
1355  MultidimArray<T> aux = V1;
1356  V1.initZeros();
1357  rotate(SplineDegree, V1, aux, ang, axis, wrap, outside);
1358 }
1359 
1371 template<typename T>
1372 void translate(int SplineDegree,
1373  MultidimArray<T> &V2,
1374  const MultidimArray<T> &V1,
1375  const Matrix1D< double >& v,
1376  bool wrap = xmipp_transformation::WRAP, T outside = 0)
1377 {
1378  Matrix2D< double > tmp;
1379  if (V1.getDim()==2)
1380  translation2DMatrix(v, tmp,true);
1381  else if (V1.getDim()==3)
1382  translation3DMatrix(v, tmp,true);
1383  else
1384  REPORT_ERROR(ERR_MULTIDIM_DIM,"translate ERROR: translate only valid for 2D or 3D arrays");
1385  applyGeometry(SplineDegree, V2, V1, tmp, xmipp_transformation::IS_INV, wrap, outside);
1386 }
1387 
1393 template<typename T>
1394 void selfTranslate(int SplineDegree,
1395  MultidimArray<T>& V1,
1396  const Matrix1D< double >& v,
1397  bool wrap = xmipp_transformation::WRAP, T outside = 0)
1398 {
1399  MultidimArray<T> aux = V1;
1400  V1.initZeros();
1401  translate(SplineDegree, V1, aux, v, wrap, outside);
1402 }
1403 
1410 template<typename T>
1411 void translateCenterOfMassToCenter(int SplineDegree,
1412  MultidimArray<T> &V2,
1413  const MultidimArray<T> &V1,
1414  bool wrap = xmipp_transformation::WRAP)
1415 {
1416  V2 = V1;
1417  V2.setXmippOrigin();
1418  Matrix1D< double > center;
1419  V2.centerOfMass(center);
1420  center *= -1;
1421  translate(SplineDegree, V2, V1, center, wrap, 0);
1422 }
1423 
1429 template<typename T>
1431  MultidimArray<T> &V1,
1432  bool wrap = xmipp_transformation::WRAP)
1433 {
1434  MultidimArray<T> aux = V1;
1435  V1.initZeros();
1436  translateCenterOfMassToCenter(SplineDegree, V1, aux, wrap);
1437 }
1438 
1450 template<typename T1, typename T>
1451 void scaleToSize(int SplineDegree,
1452  MultidimArray<T> &V2,
1453  const MultidimArray<T1> &V1,
1454  size_t Xdim, size_t Ydim, size_t Zdim = 1)
1455 {
1456  if (Xdim == XSIZE(V1) && Ydim == YSIZE(V1) && \
1457  (!(V1.getDim()==3) || (Zdim == ZSIZE(V1))) )
1458  {
1459  typeCast(V1,V2);
1460  return;
1461  }
1462 
1463  Matrix2D< double > tmp;
1464  if (V1.getDim()==2)
1465  {
1466  tmp.initIdentity(3);
1467  tmp(0, 0) = (double) Xdim / (double) XSIZE(V1);
1468  tmp(1, 1) = (double) Ydim / (double) YSIZE(V1);
1469  V2.initZeros(1, 1, Ydim, Xdim);
1470  }
1471  else if (V1.getDim()==3)
1472  {
1473  tmp.initIdentity(4);
1474  tmp(0, 0) = (double) Xdim / (double) XSIZE(V1);
1475  tmp(1, 1) = (double) Ydim / (double) YSIZE(V1);
1476  tmp(2, 2) = (double) Zdim / (double) ZSIZE(V1);
1477  V2.initZeros(1, Zdim, Ydim, Xdim);
1478  }
1479  else
1480  REPORT_ERROR(ERR_MULTIDIM_DIM,"scaleToSize ERROR: scaleToSize only valid for 2D or 3D arrays");
1481 
1482  V2.setXmippOrigin();
1483  applyGeometry(SplineDegree, V2, V1, tmp, xmipp_transformation::IS_NOT_INV, xmipp_transformation::WRAP, (T)0);
1484 }
1485 
1496 template<typename T>
1497 inline void scaleToSize(int SplineDegree,
1498  MultidimArray<T> &V2,
1499  const MultidimArrayGeneric &V1,int Xdim, int Ydim, int Zdim = 1)
1500 {
1501 #define SCALETOSIZE(type) scaleToSize(SplineDegree,V2,*((MultidimArray<type>*)(V1.im)),Xdim,Ydim,Zdim);
1503 #undef SCALETOSIZE
1504 }
1505 
1516 template<typename T>
1517 inline void scaleToSize(int SplineDegree,
1519  const MultidimArray<T> &V1,int Xdim, int Ydim, int Zdim = 1)
1520 {
1521 #define SCALETOSIZE(type) scaleToSize(SplineDegree,MULTIDIM_ARRAY_TYPE(V2,type),V1,Xdim,Ydim,Zdim);
1522  SWITCHDATATYPE(V1.datatype,SCALETOSIZE)
1523 #undef SCALETOSIZE
1524 }
1525 
1536 void scaleToSize(int SplineDegree,
1538  const MultidimArrayGeneric &V1,int Xdim, int Ydim, int Zdim = 1);
1539 
1545 template<typename T>
1546 void selfScaleToSize(int SplineDegree,
1547  MultidimArray<T> &V1,
1548  int Xdim, int Ydim, int Zdim = 1)
1549 {
1550  MultidimArray<T> aux = V1;
1551  scaleToSize(SplineDegree, V1, aux, Xdim, Ydim, Zdim);
1552 }
1553 
1554 void selfScaleToSize(int SplineDegree,
1556  int Xdim, int Ydim, int Zdim = 1);
1557 
1558 
1559 // Special case for complex arrays
1560 void scaleToSize(int SplineDegree,
1561  MultidimArray< std::complex<double> > &V2,
1562  const MultidimArray< std::complex<double> > &V1,
1563  int Xdim, int Ydim, int Zdim = 1);
1564 
1565 // Special case for complex arrays
1566 void selfScaleToSize(int SplineDegree,
1567  MultidimArray< std::complex<double> > &V1,
1568  int Xdim, int Ydim, int Zdim = 1);
1569 
1570 
1577 template<typename T>
1578 void reduceBSpline(int SplineDegree,
1580  const MultidimArray<T> &V1);
1581 
1588 template<typename T>
1589 void expandBSpline(int SplineDegree,
1591  const MultidimArray<T> &V1);
1592 
1596 template<typename T>
1597 void pyramidReduce(int SplineDegree,
1598  MultidimArray<T> &V2,
1599  const MultidimArray<T> &V1,
1600  int levels = 1)
1601 {
1602  MultidimArray< double > coeffs, coeffs2;
1603 
1604  produceSplineCoefficients(SplineDegree, coeffs, V1);
1605 
1606  for (int i = 0; i < levels; i++)
1607  {
1608  reduceBSpline(SplineDegree, coeffs2, coeffs);
1609  coeffs = coeffs2;
1610  }
1611 
1612  produceImageFromSplineCoefficients(SplineDegree, V2, coeffs);
1613 }
1614 
1620 template<typename T>
1621 void selfPyramidReduce(int SplineDegree,
1622  MultidimArray<T> &V1,
1623  int levels = 1)
1624 {
1625  MultidimArray<T> aux = V1;
1626  V1.initZeros();
1627  pyramidReduce(SplineDegree, V1, aux, levels);
1628 }
1629 
1631 void selfPyramidReduce(int SplineDegree,
1633  int levels = 1);
1634 
1635 
1639 template<typename T>
1640 void pyramidExpand(int SplineDegree,
1641  MultidimArray<T> &V2,
1642  const MultidimArray<T> &V1,
1643  int levels = 1)
1644 {
1645  MultidimArray< double > coeffs, coeffs2;
1646 
1647  produceSplineCoefficients(SplineDegree, coeffs, V1);
1648 
1649  for (int i = 0; i < levels; i++)
1650  {
1651  expandBSpline(SplineDegree, coeffs2, coeffs);
1652  coeffs = coeffs2;
1653  }
1654 
1655  produceImageFromSplineCoefficients(SplineDegree, V2, coeffs);
1656 
1657 }
1658 
1659 void pyramidExpand(int SplineDegree,
1661  const MultidimArrayGeneric &V1,
1662  int levels = 1);
1663 
1664 void pyramidReduce(int SplineDegree,
1666  const MultidimArrayGeneric &V1,
1667  int levels = 1);
1668 
1674 template<typename T>
1675 void selfPyramidExpand(int SplineDegree,
1676  MultidimArray<T> &V1,
1677  int levels = 1)
1678 {
1679  MultidimArray<T> aux = V1;
1680  V1.initZeros();
1681  pyramidExpand(SplineDegree, V1, aux, levels);
1682 }
1683 
1685 void selfPyramidExpand(int SplineDegree,
1687  int levels = 1);
1688 
1689 
1710 template<typename T>
1712  Matrix1D< int >& center_of_rot,
1713  MultidimArray< T >& radial_mean,
1714  MultidimArray< int >& radial_count,
1715  const bool& rounding = false)
1716 {
1717  Matrix1D< double > idx(3);
1718 
1719  // If center_of_rot was written for 2D image
1720  if (center_of_rot.size() < 3)
1721  center_of_rot.resize(3);
1722 
1723  // First determine the maximum distance that one should expect, to set the
1724  // dimension of the radial average vector
1725  MultidimArray< int > distances(8);
1726 
1727  double z = STARTINGZ(m) - ZZ(center_of_rot);
1728  double y = STARTINGY(m) - YY(center_of_rot);
1729  double x = STARTINGX(m) - XX(center_of_rot);
1730 
1731  distances(0) = (int) floor(sqrt(x * x + y * y + z * z));
1732  x = FINISHINGX(m) - XX(center_of_rot);
1733 
1734  distances(1) = (int) floor(sqrt(x * x + y * y + z * z));
1735  y = FINISHINGY(m) - YY(center_of_rot);
1736 
1737  distances(2) = (int) floor(sqrt(x * x + y * y + z * z));
1738  x = STARTINGX(m) - XX(center_of_rot);
1739 
1740  distances(3) = (int) floor(sqrt(x * x + y * y + z * z));
1741  z = FINISHINGZ(m) - ZZ(center_of_rot);
1742 
1743  distances(4) = (int) floor(sqrt(x * x + y * y + z * z));
1744  x = FINISHINGX(m) - XX(center_of_rot);
1745 
1746  distances(5) = (int) floor(sqrt(x * x + y * y + z * z));
1747  y = STARTINGY(m) - YY(center_of_rot);
1748 
1749  distances(6) = (int) floor(sqrt(x * x + y * y + z * z));
1750  x = STARTINGX(m) - XX(center_of_rot);
1751 
1752  distances(7) = (int) floor(sqrt(x * x + y * y + z * z));
1753 
1754  int dim = (int) CEIL(distances.computeMax()) + 1;
1755  if (rounding)
1756  dim++;
1757 
1758  // Define the vectors
1759  radial_mean.initZeros(dim);
1760  radial_count.initZeros(dim);
1761 
1762  // Perform the radial sum and count pixels that contribute to every
1763  // distance
1765  {
1766  ZZ(idx) = k - ZZ(center_of_rot);
1767  YY(idx) = i - YY(center_of_rot);
1768  XX(idx) = j - XX(center_of_rot);
1769 
1770  // Determine distance to the center
1771  ;
1772  double module = sqrt(ZZ(idx)*ZZ(idx)+YY(idx)*YY(idx)+XX(idx)*XX(idx));
1773  int distance = (rounding) ? (int) round(module) : (int) floor(module);
1774 
1775  // Sum the value to the pixels with the same distance
1776  DIRECT_MULTIDIM_ELEM(radial_mean,distance) += A3D_ELEM(m, k, i, j);
1777 
1778  // Count the pixel
1779  DIRECT_MULTIDIM_ELEM(radial_count,distance)++;
1780  }
1781 
1782  // Perform the mean
1784  if (DIRECT_MULTIDIM_ELEM(radial_count,i) > 0)
1785  DIRECT_MULTIDIM_ELEM(radial_mean,i) /= DIRECT_MULTIDIM_ELEM(radial_count,i);
1786 }
1787 
1788 template<typename T>
1790  Matrix1D< int >& center_of_rot,
1792  int &dim,
1793  const bool& rounding = false)
1794 {
1795  Matrix1D< double > idx(3);
1796 
1797  // If center_of_rot was written for 2D image
1798  if (center_of_rot.size() < 3)
1799  center_of_rot.resize(3);
1800 
1801  // First determine the maximum distance that one should expect, to set the
1802  // dimension of the radial average vector
1803  MultidimArray< int > distances(8);
1804 
1805  double z = STARTINGZ(m) - ZZ(center_of_rot);
1806  double y = STARTINGY(m) - YY(center_of_rot);
1807  double x = STARTINGX(m) - XX(center_of_rot);
1808 
1809  distances(0) = (int) floor(sqrt(x * x + y * y + z * z));
1810  x = FINISHINGX(m) - XX(center_of_rot);
1811 
1812  distances(1) = (int) floor(sqrt(x * x + y * y + z * z));
1813  y = FINISHINGY(m) - YY(center_of_rot);
1814 
1815  distances(2) = (int) floor(sqrt(x * x + y * y + z * z));
1816  x = STARTINGX(m) - XX(center_of_rot);
1817 
1818  distances(3) = (int) floor(sqrt(x * x + y * y + z * z));
1819  z = FINISHINGZ(m) - ZZ(center_of_rot);
1820 
1821  distances(4) = (int) floor(sqrt(x * x + y * y + z * z));
1822  x = FINISHINGX(m) - XX(center_of_rot);
1823 
1824  distances(5) = (int) floor(sqrt(x * x + y * y + z * z));
1825  y = STARTINGY(m) - YY(center_of_rot);
1826 
1827  distances(6) = (int) floor(sqrt(x * x + y * y + z * z));
1828  x = STARTINGX(m) - XX(center_of_rot);
1829 
1830  distances(7) = (int) floor(sqrt(x * x + y * y + z * z));
1831 
1832  dim = (int) CEIL(distances.computeMax()) + 1;
1833  if (rounding)
1834  dim++;
1835 
1836  // Perform the radial sum and count pixels that contribute to every
1837  // distance
1838  distance.initZeros(m);
1840  {
1841  ZZ(idx) = k - ZZ(center_of_rot);
1842  YY(idx) = i - YY(center_of_rot);
1843  XX(idx) = j - XX(center_of_rot);
1844 
1845  // Determine distance to the center
1846  if (rounding)
1847  A3D_ELEM(distance,k,i,j) = (int) round(idx.module());
1848  else
1849  A3D_ELEM(distance,k,i,j) = (int) floor(idx.module());
1850  }
1851 }
1852 
1853 template<typename T>
1856  int dim,
1857  MultidimArray< T >& radial_mean,
1858  MultidimArray< int >& radial_count)
1859 {
1860  // Define the vectors
1861  radial_mean.initZeros(dim);
1862  radial_count.initZeros(dim);
1863 
1864  // Perform the radial sum and count pixels that contribute to every
1865  // distance
1867  {
1868  int d=DIRECT_MULTIDIM_ELEM(distance,n);
1869  A1D_ELEM(radial_mean,d) += DIRECT_MULTIDIM_ELEM(m,n);
1870  ++A1D_ELEM(radial_count,d);
1871  }
1872 
1873  // Perform the mean
1875  if (DIRECT_MULTIDIM_ELEM(radial_count,i) > 0)
1876  DIRECT_MULTIDIM_ELEM(radial_mean,i) /= DIRECT_MULTIDIM_ELEM(radial_count,i);
1877 }
1878 
1879 template<typename T>
1881 {
1882  MultidimArray<double> inCentered;
1883  inCentered.alias(in);
1884  inCentered.setXmippOrigin();
1885  if (axis=='z')
1886  {
1887  out.initZeros(ZSIZE(in),XSIZE(in));
1888  out.setXmippOrigin();
1889  for (int i=STARTINGY(inCentered); i<=FINISHINGY(inCentered); ++i)
1890  {
1891  double z=i;
1892  for (int j=0; j<XSIZE(out)/2; ++j)
1893  {
1894  for (double ang=0; ang<TWOPI; ang+=TWOPI/72)
1895  {
1896  double x=j*cos(ang);
1897  double y=j*sin(ang);
1898  double val=inCentered.interpolatedElement3D(x,y,z);
1899  A2D_ELEM(out,i,j)+=val;
1900  }
1901  A2D_ELEM(out,i,j)/=73;
1902  A2D_ELEM(out,i,-j)=A2D_ELEM(out,i,j);
1903  }
1904  }
1905  }
1906 
1907  else
1908  REPORT_ERROR(ERR_ARG_INCORRECT,"Not implemented yet");
1909 }
1910 
1911 template<typename T>
1913  Matrix1D< int >& center_of_rot,
1914  MultidimArray< T >& radial_mean,
1915  MultidimArray< int >& radial_count,
1916  bool rounding = false);
1917 
1919 
1928 double interpolatedElementBSplineDiffX(MultidimArray<double> &vol, double x, double y, double z,
1929  int SplineDegree = 3);
1930 
1939 double interpolatedElementBSplineDiffY(MultidimArray<double> &vol, double x, double y, double z,
1940  int SplineDegree = 3);
1949 double interpolatedElementBSplineDiffZ(MultidimArray<double> &vol, double x, double y, double z,
1950  int SplineDegree = 3);
1952 #endif
#define MAT_YSIZE(m)
Definition: matrix2d.h:124
bool isIdentity() const
Definition: matrix2d.cpp:1323
#define YSIZE(v)
void min(Image< double > &op1, const Image< double > &op2)
#define A2D_ELEM(v, i, j)
void translate(int SplineDegree, MultidimArray< T > &V2, const MultidimArray< T > &V1, const Matrix1D< double > &v, bool wrap=xmipp_transformation::WRAP, T outside=0)
double module() const
Definition: matrix1d.h:983
void applyGeometry(int SplineDegree, MultidimArray< T > &__restrict__ V2, const MultidimArray< T1 > &__restrict__ V1, const Matrix2D< T2 > &At, bool inv, bool wrap, T outside=T(0), MultidimArray< double > *BcoeffsPtr=NULL)
void translateCenterOfMassToCenter(int SplineDegree, MultidimArray< T > &V2, const MultidimArray< T > &V1, bool wrap=xmipp_transformation::WRAP)
#define APPLYGEO(type)
__host__ __device__ float2 floor(const float2 v)
void string2TransformationMatrix(const String &matrixStr, Matrix2D< double > &matrix, size_t dim=4)
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
T interpolatedElementBSpline2D_Degree3(double x, double y) const
void geo2TransformationMatrix(const MDRow &imageHeader, Matrix2D< double > &A, bool only_apply_shifts=false)
void transformationMatrix2Geo(const Matrix2D< double > &A, MDRow &imageGeo)
Problem with matrix size.
Definition: xmipp_error.h:152
void fastRadialAverage(const MultidimArray< T > &m, const MultidimArray< int > &distance, int dim, MultidimArray< T > &radial_mean, MultidimArray< int > &radial_count)
double interpolatedElementBSplineDiffZ(MultidimArray< double > &vol, double x, double y, double z, int SplineDegree=3)
void resizeNoCopy(const MultidimArray< T1 > &v)
#define dAij(M, i, j)
void sqrt(Image< double > &op)
void selfTranslateCenterOfMassToCenter(int SplineDegree, MultidimArray< T > &V1, bool wrap=xmipp_transformation::WRAP)
static double * y
void translation2DMatrix(const Matrix1D< T > &translation, Matrix2D< T > &resMatrix, bool inverse=false)
void selfApplyGeometry(int SplineDegree, MultidimArray< T > &V1, const Matrix2D< double > &A, bool inv, bool wrap, T outside=0)
T interpolatedElementBSpline3D(double x, double y, double z, int SplineDegree=3) const
#define DIRECT_A2D_ELEM(v, i, j)
#define A1D_ELEM(v, i)
#define TWOPI
Definition: xmipp_macros.h:111
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
void selfScaleToSize(int SplineDegree, MultidimArray< T > &V1, int Xdim, int Ydim, int Zdim=1)
#define SAME_SHAPE3D(v1, v2)
void translation3DMatrix(const Matrix1D< T > &translation, Matrix2D< T > &resMatrix, bool inverse=false)
#define FINISHINGZ(v)
#define FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY1D(v)
void selfRotate(int SplineDegree, MultidimArray< T > &V1, double ang, char axis='Z', bool wrap=xmipp_transformation::DONT_WRAP, T outside=0)
#define STARTINGX(v)
doublereal * x
#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 radialAverageAxis(const MultidimArray< T > &in, char axis, MultidimArray< double > &out)
void radialAverageNonCubic(const MultidimArray< T > &m, Matrix1D< int > &center_of_rot, MultidimArray< T > &radial_mean, MultidimArray< int > &radial_count, bool rounding=false)
doublereal * d
void rotation3DMatrix(double ang, char axis, Matrix2D< double > &m, bool homogeneous=true)
void centerOfMass(Matrix1D< double > &center, void *mask=NULL, size_t n=0)
#define STARTINGY(v)
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
#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)
double v1
char axis
void applyGeometry2DDegree1(MultidimArray< T > &__restrict__ V2, const MultidimArray< T1 > &__restrict__ V1, const Matrix2D< double > &Aref)
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
void scaleToSize(int SplineDegree, MultidimArray< T > &V2, const MultidimArray< T1 > &V1, size_t Xdim, size_t Ydim, size_t Zdim=1)
void selfTranslate(int SplineDegree, MultidimArray< T > &V1, const Matrix1D< double > &v, bool wrap=xmipp_transformation::WRAP, T outside=0)
#define CEIL(x)
Definition: xmipp_macros.h:225
int in
Incorrect argument received.
Definition: xmipp_error.h:113
void rotate(int SplineDegree, MultidimArray< T > &V2, const MultidimArray< T > &V1, double ang, char axis='Z', bool wrap=xmipp_transformation::DONT_WRAP, T outside=0)
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
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)
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)
#define dAkij(V, k, i, j)
void radiallySymmetrize(const MultidimArray< double > &img, MultidimArray< double > &radialImg)
#define ZSIZE(v)
double z
#define DIRECT_MULTIDIM_ELEM(v, n)
T interpolatedElement3D(double x, double y, double z, T outside_value=(T) 0) const
void selfPyramidReduce(int SplineDegree, MultidimArray< T > &V1, int levels=1)
void scale3DMatrix(const Matrix1D< double > &sc, Matrix2D< double > &m, bool homogeneous=true)
void pyramidExpand(int SplineDegree, MultidimArray< T > &V2, const MultidimArray< T > &V1, int levels=1)
void alias(const MultidimArray< T > &m)
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)
#define XMIPP_RANGE_OUTSIDE(x, min, max)
Definition: xmipp_macros.h:126
T interpolatedElementBSpline2D(double x, double y, int SplineDegree=3) const
void rotation2DMatrix(T ang, Matrix2D< T > &m, bool homogeneous=true)
#define j
#define YY(v)
Definition: matrix1d.h:93
int m
int trunc(double x)
Definition: ap.cpp:7248
TYPE distance(struct Point_T *p, struct Point_T *q)
Definition: point.cpp:28
#define SCALETOSIZE(type)
#define FINISHINGY(v)
void radialAverage(const MultidimArray< T > &m, Matrix1D< int > &center_of_rot, MultidimArray< T > &radial_mean, MultidimArray< int > &radial_count, const bool &rounding=false)
int round(double x)
Definition: ap.cpp:7245
Definition: ctf.h:38
void typeCast(const Matrix1D< T1 > &v1, Matrix1D< T2 > &v2)
Definition: matrix1d.h:1227
#define MAT_XSIZE(m)
Definition: matrix2d.h:120
double interpolatedElementBSplineDiffX(MultidimArray< double > &vol, double x, double y, double z, int SplineDegree=3)
std::string String
Definition: xmipp_strings.h:34
double psi(const double x)
bool getLoopRange(double value, double min, double max, double delta, int loopLimit, int &minIter, int &maxIter)
#define realWRAP(x, x0, xF)
Definition: xmipp_macros.h:304
#define XMIPP_RANGE_OUTSIDE_FAST(x, min, max)
Definition: xmipp_macros.h:128
void reduceBSpline(int SplineDegree, MultidimArray< double > &V2, const MultidimArray< T > &V1)
void produceImageFromSplineCoefficients(int SplineDegree, MultidimArray< T > &img, const MultidimArray< double > &coeffs)
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
double interpolatedElementBSplineDiffY(MultidimArray< double > &vol, double x, double y, double z, int SplineDegree=3)
void initZeros(const MultidimArray< T1 > &op)
void alignWithZ(const Matrix1D< double > &axis, Matrix2D< double > &m, bool homogeneous=true)
Incorrect value received.
Definition: xmipp_error.h:195
#define STARTINGZ(v)
int * n
#define ZZ(v)
Definition: matrix1d.h:101
void initIdentity()
Definition: matrix2d.h:673
T computeMax() const
#define SWITCHDATATYPE(datatype, OP)
double * delta
void selfPyramidExpand(int SplineDegree, MultidimArray< T > &V1, int levels=1)
void pyramidReduce(int SplineDegree, MultidimArray< T > &V2, const MultidimArray< T > &V1, int levels=1)