Xmipp  v3.23.11-Nereus
tomo_align_dual_tilt_series.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Authors: Carlos Oscar Sorzano (coss@cnb.csic.es)
3  *
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 
27 #include "data/filters.h"
28 #include "core/xmipp_fftw.h"
29 #include "core/geometry.h"
30 #include "core/transformations.h"
31 #include "core/xmipp_image.h"
32 
33 double wrapperDualAligment(double *p, void *prm)
34 {
35  auto *eprm=(ProgAlignDualTiltSeries *)prm;
36  Matrix1D<double> aux(6);
38  aux(i)=p[i+1];
39  return eprm->evaluateAlignment(aux);
40 }
41 
44 {
45  fnRef=getParam("--ref");
46  fnDual=getParam("--dual");
47  fnOut=getParam("-o");
48  scaleFactor=getDoubleParam("--scale");
49 }
50 
53 {
54  std::cout
55  << "Reference: " << fnRef << std::endl
56  << "Dual: " << fnDual << std::endl
57  << "Output: " << fnOut << std::endl
58  << "Scale: " << scaleFactor << std::endl
59  ;
60 }
61 
64 {
65  addUsageLine("Align two dual tilt series that have been previously internally aligned");
66  addUsageLine("with xmipp_tomo_align_tilt_series");
67  addSeeAlsoLine("tomo_align_tilt_series");
68  addParamsLine(" --ref <selfile> : Reference tilt series");
69  addParamsLine(" : The selfile must contain the list of micrographs");
70  addParamsLine(" : and its tilt angles");
71  addParamsLine(" --dual <selfile> : Dual tilt series");
72  addParamsLine(" [-o <rootname=\"\">] : Rootname for the aligned tilt series");
73  addParamsLine(" : If not given, the dual tilt series+_aligned");
74  addParamsLine(" [--scale <s=0.25>] : Scale for performing the common line comparisons");
75 }
76 
79 {
80  imgDual.clear();
82  int i=0;
84  FileName fnImg;
85  double minAbsTilt=1000;
86  for (size_t objId: SFDual.ids())
87  {
88  SFDual.getValue(MDL_IMAGE,fnImg, objId);
90  if (fabs(tiltDual(i))<minAbsTilt)
91  {
92  minAbsTilt=fabs(tiltDual(i));
93  fnDual0=fnImg;
94  }
95  I.read(fnImg);
97  ROUND(XSIZE(I())*scaleFactor));
98  I().setXmippOrigin();
99  Xdim=XSIZE(I());
100  Ydim=YSIZE(I());
101  imgDual.push_back(I());
102  i++;
103  }
104 }
105 
108 {
109  debugging=false;
110  if (fnOut=="")
111  fnOut=fnDual.withoutExtension()+"_aligned";
112 
113  std::cout << "Reading data...\n";
114  SFRef.read(fnRef);
115  SFDual.read(fnDual);
116 
117  // Read Reference series
119  int i=0;
121  FileName fnImg;
122  double minAbsTilt=1000;
123  for (size_t objId: SFRef.ids())
124  {
125  SFRef.getValue(MDL_IMAGE,fnImg,objId);
127  if (fabs(tiltRef(i))<minAbsTilt)
128  {
129  minAbsTilt=fabs(tiltRef(i));
130  fnRef0=fnImg;
131  }
132  I.read(fnImg);
134  ROUND(XSIZE(I())*scaleFactor));
135  I().setXmippOrigin();
136  imgRef.push_back(I());
137  i++;
138  }
139 
140  // Read Dual series
141  readDual();
142 
143  normali.resize(3);
144  normalj.resize(3);
145  commonline.resize(3);
146  commonlinei.resize(3);
147  commonlinej.resize(3);
148  commonlinejE.resize(3);
149  A.initIdentity(3);
150  int minDim=XMIPP_MIN(Xdim,Ydim);
151  profilei.resize(minDim);
154 }
155 
157 //#define DEBUG
159 {
160  Image<double> Iref, Idual;
161  Iref.read(fnRef0);
162  Idual.read(fnDual0);
163  Iref().setXmippOrigin();
164  Idual().setXmippOrigin();
165  if (rotateDual)
167  Matrix2D<double> M0,M0inv;
168 #ifdef DEBUG
169 
170  Image<double> save;
171  save()=Iref();
172  save.write("PPPref0.xmp");
173  save()=Idual();
174  save.write("PPPdual0.xmp");
175 #endif
176 
177  alignImages(Iref(), Idual(), M0);
178  M0inv=M0.inv();
179 #ifdef DEBUG
180 
181  save()=Idual();
182  save.write("PPPdual0Aligned.xmp");
183  std::cout << "M0\n" << M0 << std::endl;
184  std::cout << "M0inv\n" << M0inv << std::endl;
185  std::cout << "Press any key\n";
186  char c;
187  std::cin >> c;
188 #endif
189 
190  alignment.resize(6);
191  alignment(0)=-RAD2DEG(atan2(M0inv(1,0),M0inv(1,1))); // rot
192  alignment(1)=0; // tilt
193  alignment(2)=0; // psi
194  alignment(3)=-M0inv(0,2)*scaleFactor; // X
195  alignment(4)=-M0inv(1,2)*scaleFactor; // Y
196  alignment(5)=0; // Z
197 
198  /*
199  alignment(0)=90;
200  alignment(3)=-25*scaleFactor; // X
201  alignment(4)= 15*scaleFactor; // Y
202  alignment(5)=5;
203  */
204  if (rotateDual)
205  std::cout << "First estimate (180) of (rot,tilt,psi,x,y,z)=\n"
206  << alignment.transpose() << std::endl;
207  else
208  std::cout << "First estimate (0) of (rot,tilt,psi,x,y,z)=\n"
209  << alignment.transpose() << std::endl;
210  /*
211  debugging=true;
212  */
213 }
214 #undef DEBUG
215 
217 //#define DEBUG
219  int refi, int dualj, const Matrix2D<double> &E,
220  double X, double Y, double Z)
221 {
223 
224  // Compute the direction of the common line in the
225  // universal coordinate system
226  Euler_direction(0, tiltRef(refi), 0, normali);
227  Euler_direction(0, tiltDual(dualj), 0, normalj);
229 
232  return -2;
234 
235  // Compute the direction of the common line in each
236  // of the projection coordinate systems
242 
243  // Compute the angle of the common line in i and j images
244  double angi=-RAD2DEG(atan2(YY(commonlinei),XX(commonlinei)));
245  double angj=-RAD2DEG(atan2(YY(commonlinej),XX(commonlinej)));
246 
247  I=imgRef[refi];
248 #ifdef DEBUG
249  debugging=true;
250  Image<double> save;
251  save()=I;
252  save.write("PPPref.xmp");
253 #endif
254 
255  selfRotate(xmipp_transformation::LINEAR,I, -angi, xmipp_transformation::DONT_WRAP);
259 #ifdef DEBUG
260 
261  save()=I;
262  save.write("PPPrefaligned.xmp");
263 #endif
264 
265  I=imgDual[dualj];
266 #ifdef DEBUG
267 
268  save()=I;
269  save.write("PPPdual.xmp");
270 #endif
271 
272  // Modify Idual according to z
273  shiftProjectionInZ(I, dualj, Z/scaleFactor);
274 
275  // Modify Idual according to x,y,angj
276  // First translation, then rotation
277  double cj=COSD(angj);
278  double sj=SIND(angj);
279  MAT_ELEM(A,0,0)=MAT_ELEM(A,1,1)=cj;
280  MAT_ELEM(A,1,0)=sj;
281  MAT_ELEM(A,0,1)=-sj;
282  MAT_ELEM(A,0,2)=cj*X-sj*Y;
283  MAT_ELEM(A,1,2)=sj*X+cj*Y;
284  selfApplyGeometry(xmipp_transformation::LINEAR, I, A, xmipp_transformation::IS_NOT_INV, xmipp_transformation::DONT_WRAP);
288 #ifdef DEBUG
289 
290  save()=I;
291  save.write("PPPdualAligned.xmp");
292 #endif
293 
294  if (debugging)
295  {
296  std::cout << "refi=" << refi << " dualj=" << dualj << std::endl
297  << " tiltRef=" << tiltRef(refi) << " tiltDual=" << tiltDual(dualj) << std::endl
298  << " normali=" << normali.transpose() << std::endl
299  << " normalj=" << normalj.transpose() << std::endl
300  << " commonline=" << commonline.transpose() << std::endl
301  << " commonlinei=" << commonlinei.transpose() << std::endl
302  << " commonlinejE=" << commonlinejE.transpose() << std::endl
303  << " commonlinej=" << commonlinej.transpose() << std::endl
304  << " angi=" << angi << " angj=" << angj << std::endl
305  << " A\n" << A << std::endl
306  << " corr=" << correlationIndex(profilei,profilej) << std::endl
307  ;
308 
309  profilei.write("PPPi.txt");
310  profilej.write("PPPj.txt");
311 
312  std::cout << "Press any key\n";
313  char c;
314  std::cin >> c;
315  }
317 }
318 #undef DEBUG
319 
322 {
323  Euler_angles2matrix(_alignment(0),_alignment(1),_alignment(2),E);
324  Et=E.transpose();
325  double X=_alignment(3);
326  double Y=_alignment(4);
327  double Z=_alignment(5);
328 
329  int Nref=imgRef.size();
330  int Ndual=imgDual.size();
331  int Ncomparisons=0;
332  double avgDistance=0;
333  for (int nref=0; nref<Nref; nref++)
334  for (int ndual=0; ndual<Ndual; ndual++)
335  {
336  double d=distanceBetweenCommonLines(nref,ndual,E,X,Y,Z);
337  if (d>0)
338  {
339  avgDistance+=d;
340  Ncomparisons++;
341  }
342  }
343  if (Ncomparisons>0)
344  avgDistance/=Ncomparisons;
345  return avgDistance;
346 }
347 
348 //#define DEBUG
350 {
352  steps.resize(alignment);
353  steps.initConstant(1);
354  double fitness;
355  int iter;
356  powellOptimizer(alignment,1,6,&wrapperDualAligment,this,0.01,fitness,
357  iter,steps,true);
358 #ifdef DEBUG
359 
360  debugging=true;
362  debugging=false;
363 #endif
364 
365  return fitness;
366 }
367 #undef DEBUG
368 
371 {
372 /* There might be a problem, the code seemingly working in TomoJ is
373 
374  for(int i=0;i<ts.length;i++){ // ts is an array of tilt series
375  double[] ali=ts[i].getGlobalOrientation(); // I get the
376  alignment computed between the tilt series with common lines
377  if(ali!=null){ // is there an alignment?
378  double cxtmp=ali[3]; //this is the shift of the center of
379  volume original is (0,0,0)
380  double cytmp=ali[4];
381  //Now where will be this center of tilt axis in the volume?
382  DoubleMatrix2D et= TiltSeries.eulerAngles2Matrix(ali[0],
383  ali[1], ali[2]).viewDice(); // I compute the euler angles of the rotation
384  between the tilt series
385  cx[i]=cxtmp*et.getQuick(0,0)+cytmp*et.getQuick(0,1)+width/2;
386  // I compute the new position of the center of the volume + add width/2 for
387  correct indexation of arrays (in Xmipp should not be there)
388 
389  cy[i]=cxtmp*et.getQuick(1,0)+cytmp*et.getQuick(1,1)+height/2;
390 
391 
392  }else{ //there is no alignment so I define it as classical
393  cx[i]=width/2;
394  cy[i]=height/2;
395  }
396  }
397 */
398 
402  shift3D/=scaleFactor;
403  shift2D/=scaleFactor;
404  MetaDataVec SFout;
405  int n=0;
406  //std::cout << "Aligning dual" << std::endl;
407  Image<double> Idual;
408  Matrix2D<double> Edual;
409  FileName fnImg, fn;
410 
411  for (size_t objId : SFDual.ids())
412  {
413  SFDual.getValue(MDL_IMAGE,fnImg,objId);
414  Idual.read(fnImg);
415  Idual().setXmippOrigin();
416  if (rotatedDual)
417  selfRotate(xmipp_transformation::BSPLINE3,Idual(),180,xmipp_transformation::DONT_WRAP);
418  selfTranslate(xmipp_transformation::BSPLINE3,Idual(),shift2D,xmipp_transformation::DONT_WRAP);
419  shiftProjectionInZ(Idual(), n, ZZ(shift3D));
420  Euler_angles2matrix(0., tiltDual(n), 0., Edual);
421  Edual=Edual*E;
422  double rot, tilt, psi;
423  Euler_matrix2angles(Edual, rot, tilt, psi);
424  fn.compose(n+1,fnOut+".stk");
425  Idual.write(fn);
426  size_t id = SFout.addObject();
427  SFout.setValue(MDL_IMAGE, fn, id);
428  SFout.setValue(MDL_ANGLE_ROT, rot, id);
429  SFout.setValue(MDL_ANGLE_TILT, tilt, id);
430  SFout.setValue(MDL_ANGLE_PSI, psi, id);
431  n++;
432  }
433  SFout.write(fnOut.removeDirectories()+".sel");
434 }
435 
438 {
439  produceSideInfo();
440 
441  // Check if there is a rotation of 180 degrees
443  double objective0=evaluateAlignment(alignment);
444  Matrix1D<double> alignmentBackup=alignment;
445 
446  int Ndual=imgDual.size();
447  for (int ndual=0; ndual<Ndual; ndual++)
450  double objective180=evaluateAlignment(alignment);
451  std::cout << "objective0=" << objective0 << " objective180=" << objective180 << std::endl;
452  if (objective0<objective180)
453  {
454  readDual();
455  rotatedDual=false;
456  alignment=alignmentBackup;
457  }
458  else
459  rotatedDual=true;
460 
462  alignDual();
463 }
464 
466 {
467  if (Z==0)
468  return;
469  FourierTransformer transformer;
471  Matrix1D<double> w(3);
472  Matrix1D<int> idx(3);
473  Matrix2D<double> Edual, Edualt;
474  Euler_angles2matrix(0., tiltDual(dualj), 0., Edual);
475  Edualt=Edual.transpose();
476  transformer.FourierTransform(I,Ifft,false);
478  {
480  VECTOR_R2(idx,j,i);
481  FFT_idx2digfreq(I,idx,w);
482  ZZ(w)=0;
483  M3x3_BY_V3x1(w,Edualt,w);
484  double arg=ZZ(w)*Z;
485  A2D_ELEM(Ifft,i,j)*=std::complex<double>(cos(arg),sin(arg));
486  }
487  transformer.inverseFourierTransform();
488 }
void selfApplyGeometry(int Splinedegree, MultidimArray< std::complex< double > > &V1, const Matrix2D< double > &A, bool inv, bool wrap, std::complex< double > outside)
#define VECTOR_R2(v, x, y)
Definition: matrix1d.h:112
Rotation angle of an image (double,degrees)
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
double module() const
Definition: matrix1d.h:983
double distanceBetweenCommonLines(int refi, int dualj, const Matrix2D< double > &E, double X, double Y, double Z)
Distance between a pair of common lines.
double getDoubleParam(const char *param, int arg=0)
double wrapperDualAligment(double *p, void *prm)
FileName fnOut
Aligned tilt series.
void inverseFourierTransform()
Definition: xmipp_fftw.cpp:329
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
double alignImages(const MultidimArray< double > &Iref, const AlignmentTransforms &IrefTransforms, MultidimArray< double > &I, Matrix2D< double > &M, bool wrap, AlignmentAux &aux, CorrelationAux &aux2, RotationalCorrelationAux &aux3)
Definition: filters.cpp:2047
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
doublereal * c
void Euler_direction(double alpha, double beta, double gamma, Matrix1D< double > &v)
Definition: geometry.cpp:721
Tilting angle of an image (double,degrees)
void readParams()
Read parameters from command line.
MultidimArray< double > profilei
Matrix1D< double > vectorR3(double x, double y, double z)
Definition: matrix1d.cpp:892
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
double correlationIndex(const MultidimArray< T > &x, const MultidimArray< T > &y, const MultidimArray< int > *mask=NULL, MultidimArray< double > *Contributions=NULL)
#define A1D_ELEM(v, i)
void readDual()
Read dual series.
void shiftProjectionInZ(MultidimArray< double > &I, int dualj, double Z) const
Shift the projection in Z.
void compose(const String &str, const size_t no, const String &ext="")
FileName removeDirectories(int keep=0) const
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
Special label to be used when gathering MDs in MpiMetadataPrograms.
doublereal * w
void write(const FileName &outFile, WriteModeMetaData mode=MD_OVERWRITE) const
void produceSideInfo()
Produce side info.
void powellOptimizer(Matrix1D< double > &p, int i0, int n, double(*f)(double *x, void *), void *prm, double ftol, double &fret, int &iter, const Matrix1D< double > &steps, bool show)
void selfNormalize()
Definition: matrix1d.cpp:723
Matrix2D< T > transpose() const
Definition: matrix2d.cpp:1314
Matrix1D< T > vectorProduct(const Matrix1D< T > &v1, const Matrix1D< T > &v2)
Definition: matrix1d.h:1165
glob_prnt iter
#define SIND(x)
Definition: xmipp_macros.h:347
virtual IdIteratorProxy< false > ids()
void selfRotate(int SplineDegree, MultidimArray< T > &V1, double ang, char axis='Z', bool wrap=xmipp_transformation::DONT_WRAP, T outside=0)
void FFT_idx2digfreq(T &v, const Matrix1D< int > &idx, Matrix1D< double > &freq)
Definition: xmipp_fft.h:80
std::vector< MultidimArray< double > > imgDual
size_t size() const override
#define i
void selfScaleToSize(int SplineDegree, MultidimArrayGeneric &V1, int Xdim, int Ydim, int Zdim)
doublereal * d
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
void addSeeAlsoLine(const char *seeAlso)
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
#define FOR_ALL_ELEMENTS_IN_MATRIX1D(v)
Definition: matrix1d.h:72
const char * getParam(const char *param, int arg=0)
#define XX(v)
Definition: matrix1d.h:85
MultidimArray< double > tiltDual
void selfTranslate(int SplineDegree, MultidimArray< T > &V1, const Matrix1D< double > &v, bool wrap=xmipp_transformation::WRAP, T outside=0)
bool setValue(const MDObject &mdValueIn, size_t id)
size_t addObject() override
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
#define XSIZE(v)
void write(const FileName &fn) const
#define ROUND(x)
Definition: xmipp_macros.h:210
MultidimArray< double > profilej
Matrix1D< double > vectorR2(double x, double y)
Definition: matrix1d.cpp:884
void FourierTransform(T &v, T1 &V, bool getCopy=true)
Definition: xmipp_fftw.h:166
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define j
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
double steps
#define YY(v)
Definition: matrix1d.h:93
void findParametersAt0degrees(bool rotateDual)
Find parameters (shift+rotation) at 0 degrees.
bool getValue(MDObject &mdValueOut, size_t id) const override
FileName withoutExtension() const
#define RAD2DEG(r)
Definition: xmipp_macros.h:320
double optimizeAlignment()
Optimize current alignment.
double psi(const double x)
void Euler_matrix2angles(const Matrix2D< double > &A, double &alpha, double &beta, double &gamma, bool homogeneous)
Definition: geometry.cpp:839
int read(const FileName &name, DataMode datamode=DATA, size_t select_img=ALL_IMAGES, bool mapData=false, int mode=WRITE_READONLY)
ProgClassifyCL2D * prm
FileName fnRef
Reference tilt series.
void addUsageLine(const char *line, bool verbatim=false)
void initZeros(const MultidimArray< T1 > &op)
#define COSD(x)
Definition: xmipp_macros.h:329
std::vector< MultidimArray< double > > imgRef
void Uproject_to_plane(const Matrix1D< double > &point, const Matrix1D< double > &direction, double distance, Matrix1D< double > &result)
Definition: geometry.cpp:39
void initConstant(T val)
Definition: matrix1d.cpp:83
int * n
Name of an image (std::string)
double fitness(double *p)
#define ZZ(v)
Definition: matrix1d.h:101
void addParamsLine(const String &line)
void initIdentity()
Definition: matrix2d.h:673
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403
double evaluateAlignment(const Matrix1D< double > &_alignment)
Evaluate alignment.
FileName fnDual
Dual tilt series.