Xmipp  v3.23.11-Nereus
directions.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Sjors Scheres scheres@cnb.csic.es (2004)
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 
26 #include "directions.h"
27 #include "core/geometry.h"
28 #include "core/metadata_sql.h"
29 
30 // Check whether projection directions are unique =================================
31 bool directions_are_unique(double rot, double tilt,
32  double rot2, double tilt2,
33  double rot_limit, double tilt_limit,
34  SymList &SL, bool include_mirrors,
36 {
37  bool are_unique = true;
38  double rot2p, tilt2p, psi2p, psi2 = 0.;
39  double diff_rot, diff_tilt;
40 
41  int isymmax=SL.symsNo();
42  for (int isym = 0; isym <= isymmax; isym++)
43  {
44  if (isym == 0)
45  {
46  rot2p = rot2;
47  tilt2p = tilt2;
48  psi2p = psi2;
49  }
50  else
51  {
52  SL.getMatrices(isym - 1, Laux, Raux,false);
53  Euler_apply_transf(Laux, Raux, rot2, tilt2, psi2, rot2p, tilt2p, psi2p);
54  }
55 
56  double aux=rot - rot2p;
57  diff_rot = fabs(realWRAP(aux, -180, 180));
58  aux=tilt - tilt2p;
59  diff_tilt = fabs(realWRAP(aux, -180, 180));
60  if ((rot_limit - diff_rot) > 1e-3 && (tilt_limit - diff_tilt) > 1e-3)
61  are_unique = false;
62  Euler_another_set(rot2p, tilt2p, psi2p, rot2p, tilt2p, psi2p);
63  aux=rot - rot2p;
64  diff_rot = fabs(realWRAP(aux, -180, 180));
65  aux=tilt - tilt2p;
66  diff_tilt = fabs(realWRAP(aux, -180, 180));
67  if ((rot_limit - diff_rot) > 1e-3 && (tilt_limit - diff_tilt) > 1e-3)
68  are_unique = false;
69  if (!include_mirrors)
70  {
71  Euler_up_down(rot2p, tilt2p, psi2p, rot2p, tilt2p, psi2p);
72  aux=rot - rot2p;
73  diff_rot = fabs(realWRAP(aux, -180, 180));
74  aux=tilt - tilt2p;
75  diff_tilt = fabs(realWRAP(aux, -180, 180));
76  if ((rot_limit - diff_rot) > 1e-3 && (tilt_limit - diff_tilt) > 1e-3)
77  are_unique = false;
78  Euler_another_set(rot2p, tilt2p, psi2p, rot2p, tilt2p, psi2p);
79  aux=rot - rot2p;
80  diff_rot = fabs(realWRAP(aux, -180, 180));
81  aux=tilt - tilt2p;
82  diff_tilt = fabs(realWRAP(aux, -180, 180));
83  if ((rot_limit - diff_rot) > 1e-3 && (tilt_limit - diff_tilt) > 1e-3)
84  are_unique = false;
85  }
86  }
87 
88  return are_unique;
89 }
90 
91 double distance_directions(double rot1, double tilt1,
92  double rot2, double tilt2,
93  bool include_mirrors)
94 {
95 
96  double rot2p, tilt2p, psi2p, dist;
97  double diff_rot, diff_tilt;
98 
99  double aux=rot1 - rot2;
100  diff_rot = fabs(realWRAP(aux, -180, 180));
101  aux=tilt1 - tilt2;
102  diff_tilt = fabs(realWRAP(aux, -180, 180));
103  dist = sqrt((diff_rot * diff_rot) + (diff_tilt * diff_tilt));
104 
105  Euler_another_set(rot2, tilt2, 0., rot2p, tilt2p, psi2p);
106  aux=rot1 - rot2p;
107  diff_rot = fabs(realWRAP(aux, -180, 180));
108  aux=tilt1 - tilt2p;
109  diff_tilt = fabs(realWRAP(aux, -180, 180));
110  dist = fmin(dist, sqrt((diff_rot * diff_rot) + (diff_tilt * diff_tilt)));
111 
112  if (include_mirrors)
113  {
114  Euler_up_down(rot2, tilt2, 0., rot2p, tilt2p, psi2p);
115  aux=rot1 - rot2p;
116  diff_rot = fabs(realWRAP(aux, -180, 180));
117  aux=tilt1 - tilt2p;
118  diff_tilt = fabs(realWRAP(aux, -180, 180));
119  dist = fmin(dist, sqrt((diff_rot * diff_rot) + (diff_tilt * diff_tilt)));
120 
121  Euler_another_set(rot2p, tilt2p, 0., rot2p, tilt2p, psi2p);
122  aux=rot1 - rot2p;
123  diff_rot = fabs(realWRAP(aux, -180, 180));
124  aux=tilt1 - tilt2p;
125  diff_tilt = fabs(realWRAP(aux, -180, 180));
126  dist = fmin(dist, sqrt((diff_rot * diff_rot) + (diff_tilt * diff_tilt)));
127  }
128 
129  return dist;
130 
131 }
132 // Fill DF with evenly distributed rot & tilt =================================
133 void make_even_distribution(std::vector<double> &rotList, std::vector<double> &tiltList,
134  double sampling, SymList &SL, bool include_mirror)
135 {
136  int rot_nstep, tilt_nstep = ROUND(180. / sampling) + 1;
137  double rot_sam, tilt, tilt_sam;
138  bool append;
139  tilt_sam = (180. / tilt_nstep);
140 
141  // Create evenly distributed angles
142  rotList.clear();
143  tiltList.clear();
144  rotList.reserve(20000); // Normally there are many less directions than 20000
145  tiltList.reserve(20000); // Set to 20000 to avoid resizing
146  Matrix2D<double> L(3,3),R(3,3);
147  for (int tilt_step = 0; tilt_step < tilt_nstep; tilt_step++)
148  {
149  tilt = ((double)tilt_step / (tilt_nstep - 1)) * 180.;
150  if (tilt > 0)
151  rot_nstep = CEIL(360. * sin(DEG2RAD(tilt)) / sampling);
152  else
153  rot_nstep = 1;
154  rot_sam = 360. / (double)rot_nstep;
155  for (double rot = 0.; rot < 360.; rot += rot_sam)
156  {
157  // Check whether by symmetry or mirror the angle has been included already
158  append = true;
159  size_t imax=rotList.size();
160  double *ptrRot=nullptr;
161  double *ptrTilt=nullptr;
162  if (imax>0)
163  {
164  ptrRot=&rotList[0];
165  ptrTilt=&tiltList[0];
166  }
167  for (size_t i=0; i<imax; ++i, ++ptrRot, ++ptrTilt)
168  {
169  if (!directions_are_unique(rot, tilt, *ptrRot, *ptrTilt, rot_sam, tilt_sam, SL,
170  include_mirror, L, R))
171  {
172  append = false;
173  break;
174  }
175  }
176  if (append)
177  {
178  rotList.push_back(rot);
179  tiltList.push_back(tilt);
180  }
181  }
182  }
183 }
184 
185 void limit_tilt_range(MetaDataVec &DF, double tilt_range0, double tilt_rangeF)
186 {
187 
188  MetaDataVec DFaux;
189  DFaux.importObjects(DF, MDValueRange(MDL_ANGLE_TILT, tilt_range0, tilt_rangeF));
190  DF = DFaux;
191 }
192 
193 
194 int find_nearest_direction(double rot1, double tilt1,
195  std::vector<double> &rotList, std::vector<double> &tiltList,
196  SymList &SL, Matrix2D<double> &Laux, Matrix2D<double> &Raux)
197 {
198 
199  int optdir;
200  double dist, mindist;
201  double newrot, newtilt, newpsi;
202 
203  optdir = -1;
204  mindist = 9999.;
205  int imax=SL.symsNo();
206  size_t nmax=rotList.size();
207  double *ptrRot=nullptr;
208  double *ptrTilt=nullptr;
209  if (nmax>0)
210  {
211  ptrRot=&rotList[0];
212  ptrTilt=&tiltList[0];
213  }
214  for (size_t n=0; n<nmax; ++n, ++ptrRot, ++ptrTilt)
215  {
216  dist = distance_directions(rot1, tilt1, *ptrRot, *ptrTilt, false);
217  if (dist < mindist)
218  {
219  mindist = dist;
220  optdir = n;
221  }
222 
223  for (int i = 0; i < imax; i++)
224  {
225  SL.getMatrices(i, Laux, Raux, false);
226  Euler_apply_transf(Laux, Raux, rot1, tilt1, 0., newrot, newtilt, newpsi);
227  dist = distance_directions(newrot, newtilt, *ptrRot, *ptrTilt, false);
228  if (dist < mindist)
229  {
230  mindist = dist;
231  optdir = n;
232  }
233  }
234  }
235 
236  return optdir;
237 }
238 
int * nmax
void getMatrices(int i, Matrix2D< double > &L, Matrix2D< double > &R, bool homogeneous=true) const
Definition: symmetries.cpp:348
#define DEG2RAD(d)
Definition: xmipp_macros.h:312
void make_even_distribution(std::vector< double > &rotList, std::vector< double > &tiltList, double sampling, SymList &SL, bool include_mirror)
Make even distribution, taking symmetry into account.
Definition: directions.cpp:133
void Euler_another_set(double rot, double tilt, double psi, double &newrot, double &newtilt, double &newpsi)
Definition: geometry.cpp:1002
void sqrt(Image< double > &op)
Tilting angle of an image (double,degrees)
int symsNo() const
Definition: symmetries.h:268
void Euler_apply_transf(const Matrix2D< double > &L, const Matrix2D< double > &R, double rot, double tilt, double psi, double &newrot, double &newtilt, double &newpsi)
Definition: geometry.cpp:1038
#define i
void limit_tilt_range(MetaDataVec &DF, double tilt_range0, double tilt_rangeF)
Select a user-provided tilt range.
Definition: directions.cpp:185
int find_nearest_direction(double rot1, double tilt1, std::vector< double > &rotList, std::vector< double > &tiltList, SymList &SL, Matrix2D< double > &Laux, Matrix2D< double > &Raux)
Determine which of the entries in DFlib is closest to [rot1,tilt1].
Definition: directions.cpp:194
#define CEIL(x)
Definition: xmipp_macros.h:225
void importObjects(const MetaData &md, const std::vector< size_t > &objectsToAdd, bool doClear=true) override
#define sampling
void Euler_up_down(double rot, double tilt, double psi, double &newrot, double &newtilt, double &newpsi)
Definition: geometry.cpp:993
double distance_directions(double rot1, double tilt1, double rot2, double tilt2, bool include_mirrors)
Calculate angular distance between two directions.
Definition: directions.cpp:91
#define ROUND(x)
Definition: xmipp_macros.h:210
#define realWRAP(x, x0, xF)
Definition: xmipp_macros.h:304
int * n
bool directions_are_unique(double rot, double tilt, double rot2, double tilt2, double rot_limit, double tilt_limit, SymList &SL, bool include_mirrors, Matrix2D< double > &Laux, Matrix2D< double > &Raux)
Check whether projection directions are unique.
Definition: directions.cpp:31