Xmipp  v3.23.11-Nereus
project_real_shears.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Slavica JONIC (slavica.jonic@impmc.jussieu.fr, slavica.jonic@a3.epfl.ch)
4  * Jean-Noel PIOCHE (jnp95@hotmail.com)
5  *
6  * Biomedical Imaging Group, EPFL (Lausanne, Suisse).
7  * Structures des Assemblages MacromolĂ©culaires, IMPMC UMR 7590 (Paris, France).
8  * IUT de Reims-Chlons-Charleville (Reims, France).
9  *
10  * Last modifications by JNP the 27/05/2009 15:52:56
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25  * 02111-1307 USA
26  *
27  * All comments concerning this program package may be sent to the
28  * e-mail address 'xmipp@cnb.csic.es'
29  ***************************************************************************/
30 
31 #include "project_real_shears.h"
32 #include "core/bilib/getputd.h"
33 #include "core/bilib/changebasis.h"
34 #include "core/bilib/configs.h"
35 #include "core/bilib/kernel.h"
36 #include "core/transformations.h"
38 
39 #ifndef DBL_EPSILON
40 #define DBL_EPSILON 2.2204460492503130808472633361816000000000e-16
41 #endif
42 
44 {
45  volume=&V;
46  if (XSIZE(V)!=XSIZE(V) || XSIZE(V)!=ZSIZE(V))
47  REPORT_ERROR(ERR_MULTIDIM_DIM, "The volume must be cubic");
48  Xdim=XSIZE(*volume);
49 
50  int Status = !ERROR;
51  MultidimArray<double> planeCoef, inputPlane, inputRow;
55  planeCoef.resizeNoCopy(Xdim,Xdim);
56  inputPlane.resizeNoCopy(Xdim,Xdim);
57  inputRow.resizeNoCopy(Xdim);
58 
59  for (long l = 0; l<Xdim; l++)
60  {
61  for (long m = 0; m < Xdim; m++)
62  {
63  CopyDoubleToDouble(MULTIDIM_ARRAY(V), Xdim, Xdim, Xdim, l, 0L, m,
64  MULTIDIM_ARRAY(inputRow), 1L, Xdim, 1L, 0L, 0L, 0L,
65  1L, Xdim, 1L);
66  memcpy(&DIRECT_A2D_ELEM(inputPlane,m,0),
67  MULTIDIM_ARRAY(inputRow),Xdim*sizeof(double));
68  }
69 
70  ChangeBasisVolume(MULTIDIM_ARRAY(inputPlane), MULTIDIM_ARRAY(planeCoef),
71  Xdim, Xdim, 1L, CardinalSpline,
73 
74  CopyDoubleToDouble(MULTIDIM_ARRAY(planeCoef), Xdim, Xdim, 1L, 0L, 0L, 0L,
75  MULTIDIM_ARRAY(Coef_x), Xdim, Xdim, Xdim, 0L, 0L, l,
76  Xdim, Xdim, 1L);
77  }
78 
79  for (long l = 0; l < Xdim; l++)
80  {
81  for (long m = 0; m < Xdim; m++)
82  {
83  CopyDoubleToDouble(MULTIDIM_ARRAY(V), Xdim, Xdim, Xdim, 0L, l, m,
84  MULTIDIM_ARRAY(inputRow), Xdim, 1L, 1L, 0L, 0L, 0L,
85  Xdim, 1L, 1L);
86  CopyDoubleToDouble(MULTIDIM_ARRAY(inputRow), Xdim, 1L, 1L, 0L, 0L, 0L,
87  MULTIDIM_ARRAY(inputPlane), Xdim, Xdim, 1L, 0L, m, 0L,
88  Xdim, 1L, 1L);
89  }
90 
91  ChangeBasisVolume(MULTIDIM_ARRAY(inputPlane), MULTIDIM_ARRAY(planeCoef),
92  Xdim, Xdim, 1L, CardinalSpline,
94  CopyDoubleToDouble(MULTIDIM_ARRAY(planeCoef), Xdim, Xdim, 1L, 0L, 0L, 0L,
95  MULTIDIM_ARRAY(Coef_y), Xdim, Xdim, Xdim, 0L, 0L, l,
96  Xdim, Xdim, 1L);
97  }
98 
99  for (long l = 0L; l < Xdim; l++)
100  {
101  for (long m = 0L; m < Xdim; m++)
102  {
103  CopyDoubleToDouble(MULTIDIM_ARRAY(V), Xdim, Xdim, Xdim, 0L, m, l,
104  MULTIDIM_ARRAY(inputRow), Xdim, 1L, 1L, 0L, 0L, 0L,
105  Xdim, 1L, 1L);
106  CopyDoubleToDouble(MULTIDIM_ARRAY(inputRow), Xdim, 1L, 1L, 0L, 0L, 0L,
107  MULTIDIM_ARRAY(inputPlane), Xdim, Xdim, 1L, 0L, m, 0L,
108  Xdim, 1L, 1L);
109  }
110 
111  ChangeBasisVolume(MULTIDIM_ARRAY(inputPlane), MULTIDIM_ARRAY(planeCoef),
112  Xdim, Xdim, 1L, CardinalSpline,
114  CopyDoubleToDouble(MULTIDIM_ARRAY(planeCoef), Xdim, Xdim, 1L, 0L, 0L, 0L,
115  MULTIDIM_ARRAY(Coef_z), Xdim, Xdim, Xdim, 0L, 0L, l,
116  Xdim, Xdim, 1L);
117  }
118 
119  Ac.initIdentity(4);
120  Acinv.initIdentity(4);
121  double halfSize=Xdim/2;
122  MAT_ELEM(Ac,0,3)=MAT_ELEM(Ac,1,3)=MAT_ELEM(Ac,2,3)=halfSize;
123  MAT_ELEM(Acinv,0,3)=MAT_ELEM(Acinv,1,3)=MAT_ELEM(Acinv,2,3)=-halfSize;
124 }
125 
127 void convertAngles(double &phi, double &theta, double &psi)
128 {
130  Euler_angles2matrix(phi,theta,psi,E,false);
131  double A00=MAT_ELEM(E,0,0);
132  double A02=MAT_ELEM(E,0,2);
133  double A10=MAT_ELEM(E,1,0);
134  double A12=MAT_ELEM(E,1,2);
135  double A20=MAT_ELEM(E,2,0);
136  double A21=MAT_ELEM(E,2,1);
137  double A22=MAT_ELEM(E,2,2);
138 
139  double abs_cosay = sqrt(A22*A22+A21*A21);
140 
141  //Results angles
142  double ax, ay, az;
143 
144  if(abs_cosay > 0.0)
145  {
146  double sign_cosay;
147 
148  ax = atan2(-A21, A22);
149  az = atan2(-A10, A00);
150 
151  if(fabs(cos(ax)) == 0.0)
152  sign_cosay = SGN(-A21/sin(ax));
153  else
154  {
155  if (cos(ax) > 0.0)
156  sign_cosay = SGN(A22);
157  else
158  sign_cosay = -SGN(A22);
159  }
160 
161  ay = atan2(A20, sign_cosay * abs_cosay);
162  }
163  else
164  {
165  //Let's consider the matrix as a rotation around Z
166  if (SGN(A20) > 0.0)
167  {
168  ax = 0.0;
169  ay = PI/2.0;
170  az = atan2(A12, -A02);
171  }
172  else
173  {
174  ax = 0.0;
175  ay = -PI/2.0;
176  az = atan2(-A12, A02);
177  }
178  }
179 
180  phi = ax;
181  theta = ay;
182  psi = az;
183 }
184 
185 //-------------------------------------------------------------------------
186 // Second level of projection
188  double absscale,
189  Matrix2D<double> &Binv,
190  Matrix1D<double> &BinvCscaled,
191  int *arr,
192  MultidimArray<double> &projection)
193 {
194  double K[4], Arg[4], Ki[4];
195  int Xdim=XSIZE(projection);
196  double *ptrProjection=MULTIDIM_ARRAY(projection);
197  size_t CC1 = Xdim * Xdim;
198 
199  Ki[0]=dMn(Binv,3);
200  Ki[1]=dMn(Binv,7);
201  Ki[2]=dMn(Binv,11);
202  Ki[3]=dMn(Binv,15);
203  for (int i = 0; i < Xdim; i++)
204  {
205  K[0]=Ki[0];
206  K[1]=Ki[1];
207  K[2]=Ki[2];
208  K[3]=Ki[3];
209  for (int n = 0; n < Xdim; n++)
210  {
211  double Proj = 0.0;
212  for (int ksi = 0; ksi < Xdim; ksi++)
213  {
214  size_t CC2 = CC1 * ksi;
215  double sc = (double) ksi - K[arr[0]];
216  Arg[0]=VEC_ELEM(BinvCscaled,0)*sc+K[0];
217  Arg[1]=VEC_ELEM(BinvCscaled,1)*sc+K[1];
218  Arg[2]=VEC_ELEM(BinvCscaled,2)*sc+K[2];
219  Arg[3]=VEC_ELEM(BinvCscaled,3)*sc+K[3];
220  double g = Arg[arr[1]];
221  double h = Arg[arr[2]];
222 
223  auto l1 = (int)ceil(g-2.0);
224  int l2 = l1 + 3;
225  auto m1 = (int)ceil(h-2.0);
226  int m2 = m1 + 3;
227  double columns = 0.0;
228  double aux;
229  for (int m = m1; m <= m2; m++)
230  {
231  if (m < Xdim && m > -1)
232  {
233  size_t CC3 = CC2 + Xdim * m;
234  double rows = 0.0;
235  for (int l = l1; l <= l2; l++)
236  {
237  if (l < Xdim && l > -1)
238  {
239  double gminusl = g - (double) l;
240  BSPLINE03(aux,gminusl);
241  double Coeff = DIRECT_A1D_ELEM(CoefVolume,CC3 + l);
242  rows += Coeff * aux;
243  }
244  }
245  double hminusm = h - (double) m;
246  BSPLINE03(aux,hminusm);
247  columns += rows * aux;
248  }
249  }
250  Proj += columns;
251  }
252  *ptrProjection++ = Proj*absscale;
253  K[0]+=dMn(Binv,0);
254  K[1]+=dMn(Binv,4);
255  K[2]+=dMn(Binv,8);
256  K[3]+=dMn(Binv,12);
257  }
258  Ki[0]+=dMn(Binv,1);
259  Ki[1]+=dMn(Binv,5);
260  Ki[2]+=dMn(Binv,9);
261  Ki[3]+=dMn(Binv,13);
262  }
263 }
264 
265 //-------------------------------------------------------------------------
266 // First level of projection
268  double phi, double theta, double psi,
269  double shiftX, double shiftY,
270  MultidimArray<double> &projection)
271 {
273  R.initIdentity(4);
274  MAT_ELEM(R,0,3)=shiftX;
275  MAT_ELEM(R,1,3)=shiftY;
276  Matrix2D<double> B=Data.Ac*R;
277  rotation3DMatrix(-RAD2DEG(phi),'X',R,true);
278  B=B*R;
279  rotation3DMatrix(RAD2DEG(theta),'Y',R,true);
280  B=B*R;
281  rotation3DMatrix(-RAD2DEG(psi),'Z',R,true);
282  B=B*R;
283  B=B*Data.Acinv;
284  Matrix2D<double> Binv;
285  B.inv(Binv);
286  Matrix1D<double> BinvC;
287  Binv.getCol(2,BinvC);
288 
289  double scale_x, scale_y, scale_z;
290  if (XX(BinvC) != 0.0)
291  scale_x = 1.0 / XX(BinvC);
292  else
293  scale_x = 1e38;
294 
295  if (YY(BinvC) != 0.0)
296  scale_y = 1.0 / YY(BinvC);
297  else
298  scale_y = 1e38;
299 
300  if (ZZ(BinvC) != 0.0)
301  scale_z = 1.0 / ZZ(BinvC);
302  else
303  scale_z = 1e38;
304  double m_x = fabs(scale_x);
305  double m_y = fabs(scale_y);
306  double m_z = fabs(scale_z);
307 
308  int arr[3];
309  double minm = m_x;
310  double scale = scale_x;
311  arr[0] = 0;
312  arr[1] = 1;
313  arr[2] = 2;
314  MultidimArray<double> *Coef_xyz = &Data.Coef_x;
315  if (m_y < minm)
316  {
317  minm = m_y;
318  scale = scale_y;
319  arr[0] = 1;
320  arr[1] = 0;
321  arr[2] = 2;
322  Coef_xyz = &Data.Coef_y;
323  }
324  if (m_z < minm)
325  {
326  minm = m_z;
327  scale = scale_z;
328  arr[0] = 2;
329  arr[1] = 0;
330  arr[2] = 1;
331  Coef_xyz = &Data.Coef_z;
332  }
333  Matrix1D<double> BinvCscaled=BinvC;
334  BinvCscaled*=scale;
335 
336  projectionRealShears2(*Coef_xyz, minm, Binv, BinvCscaled, arr, projection);
337 }
338 
339 void projectVolume(RealShearsInfo &Data, Projection &P, int Ydim, int Xdim,
340  double rot, double tilt, double psi, double shiftX, double shiftY)
341 {
342  P.reset(Data.Xdim,Data.Xdim);
343  double Phi=-psi;
344  double Theta=-tilt;
345  double Psi=-rot;
346  convertAngles(Phi, Theta, Psi);
347  projectionRealShears1(Data, Phi, Theta, Psi, shiftX, shiftY, P());
348  if (Ydim!=Data.Xdim || Xdim!=Data.Xdim)
349  P().selfWindow(FIRST_XMIPP_INDEX(Ydim),FIRST_XMIPP_INDEX(Xdim),
350  LAST_XMIPP_INDEX(Ydim),LAST_XMIPP_INDEX(Xdim));
351 }
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
void reset(int Ydim, int Xdim)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
doublereal * g
void resizeNoCopy(const MultidimArray< T1 > &v)
void sqrt(Image< double > &op)
#define DIRECT_A2D_ELEM(v, i, j)
void convertAngles(double &phi, double &theta, double &psi)
Transforms angles from (Ry, Rz, Ry) to (Rx, Ry, Rz) system. Returns possible error.
#define MULTIDIM_ARRAY(v)
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
void projectionRealShears2(MultidimArray< double > &CoefVolume, double absscale, Matrix2D< double > &Binv, Matrix1D< double > &BinvCscaled, int *arr, MultidimArray< double > &projection)
const MultidimArray< double > * volume
MultidimArray< double > Coef_y
void projectVolume(RealShearsInfo &Data, Projection &P, int Ydim, int Xdim, double rot, double tilt, double psi, double shiftX, double shiftY)
Make projection.
#define i
double theta
MultidimArray< double > Coef_x
void rotation3DMatrix(double ang, char axis, Matrix2D< double > &result, bool homogeneous)
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
#define DIRECT_A1D_ELEM(v, i)
MultidimArray< double > Coef_z
#define XX(v)
Definition: matrix1d.h:85
#define ERROR
Definition: configs.h:24
Matrix2D< double > Ac
#define XSIZE(v)
Structure for holding a volume.
#define ZSIZE(v)
Matrix2D< double > Acinv
RealShearsInfo(const MultidimArray< double > &V)
#define YY(v)
Definition: matrix1d.h:93
#define DBL_EPSILON
void getCol(size_t j, Matrix1D< T > &v) const
Definition: matrix2d.cpp:890
int m
#define RAD2DEG(r)
Definition: xmipp_macros.h:320
void projectionRealShears1(RealShearsInfo &Data, double phi, double theta, double psi, double shiftX, double shiftY, MultidimArray< double > &projection)
#define FIRST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:439
double psi(const double x)
#define dMn(m, n)
Definition: matrix2d.h:146
int CopyDoubleToDouble(double *VolumeSource, long NxSource, long NySource, long NzSource, long XSource, long YSource, long ZSource, double *VolumeDestination, long NxDestination, long NyDestination, long NzDestination, long XDestination, long YDestination, long ZDestination, long NxCopy, long NyCopy, long NzCopy)
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)
Incorrect MultidimArray dimensions.
Definition: xmipp_error.h:173
constexpr int K
#define LAST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:448
#define PI
Definition: tools.h:43
#define SGN(x)
Definition: xmipp_macros.h:155
int * n
#define ZZ(v)
Definition: matrix1d.h:101
#define BSPLINE03(y, x)
Definition: kernel.h:83
void initIdentity()
Definition: matrix2d.h:673