Xmipp  v3.23.11-Nereus
validation_tilt_pairs.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Jose Luis Vilas (jlvilas@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 #include "validation_tilt_pairs.h"
26 #include <core/metadata_vec.h>
28 #include <complex>
29 
30 //Define Program parameters
32 {
33  //Usage
34  addUsageLine("Takes two coordinates sets and defines the coordinate transformation between them");
35  addUsageLine("First set defines the untilted coordinates, second set defines the tilted coordinates");
36  addParamsLine(" --tilt <metadata> : Metadata with angular assignment for the tilted images");
37  addParamsLine(" --untilt <metadata> : Metadata with angular assignment for the untilted images");
38  addParamsLine(" -o <metadata> : Metadata with matrix transformation");
39 }
40 
41 
42 
43 //Read params
45 {
46  fntiltimage_In = getParam("--tilt"); //Set of tilted coordinates
47  fnuntiltimage_In = getParam("--untilt");
48  fnOut = getParam("-o"); //Output file
49 }
50 
51 
52 void ProgValidationTiltPairs::quaternion2Paulibasis(double rot, double tilt, double psi, std::complex<double> (&L)[4])
53 {
54  double cr, ct, cp, sr, st, sp;
55  std::complex<double> I(0,1);
56 
57  cr = cos(rot/2);
58  ct = cos(tilt/2);
59  cp = cos(psi/2);
60  sr = sin(rot/2);
61  st = sin(tilt/2);
62  sp = sin(psi/2);
63 
64  L[0] = cr*ct*cp - sr*ct*sp;
65  L[1] = I*(sr*st*cp - cr*st*sp);
66  L[2] = I*(cr*st*cp + sr*st*sp);
67  L[3] = I*(sr*ct*cp+cr*ct*sp);
68 }
69 
70 
71 void ProgValidationTiltPairs::matrix2Paulibasis(std::complex<double> M[4],
72  std::complex<double> (&P)[4])
73 {
74  //M[0] = m11; M[1]=m12; M[2]=m21; M[3]=m22
75 
76  std::complex<double> I(0,1);
77  std::complex<double> aux=0.5;
78  P[0]=(M[0]+M[3])*aux;
79  P[1]=(M[1]+M[2])*aux;
80  P[2]=I*(M[1]-M[2])*aux;
81  P[3]=(M[0]-M[3])*aux;
82 }
83 
84 void ProgValidationTiltPairs::InversefromPaulibasis(std::complex<double> Original[4],
85  std::complex<double> (&Inver)[4])
86 {
87  //It takes a Pauli expression and returns its inverse expressed in Pauli basis
88 
89  //TODO Raise an exception is the Original matrix does not belong to SU(2) group
90 
91  std::complex<double> Inver_matrix[4], mat[4];
92  std::complex<double> NOriginal;
93 
94  Paulibasis2matrix(Original,mat);
95 
96  Inver_matrix[0] = mat[3];
97  Inver_matrix[1] = -mat[1];
98  Inver_matrix[2] = -mat[2];
99  Inver_matrix[3] = mat[0];
100 
101  matrix2Paulibasis(Inver_matrix,Inver);
102 }
103 
104 void ProgValidationTiltPairs::inverse_matrixSU2(std::complex<double> Original[4],
105  std::complex<double> (&Inver)[4])
106 {
107  //It takes a matrix and returns its inverse expressed in Pauli basis
108 
109  //TODO Raise an exception is the Original matrix does not belong to SU(2) group
110 
111  std::complex<double> Inver_matrix[4];
112 
113  Inver_matrix[0] = Original[3];
114  Inver_matrix[1] = -Original[1];
115  Inver_matrix[2] = -Original[2];
116  Inver_matrix[3] = Original[0];
117 
118  matrix2Paulibasis(Inver_matrix,Inver);
119 }
120 
121 void ProgValidationTiltPairs::Paulibasis2matrix(std::complex<double> P[4], std::complex<double> (&M)[4])
122 {
123  std::complex<double> I(0,1);
124  M[0] = (P[0]+P[3]);
125  M[1] = (P[1]-I*P[2]);
126  M[2] = (P[1]+I*P[2]);
127  M[3] = (P[0]-P[3]);
128 }
129 
130 void ProgValidationTiltPairs::Pauliproduct(std::complex<double> A[4], std::complex<double> B[4],
131  std::complex<double> (&P)[4])
132 {
133  std::complex<double> A_matrix[4], B_matrix[4], aux[4];
134 
135  Paulibasis2matrix(A,A_matrix);
136  Paulibasis2matrix(B,B_matrix);
137 
138  aux[0] = A_matrix[0]*B_matrix[0] + A_matrix[1]*B_matrix[2];
139  aux[2] = A_matrix[2]*B_matrix[0] + A_matrix[3]*B_matrix[2];
140  aux[1] = A_matrix[0]*B_matrix[1] + A_matrix[1]*B_matrix[3];
141  aux[3] = A_matrix[2]*B_matrix[1] + A_matrix[3]*B_matrix[3];
142 
143  matrix2Paulibasis(aux, P);
144 }
145 
146 void ProgValidationTiltPairs::extrarotationangles(std::complex<double> R[4], double &alpha_x, double &alpha_y)
147 {
148  std::complex<double> I(0,1);
149  std::complex<double> aux1 = I*R[1]/R[0], aux2 = I*R[2]/R[0], alpha_aux_x, alpha_aux_y;
150 
151  if ((aux1.imag() == 0) && (aux2.imag() == 0))
152  {
153  alpha_aux_x = 2*atan(aux1.real());
154  alpha_aux_y = 2*atan(aux2.real());
155  alpha_x = alpha_aux_x.real()*180/PI;
156  alpha_y = alpha_aux_y.real()*180/PI;
157  }
158  else
159  {
160  std::cout << "Error, argument of atan is complex" << std::endl;
161  }
162 }
163 
164 
166  double tilt_angles[3], double alpha_x, double alpha_y)
167 {
168  double rotu = untilt_angles[0], tiltu = untilt_angles[1], psiu = untilt_angles[2];
169  double rott = tilt_angles[0], tiltt = tilt_angles[1], psit = tilt_angles[2];
170  std::complex<double> qu[4], M[4], Inv_qu[4], qt[4], R[4];
171 
172  quaternion2Paulibasis(rotu, tiltu, psiu, qu);
173  Paulibasis2matrix(qu,M);
174  inverse_matrixSU2(M, Inv_qu);
175  quaternion2Paulibasis(rott, tiltt, psit, qt);
176  Pauliproduct(qt, Inv_qu, R);
177 
178  extrarotationangles(R, alpha_x, alpha_y);
179  std::cout << "alpha_x = " << alpha_x << std::endl;
180  std::cout << "alpha_y = " << alpha_y << std::endl;
181 }
182 
184 {
185  MetaDataVec MD_tilted, MD_untilted, DF1sorted, DF2sorted, DFweights;
186 
187  MD_tilted.read(fntiltimage_In);
188  MD_untilted.read(fnuntiltimage_In);
189 
190  DF1sorted.sort(MD_tilted,MDL_ITEM_ID,true);
191  DF2sorted.sort(MD_untilted,MDL_ITEM_ID,true);
192 
193  auto iter1(DF1sorted.ids().begin()), iter2(DF2sorted.ids().begin());
194  std::vector< Matrix1D<double> > ang1, ang2;
195  Matrix1D<double> rotTiltPsi(3), z(3);
196  size_t currentId;
197  bool anotherImageIn2 = iter2 != DF2sorted.ids().end();
198  size_t id1, id2;
199  bool mirror;
200  Matrix2D<double> Eu, Et, R;
201  double alpha, beta;
202  while (anotherImageIn2)
203  {
204  ang1.clear();
205  ang2.clear();
206 
207  // Take current id
208  DF2sorted.getValue(MDL_ITEM_ID,currentId,*iter2);
209 
210  // Grab all the angles in DF2 associated to this id
211  bool anotherIteration=false;
212  do
213  {
214  DF2sorted.getValue(MDL_ITEM_ID,id2,*iter2);
215  anotherIteration=false;
216  if (id2==currentId)
217  {
218  DF2sorted.getValue(MDL_ANGLE_ROT,XX(rotTiltPsi),*iter2);
219  DF2sorted.getValue(MDL_ANGLE_TILT,YY(rotTiltPsi),*iter2);
220  DF2sorted.getValue(MDL_ANGLE_PSI,ZZ(rotTiltPsi),*iter2);
221  DF2sorted.getValue(MDL_FLIP,mirror,*iter2);
222  std::cout << "From DF2:" << XX(rotTiltPsi) << " " << YY(rotTiltPsi) << " " << ZZ(rotTiltPsi) << " " << mirror << std::endl;
223  //LINEA ANTERIOR ORIGINAL
224  if (mirror)
225  {
226  double rotp, tiltp, psip;
227  Euler_mirrorX(XX(rotTiltPsi),YY(rotTiltPsi),ZZ(rotTiltPsi), rotp, tiltp, psip);
228  XX(rotTiltPsi)=rotp;
229  YY(rotTiltPsi)=tiltp;
230  ZZ(rotTiltPsi)=psip;
231  }
232  ang2.push_back(rotTiltPsi);
233  ++iter2;
234  if (iter2 != DF2sorted.ids().end())
235  anotherIteration=true;
236  }
237  } while (anotherIteration);
238 
239  // Advance Iter 1 to catch Iter 2
240  double N=0, cumulatedDistance=0;
241  size_t newObjId=0;
242  if (*iter1 > 0)
243  {
244  DF1sorted.getValue(MDL_ITEM_ID,id1,*iter1);
245  while (id1<currentId && iter1 != DF1sorted.ids().end())
246  {
247  ++iter1;
248  DF1sorted.getValue(MDL_ITEM_ID,id1,*iter1);
249  }
250 
251  // If we are at the end of DF1, then we did not find id1 such that id1==currentId
252  if (iter1 == DF1sorted.ids().end())
253  break;
254 
255  // Grab all the angles in DF1 associated to this id
256  do
257  {
258  DF1sorted.getValue(MDL_ITEM_ID,id1,*iter1);
259  anotherIteration=false;
260  if (id1==currentId)
261  {
262  DF1sorted.getValue(MDL_ANGLE_ROT,XX(rotTiltPsi),*iter1);
263  DF1sorted.getValue(MDL_ANGLE_TILT,YY(rotTiltPsi),*iter1);
264  DF1sorted.getValue(MDL_ANGLE_PSI,ZZ(rotTiltPsi),*iter1);
265  DF1sorted.getValue(MDL_FLIP,mirror,*iter1);
266  std::cout << "From DF1:" << XX(rotTiltPsi) << " " << YY(rotTiltPsi) << " " << ZZ(rotTiltPsi) << " " << mirror << std::endl;
267  //LINEA ANTERIOR ORIGINAL
268  if (mirror)
269  {
270  double rotp, tiltp, psip;
271  Euler_mirrorX(XX(rotTiltPsi),YY(rotTiltPsi),ZZ(rotTiltPsi), rotp, tiltp, psip);
272  XX(rotTiltPsi)=rotp;
273  YY(rotTiltPsi)=tiltp;
274  ZZ(rotTiltPsi)=psip;
275  }
276  ang1.push_back(rotTiltPsi);
277  ++iter1;
278  if (iter1 != DF1sorted.ids().end())
279  anotherIteration=true;
280  }
281  } while (anotherIteration);
282 
283  // Process both sets of angles
284  for (size_t i=0; i<ang2.size(); ++i)
285  {
286  const Matrix1D<double> &anglesi=ang2[i];
287  double rotu=XX(anglesi);
288  double tiltu=YY(anglesi);
289  double psiu=ZZ(anglesi);
290  Euler_angles2matrix(rotu,tiltu,psiu,Eu,false);
291  /*std::cout << "------UNTILTED MATRIX------" << std::endl;
292  std::cout << Eu << std::endl;
293  std::cout << "vector" << std::endl;
294  std::cout << Eu(2,0) << " " << Eu(2,1) << " " << Eu(2,2) << std::endl;*/
295 
296 
297  for (size_t j=0; j<ang1.size(); ++j)
298  {
299  const Matrix1D<double> &anglesj=ang1[j];
300  double rott=XX(anglesj);
301  double tiltt=YY(anglesj);
302  double psit=ZZ(anglesj);
303  double alpha_x = 0;
304  double alpha_y = 0;
305  Euler_angles2matrix(rott,tiltt,psit,Et,false);
307  double untilt_angles[3]={rotu, tiltu, psiu}, tilt_angles[3]={rott, tiltt, psit};
308  angles2tranformation(untilt_angles, tilt_angles, alpha_x, alpha_y);
309  //std::cout << "alpha = " << (alpha_x*alpha_x+alpha_y*alpha_y) << std::endl;
311  /*std::cout << "------TILTED MATRIX------" << std::endl;
312  std::cout << Et << std::endl;
313  std::cout << "vector" << std::endl;
314  std::cout << Et(2,0) << " " << Et(2,1) << " " << Et(2,2) << std::endl;
315  std::cout << "---------------------------" << std::endl;
316  std::cout << "---------------------------" << std::endl;*/
317  R=Eu*Et.transpose();
318  double rotTransf, tiltTransf, psiTransf;
319  Euler_matrix2angles(R, rotTransf, tiltTransf, psiTransf);
320  std::cout << "Rot_and_Tilt " << rotTransf << " " << tiltTransf << std::endl;
321  //LINEA ANTERIOR ORIGINAL
322 
323  XX(z) = Eu(2,0) - Et(2,0);
324  YY(z) = Eu(2,1) - Et(2,1);
325  ZZ(z) = Eu(2,2) - Et(2,2);
326 
327  alpha = atan2(YY(z), XX(z)); //Expressed in rad
328  beta = atan2(XX(z)/cos(alpha), ZZ(z)); //Expressed in rad
329  std::cout << "alpha = " << alpha*180/PI << std::endl;
330  std::cout << "beta = " << beta*180/PI << std::endl;
331  }
332  }
333  }
334  else
335  N=0;
336 
337  if (N>0)
338  {
339  double meanDistance=cumulatedDistance/ang2.size();
340  DFweights.setValue(MDL_ANGLE_DIFF,meanDistance,newObjId);
341  }
342  else
343  if (newObjId>0)
344  DFweights.setValue(MDL_ANGLE_DIFF,-1.0,newObjId);
345  anotherImageIn2 = iter2 != DF2sorted.ids().end();
346  }
347 
348  std::complex<double> qu[4], qt[4], M[4], Inv_qu[4], P1[4], Inv_quu[4];
349  double rotu=34*PI/180, tiltu=10*PI/180, psiu=5*PI/180;
350  double rott=25*PI/180, tiltt=15*PI/180, psit=40*PI/180;
351 
352 
353  quaternion2Paulibasis(rotu, tiltu, psiu, qu);
354  /*std::cout << "quaternion2Pauli" << std::endl;
355  std::cout << "Untilted " << qu[0] << " " << qu[1] << " " << qu[2] << " " << qu[3] << std::endl;
356  std::cout << " " << std::endl;*/
357 
358  Paulibasis2matrix(qu,M);
359  /*std::cout << "Pauli2matrix" << std::endl;
360  std::cout << "Matriz " << M[0] << " " << M[1] << " " << M[2] << " " << M[3] << std::endl;
361  std::cout << " " << std::endl;*/
362 
363  inverse_matrixSU2(M, Inv_qu);
364  /*std::cout << "inverse_matrixSU(2)" << std::endl;
365  std::cout << "Inversa " << Inv_qu[0] << " " << Inv_qu[1] << " " << Inv_qu[2] << " " << Inv_qu[3] << std::endl;
366  std::cout << " " << std::endl;*/
367 
368  quaternion2Paulibasis(rott, tiltt, psit, qt);
369  /*std::cout << "quaternion2Pauli" << std::endl;
370  std::cout << "Tilted " << qt[0] << " " << qt[1] << " " << qt[2] << " " << qt[3] << std::endl;
371  std::cout << " " << std::endl;*/
372 
373  InversefromPaulibasis(qu,Inv_quu);
374 
375  Pauliproduct(qt, Inv_qu, P1);
376  /*std::cout << "Pauliproduct" << std::endl;
377  std::cout << "quaternion qt " << P1[0] << " " << P1[1] << " " << P1[2] << " " << P1[3] << std::endl;
378  std::cout << " " << std::endl;
379  std::cout << "-----------------------------------" << std::endl;*/
380 
381  //double alpha_x, alpha_y;
382  //extrarotationangles(P1, alpha_x, alpha_y);
383  //std::cout << "alpha_x = " << alpha_x << " " << "alpha_y = " << alpha_y << std::endl;
384 }
385 
386 
387 
Rotation angle of an image (double,degrees)
void sort(const MetaDataVec &MDin, const MDLabel sortLabel, bool asc=true, int limit=-1, int offset=0)
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
double beta(const double a, const double b)
void inverse_matrixSU2(std::complex< double > Original[4], std::complex< double >(&Inver)[4])
Inverse of a matrix (expressed in Pauli basis)
Tilting angle of an image (double,degrees)
void extrarotationangles(std::complex< double > R[4], double &alpha_x, double &alpha_y)
Extract angles alpha_x and alpha_y from the transformation matrix.
void Paulibasis2matrix(std::complex< double > P[4], std::complex< double >(&M)[4])
A Pauli span is converted to a 2x2 matrix.
Special label to be used when gathering MDs in MpiMetadataPrograms.
void InversefromPaulibasis(std::complex< double > Original[4], std::complex< double >(&Inver)[4])
Matrix2D< T > transpose() const
Definition: matrix2d.cpp:1314
virtual IdIteratorProxy< false > ids()
#define i
Unique identifier for items inside a list or set (std::size_t)
void quaternion2Paulibasis(double rot, double tilt, double psi, std::complex< double >(&L)[4])
Transform a set of angles/orientations to a matrix expressed in Pauli basis.
const char * getParam(const char *param, int arg=0)
#define XX(v)
Definition: matrix1d.h:85
bool setValue(const MDObject &mdValueIn, size_t id)
Flip the image? (bool)
void Euler_mirrorX(double rot, double tilt, double psi, double &newrot, double &newtilt, double &newpsi)
Definition: geometry.cpp:1020
void readParams()
Read parameters from the command line.
void defineParams()
Define parameters in the command line.
double z
void Pauliproduct(std::complex< double > A[4], std::complex< double > B[4], std::complex< double >(&P)[4])
It calculates the product of two matrix expressed in Pauli matrices by their matrix elements A an B...
#define j
difference between two angles (double,degrees)
#define YY(v)
Definition: matrix1d.h:93
bool getValue(MDObject &mdValueOut, size_t id) const override
void angles2tranformation(double untilt_angles[3], double tilt_angles[3], double alpha_x, double alpha_y)
It takes two sets of angles (rotu, tiltu, psiu) which define Eu, and (rott, tiltt, psit) which define Et,.
double psi(const double x)
void Euler_matrix2angles(const Matrix2D< double > &A, double &alpha, double &beta, double &gamma, bool homogeneous)
Definition: geometry.cpp:839
void matrix2Paulibasis(std::complex< double > M[4], std::complex< double >(&P)[4])
It takes a 2x2 matrix (where M[0] = m11; M[1]=m12; M[2]=m21; M[3]=m22) and express the matrix M...
void addUsageLine(const char *line, bool verbatim=false)
#define PI
Definition: tools.h:43
#define ZZ(v)
Definition: matrix1d.h:101
void addParamsLine(const String &line)
void run()
Execute de program.