Xmipp  v3.23.11-Nereus
Functions
frm.cpp File Reference
#include "frm.h"
#include <core/geometry.h>
#include <core/transformations.h>
Include dependency graph for frm.cpp:

Go to the source code of this file.

Functions

void alignVolumesFRM (PyObject *pFunc, const MultidimArray< double > &Iref, MultidimArray< double > &I, PyObject *Imask, double &rot, double &tilt, double &psi, double &x, double &y, double &z, double &score, Matrix2D< double > &A, int maxshift, double maxFreq, const MultidimArray< int > *mask)
 

Function Documentation

◆ alignVolumesFRM()

void alignVolumesFRM ( PyObject *  pFunc,
const MultidimArray< double > &  Iref,
MultidimArray< double > &  I,
PyObject *  Imask,
double &  rot,
double &  tilt,
double &  psi,
double &  x,
double &  y,
double &  z,
double &  score,
Matrix2D< double > &  A,
int  maxshift = 10,
double  maxFreq = 0.25,
const MultidimArray< int > *  mask = nullptr 
)

Align two volumes using FRM. The first argument is the pointer to the FRM python function. You may obtain it with getPointerToPythonFRMFunction()

Imask is a mask in Fourier space for I Maxshift is in pixels. MaxFreq is in digital frequency.

A is the transformation matrix that needs to be applied on I to fit Iref.

If apply is set, then I is substituted with the aligned volume.

Definition at line 35 of file frm.cpp.

40 {
41  PyObject *pyIref = Python::convertToNumpy(Iref);
42  PyObject *pyI = Python::convertToNumpy(I);
43  PyObject *pyMask=Py_None;
44  if (mask!=nullptr)
45  pyMask=Python::convertToNumpy(*mask);
46 
47 //#define DEBUG
48 #ifdef DEBUG
49  Image<double> save;
50  save()=I;
51  save.write("PPPI.vol");
52  save()=Iref;
53  save.write("PPPIref.vol");
54  std::cout << "Imask=" << Imask << std::endl;
55  std::cout << "Press any key\n";
56  char c; std::cin >> c;
57 #endif
58 
59  // Call frm
60  int bandWidthSphericalHarmonics0=4;
61  int bandWidthSphericalHarmonicsF=64;
62  auto frequencyPixels=(int)(XSIZE(Iref)*maxFreq);
63  PyObject *arglistfrm = Py_BuildValue("OOOO(ii)iiO", pyI, Imask, pyIref, Py_None,
64  bandWidthSphericalHarmonics0, bandWidthSphericalHarmonicsF, frequencyPixels, maxshift, pyMask);
65  PyObject *resultfrm = PyObject_CallObject(pFunc, arglistfrm);
66  Py_DECREF(arglistfrm);
67  Py_DECREF(pyIref);
68  Py_DECREF(pyI);
69  if (mask!=nullptr)
70  Py_DECREF(pyMask);
71  if (resultfrm!=nullptr)
72  {
73  PyObject *shift=PyTuple_GetItem(resultfrm,0);
74  PyObject *euler=PyTuple_GetItem(resultfrm,1);
75  score=PyFloat_AsDouble(PyTuple_GetItem(resultfrm,2));
76  double xfrm=PyFloat_AsDouble(PyList_GetItem(shift,0))-XSIZE(Iref)/2;
77  double yfrm=PyFloat_AsDouble(PyList_GetItem(shift,1))-YSIZE(Iref)/2;
78  double zfrm=PyFloat_AsDouble(PyList_GetItem(shift,2))-ZSIZE(Iref)/2;
79  double angz1=PyFloat_AsDouble(PyList_GetItem(euler,0));
80  double angz2=PyFloat_AsDouble(PyList_GetItem(euler,1));
81  double angx=PyFloat_AsDouble(PyList_GetItem(euler,2));
82  Matrix2D<double> Efrm, E(3,3);
83  Euler_anglesZXZ2matrix(-angz1, -angx, -angz2, Efrm); // -angles because FRM rotation definition
84  // is the opposite of Xmipp
85 
86  // Reorganize the matrix because the Z and X axes in the coordinate system are reversed with
87  // respect to Xmipp
88  // Exmipp=[0 0 1; 0 1 0; 1 0 0]*Efrm*[0 0 1; 0 1 0; 1 0 0]
89  MAT_ELEM(E,0,0)=MAT_ELEM(Efrm, 2, 2); MAT_ELEM(E,0,1)=MAT_ELEM(Efrm, 2, 1); MAT_ELEM(E,0,2)=MAT_ELEM(Efrm, 2, 0);
90  MAT_ELEM(E,1,0)=MAT_ELEM(Efrm, 1, 2); MAT_ELEM(E,1,1)=MAT_ELEM(Efrm, 1, 1); MAT_ELEM(E,1,2)=MAT_ELEM(Efrm, 1, 0);
91  MAT_ELEM(E,2,0)=MAT_ELEM(Efrm, 0, 2); MAT_ELEM(E,2,1)=MAT_ELEM(Efrm, 0, 1); MAT_ELEM(E,2,2)=MAT_ELEM(Efrm, 0, 0);
92  E=E.inv();
93  Euler_matrix2angles(E,rot,tilt,psi);
94  Py_DECREF(resultfrm);
95 
96  x=-zfrm;
97  y=-yfrm;
98  z=-xfrm;
99 
100  // Apply
101  Euler_angles2matrix(rot, tilt, psi, A, true);
102  Matrix2D<double> Aaux;
103  Matrix1D<double> r(3);
104  XX(r)=x;
105  YY(r)=y;
106  ZZ(r)=z;
107  translation3DMatrix(r,Aaux);
108  A=A*Aaux;
109 #ifdef DEBUG
110  std::cout << "Result: " << rot << " " << tilt << " " << psi << " " << x << " " << y << " " << z << " -> " << score << std::endl;
111 #endif
112  }
113  else
114  {
115  x=y=z=rot=tilt=psi=score=0;
116  A.initIdentity(4);
117 
118  std::cout << "No result\n";
119  std::cout << Python::print_traceback();
120  }
121 }
#define YSIZE(v)
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
doublereal * c
static double * y
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)
doublereal * x
#define MAT_ELEM(m, i, j)
Definition: matrix2d.h:116
#define XX(v)
Definition: matrix1d.h:85
template void translation3DMatrix(const Matrix1D< float > &translation, Matrix2D< float > &resMatrix, bool inverse)
#define XSIZE(v)
#define ZSIZE(v)
double z
#define YY(v)
Definition: matrix1d.h:93
PyObject * convertToNumpy(const MultidimArray< T > &array)
void Euler_anglesZXZ2matrix(double a, double b, double g, Matrix2D< double > &A, bool homogeneous)
Definition: geometry.cpp:661
double psi(const double x)
void Euler_matrix2angles(const Matrix2D< double > &A, double &alpha, double &beta, double &gamma, bool homogeneous)
Definition: geometry.cpp:839
std::string print_traceback()
#define ZZ(v)
Definition: matrix1d.h:101
void initIdentity()
Definition: matrix2d.h:673