Xmipp  v3.23.11-Nereus
project_crystal.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar S. Sorzano (coss@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 
26 #include "project_crystal.h"
27 #include "art_crystal.h"
28 
29 #include <core/args.h>
30 
31 /* Empty constructor ======================================================= */
33 {
34  crystal_Xdim = 0;
35  crystal_Ydim = 0;
36  orthogonal = false;
37  a.clear();
38  b.clear();
39  Nshift_avg = 0;
40  Nshift_dev = 0;
41  disappearing_th = 0;
42  DF_shift_bool = false;
43  DF_shift.clear();
44 }
45 
46 /* Read Crystal Projection Parameters ====================================== */
47 void Crystal_Projection_Parameters::read(const FileName &fn, double scale)
48 {
49  MetaDataVec MD;
50  size_t objId;
51  FileName fn_crystal = fn.removeBlockName();
52  MD.read(formatString("crystal@%s", fn_crystal.c_str()));
53  if (MD.isEmpty())
55  (String)"Prog_Project_Parameters::read: There is a problem "
56  "opening the file " + fn_crystal);
57 
58  std::vector <double> ParamVec;
59  objId = MD.firstRowId();
60  MD.getValue(MDL_DIMENSIONS_2D, ParamVec, objId);
61  crystal_Xdim = (int)ParamVec[0];
62  crystal_Ydim = (int)ParamVec[1];
63  crystal_Xdim = ROUND(scale * crystal_Xdim);
64  crystal_Ydim = ROUND(scale * crystal_Ydim);
65  MD.getValue(MDL_CRYSTAL_LATTICE_A, ParamVec, objId);
66  a.resize(3);
67  XX(a) = scale * ParamVec[0];
68  YY(a) = scale * ParamVec[1];
69  ZZ(a) = 0;
70  MD.getValue(MDL_CRYSTAL_LATTICE_B, ParamVec, objId);
71  b.resize(3);
72  XX(b) = scale * ParamVec[0];
73  YY(b) = scale * ParamVec[1];
74  ZZ(b) = 0;
75  MD.getValue(MDL_CRYSTAL_NOISE_SHIFT,ParamVec, objId);
76  Nshift_dev = scale * ParamVec[0];
77  if (ParamVec.size() < 2)
78  Nshift_avg = 0;
79  else
80  Nshift_avg = scale * ParamVec[1];
83  if (MD.getValue(MDL_CRYSTAL_SHFILE, fn_shift, objId))
84  DF_shift_bool = true;
85  //#define DEBUG
86 #ifdef DEBUG
87 
88  std::cerr << "crystal_Xdim" << crystal_Xdim<<std::endl;
89  std::cerr << "crystal_Ydim" << crystal_Ydim<<std::endl;
90  std::cerr << "a vector" << a <<std::endl;
91  std::cerr << "b vector" << b <<std::endl;
92  std::cerr << "Nshift_devr" << Nshift_dev <<std::endl;
93  std::cerr << "Nshift_avg" << Nshift_avg <<std::endl;
94 #endif
95 #undef DEBUG
96 }
97 
98 /* Write =================================================================== */
100 {
101  if (fn_crystal.isMetaData())
102  {
103  MetaDataVec MD1; //MetaData for crystal projection parameters
104  std::vector<double> FCVect(2); //For the center of feature
105  size_t id;
106  std::vector<double> TVector; //For general use
107  MD1.setColumnFormat(false);
108  id = MD1.addObject();
109  TVector[0] = crystal_Xdim;
110  TVector[1] = crystal_Ydim;
111  MD1.setValue(MDL_DIMENSIONS_2D, TVector, id);
112  TVector[0] = XX(a);
113  TVector[1] = YY(a);
114  MD1.setValue(MDL_CRYSTAL_LATTICE_A, TVector, id);
115  TVector[0] = XX(b);
116  TVector[1] = YY(b);
117  MD1.setValue(MDL_CRYSTAL_LATTICE_B, TVector, id);
118  TVector[0] = Nshift_dev;
119  TVector[1] = Nshift_avg;
120  MD1.setValue(MDL_NOISE_PIXEL_LEVEL, TVector, id);
123  MD1.setValue(MDL_CRYSTAL_SHFILE, fn_shift.c_str(), id);
124  //MD1.write(fn_crystal, MD_OVERWRITE);
125  }
126  else
127  {
128  FILE *fh_param;
129 
130  if ((fh_param = fopen(fn_crystal.c_str(), "w")) == nullptr)
132  (std::string)"Prog_Project_Parameters::write: There is a problem "
133  "opening the file " + fn_crystal + " for output");
134 
135  fprintf(fh_param, "# Crystal dimensions (X, Y)\n");
136  fprintf(fh_param, "%d %d\n", crystal_Xdim, crystal_Ydim);
137  fprintf(fh_param, "# Crystal a lattice vector (X, Y)\n");
138  fprintf(fh_param, "%f %f\n", XX(a), YY(a));
139  fprintf(fh_param, "# Crystal b lattice vector (X, Y)\n");
140  fprintf(fh_param, "%f %f\n", XX(b), YY(b));
141 
142  fprintf(fh_param, "# Noise (and bias) applied to the magnitude shift\n");
143  fprintf(fh_param, "%f ", Nshift_dev);
144  if (Nshift_avg != 0)
145  fprintf(fh_param, "%f \n", Nshift_avg);
146  else
147  fprintf(fh_param, "\n");
148 
149  fprintf(fh_param, "# Disappearing threshold\n");
150  fprintf(fh_param, "%f\n", disappearing_th);
151 
152  fprintf(fh_param, "# Orthogonal Projections\n");
153  if (orthogonal)
154  fprintf(fh_param, "Yes\n");
155  else
156  fprintf(fh_param, "No\n");
157 
158  // fprintf(fh_param,"# Grid relative size\n");
159 
160  fprintf(fh_param, "# File with shifts for each unit cell\n");
161  fprintf(fh_param, "%s", fn_shift.c_str());
162 
163  fclose(fh_param);
164  }
165 }
166 
167 /* Project crystal --------------------------------------------------------- */
168 //#define DEBUG
169 //#define DEBUG_MORE
171  const ParametersProjection &prm,
172  PROJECT_Side_Info &side, const Crystal_Projection_Parameters &prm_crystal,
173  float rot, float tilt, float psi)
174 {
176  //Scale crystal output
177  // int aux_crystal_Ydim = ROUND(prm_crystal.crystal_Ydim
178  // *phantom.phantom_scale);
179  // int aux_crystal_Xdim = ROUND(prm_crystal.crystal_Xdim
180  // *phantom.phantom_scale);
181 
182  // Initialize whole crystal projection
183  P().initZeros(prm_crystal.crystal_Ydim, prm_crystal.crystal_Xdim);
184  P().setXmippOrigin();
185 
186  // Compute lattice vectors in the projection plane
187  P.setAngles(rot, tilt, psi);
188  Matrix1D<double> proja = P.euler * prm_crystal.a;
189  Matrix1D<double> projb = P.euler * prm_crystal.b;
190 
191  // Check if orthogonal projections
192  // (projXdim,0)'=A*aproj
193  // (0,projYdim)'=A*bproj
194  Matrix2D<double> Ainv, A, D, Dinv, AuxMat, Daux;
195  if (prm_crystal.orthogonal)
196  {
197  A.resize(2, 2);
198  // A(0, 0) = YY(projb) * XSIZE(P());
199  // A(0, 1) = -XX(projb) * XSIZE(P());
200  // A(1, 0) = -YY(proja) * YSIZE(P());
201  // A(1, 1) = XX(proja) * YSIZE(P());
202  A(0, 0) = YY(projb) * prm.proj_Xdim;
203  A(0, 1) = -XX(projb) * prm.proj_Xdim;
204  A(1, 0) = -YY(proja) * prm.proj_Ydim;
205  A(1, 1) = XX(proja) * prm.proj_Ydim;
206  double nor = 1 / (XX(proja) * YY(projb) - XX(projb) * YY(proja));
207  M2x2_BY_CT(A, A, nor);
208  A.resize(3, 3);
209  A(2, 2) = 1;
210  A.inv(Ainv);
211  AuxMat.resize(3, 3);
212  //Matrix with crystal vectors
213  // Delta = (a, b) with a and b crystal column vectors
214  AuxMat(0, 0) = XX(prm_crystal.a);
215  AuxMat(0, 1) = YY(prm_crystal.a);
216  AuxMat(0, 2) = 0.;
217  AuxMat(1, 0) = XX(prm_crystal.b);
218  AuxMat(1, 1) = YY(prm_crystal.b);
219  AuxMat(1, 2) = 0.;
220  AuxMat(2, 0) = 0.;
221  AuxMat(2, 1) = 0.;
222  AuxMat(2, 2) = 1.;
223  // Product of Delta(trasposed) and Delta*
224  D.resize(3, 3);
225  D(0, 0) = XSIZE(P());
226  D(0, 1) = 0.;
227  D(0, 2) = 0.;
228  D(1, 0) = 0.;
229  D(1, 1) = YSIZE(P());
230  D(1, 2) = 0.;
231  D(2, 0) = 0.;
232  D(2, 1) = 0.;
233  D(2, 2) = 1.;
234  Daux = D;
235  Daux.inv(D);
236  M3x3_BY_M3x3(D, AuxMat, D);
237  Dinv.resize(3, 3);
238  D.inv(Dinv);
239  }
240  else
241  {
242  A.initIdentity(3);
243  Ainv.initIdentity(3);
244  }
245 
246 //#define DEBUG
247 #ifdef DEBUG
248  std::cout << "P shape ";
249  P().printShape();
250  std::cout << std::endl;
251  std::cout << "P.euler " << P.euler;
252  std::cout << std::endl;
253  std::cout << "rot= " << rot << " tilt= " << tilt << " psi= " << psi << std::endl;
254  std::cout << "a " << prm_crystal.a.transpose() << std::endl;
255  std::cout << "b " << prm_crystal.b.transpose() << std::endl;
256  std::cout << "proja " << proja.transpose() << std::endl;
257  std::cout << "projb " << projb.transpose() << std::endl;
258  std::cout << "proj_Xdim " << prm.proj_Xdim << " proj_Ydim " << prm.proj_Ydim
259  << std::endl;
260  std::cout << "A\n" << A << std::endl;
261  std::cout << "Ainv\n" << Ainv << std::endl;
262  std::cout << "D\n" << D << std::endl;
263  std::cout << "Dinv\n" << Dinv << std::endl;
264 #endif
265 
266  // Compute aproj and bproj in the deformed projection space
267  Matrix1D<double> aprojd = A * proja;
268  Matrix1D<double> bprojd = A * projb;
269 #ifdef DEBUG
270 
271  std::cout << "aprojd " << aprojd.transpose() << std::endl;
272  std::cout << "bprojd " << bprojd.transpose() << std::endl;
273 #endif
274 
275  // Get rid of all unnecessary components
276  Matrix2D<double> A2D = A;
277  A2D.resize(2, 2);
278  proja.resize(2);
279  projb.resize(2);
280  aprojd.resize(2);
281  bprojd.resize(2);
282 
283  // The unit cell projection size as well
284  Matrix1D<double> corner1(2), corner2(2);
285  // First in the compressed space
286  XX(corner1) = FIRST_XMIPP_INDEX(prm.proj_Xdim);
287  YY(corner1) = FIRST_XMIPP_INDEX(prm.proj_Ydim);
288  XX(corner2) = LAST_XMIPP_INDEX(prm.proj_Xdim);
289  YY(corner2) = LAST_XMIPP_INDEX(prm.proj_Ydim);
290  // Now deform
291 #ifdef DEBUG
292 
293  std::cout << "corner1 before deformation " << corner1.transpose() << std::endl;
294  std::cout << "corner2 before deformation " << corner2.transpose() << std::endl;
295 #endif
296 
297  rectangle_enclosing(corner1, corner2, A2D, corner1, corner2);
298 #ifdef DEBUG
299 
300  std::cout << "corner1 after deformation " << corner1.transpose() << std::endl;
301  std::cout << "corner2 after deformation " << corner2.transpose() << std::endl;
302 #endif
303 
304  MultidimArray<double> cell_shiftX, cell_shiftY, cell_shiftZ;
305  MultidimArray<int> cell_inside;
306  MultidimArray<double> exp_shifts_matrix_X;
307  MultidimArray<double> exp_shifts_matrix_Y;
308  MultidimArray<double> exp_shifts_matrix_Z;
309  MultidimArray<double> exp_normal_shifts_matrix_X;
310  MultidimArray<double> exp_normal_shifts_matrix_Y;
311  MultidimArray<double> exp_normal_shifts_matrix_Z;
312 
313  fill_cell_positions(P, proja, projb, aprojd, bprojd, corner1, corner2,
314  prm_crystal, cell_shiftX, cell_shiftY, cell_shiftZ, cell_inside,
315  exp_shifts_matrix_X, exp_shifts_matrix_Y, exp_shifts_matrix_Z);
316 
317  // Fill a table with all exp shifts
318  init_shift_matrix(prm_crystal, cell_inside, exp_shifts_matrix_X,
319  exp_shifts_matrix_Y,
320  exp_shifts_matrix_Z,
321  exp_normal_shifts_matrix_X,
322  exp_normal_shifts_matrix_Y,
323  exp_normal_shifts_matrix_Z,
324  phantom.phantom_scale);
325 
326  //std::cout << "prm_crystal : " << prm_crystal. << std::endl;
327  //#define DEBUG
328 #ifdef DEBUG
329  std::cout << "prm_crystal ";
330  std::cout << std::endl;
331  std::cout << "prm_crystal" << prm_crystal.DF_shift << std::endl;
332  std::cout << "prm_crystal" << prm_crystal.DF_shift_bool << std::endl;
333 
334 #endif
335 #undef DEBUG
336 
337  // Prepare matrices to go from uncompressed space to deformed projection
338  Matrix2D<double> AE = A * P.euler; // From uncompressed to deformed
339  Matrix2D<double> AEinv = AE.inv(); // From deformed to uncompressed
340  // add the shifts to the already compute values
341  Matrix1D<double> temp_vect(3);
342 
343  FOR_ALL_ELEMENTS_IN_ARRAY2D(exp_shifts_matrix_X)
344  {
345  //these experimental shift are in phantom
346  //coordinates, not into the projection
347  //plane, so before adding them we need to project
348  temp_vect = AE * vectorR3(exp_shifts_matrix_X(i, j),
349  exp_shifts_matrix_Y(i, j),
350  exp_shifts_matrix_Z(i, j));
351  //#define DEBUG5
352 #ifdef DEBUG5
353 
354  if (i > 0)
355  exp_shifts_matrix_Z(i, j) = 65;
356  else
357  exp_shifts_matrix_Z(i, j) = 0;
358  temp_vect = AE * vectorR3(exp_shifts_matrix_X(i, j),
359  exp_shifts_matrix_Y(i, j),
360  exp_shifts_matrix_Z(i, j));
361 #endif
362 #undef DEBUG5
363 
364  // Add experimental shiftsy
365  cell_shiftX(i, j) += XX(temp_vect);
366  cell_shiftY(i, j) += YY(temp_vect);
367  //entiendo que x e y deban estar en el plano de la proyeccion
368  //pero Z!!!!!!!!!!!!!!!!!!!
369  cell_shiftZ(i, j) += ZZ(temp_vect);
370  }
371  //#define DEBUG
372 #ifdef DEBUG
373  std::cout << "Cell inside shape ";
374  cell_inside.printShape();
375  std::cout << std::endl;
376  std::cout << "Cell inside\n" << cell_inside << std::endl;
377  std::cout << "Cell shiftX\n" << cell_shiftX << std::endl;
378  std::cout << "Cell shiftY\n" << cell_shiftY << std::endl;
379  std::cout << "Cell shiftZ\n" << cell_shiftZ << std::endl;
380 #endif
381  #undef DEBUG
382 
383  double density_factor = 1.0;
384  if (prm_crystal.orthogonal)
385  {
386  // Remember to compute de density factor
387  Matrix1D<double> projection_direction(3);
388  (P.euler).getCol(2, projection_direction);
389  projection_direction.selfTranspose();
390  density_factor = (projection_direction * Dinv).module();
391 #ifdef DEBUG
392 
393  std::cout << "projection_direction" << projection_direction << std::endl;
394  std::cout << "projection_direction*A" << projection_direction*A << std::endl;
395 #endif
396 
397  }
398 #ifdef DEBUG
399  std::cout << "X proyectado=" << (AE*vectorR3(1.0, 0.0, 0.0)).transpose() << std::endl;
400  std::cout << "Y proyectado=" << (AE*vectorR3(0.0, 1.0, 0.0)).transpose() << std::endl;
401  std::cout << "P.euler_shape=" << std::endl;
402  std::cout << P.euler << std::endl;
403  std::cout << "P.euler=" << P.euler << std::endl;
404  std::cout << "AE=" << AE << std::endl;
405  std::cout << "AEinv=" << AEinv << std::endl;
406  std::cout << "Ainv=" << Ainv << std::endl;
407  std::cout << "density_factor=" << density_factor << std::endl;
408 #endif
409 
410  // Project all cells
411  FOR_ALL_ELEMENTS_IN_ARRAY2D(cell_inside)
412  // if (cell_inside(i,j) && rnd_unif(0,1)<prm_crystal.disappearing_th) {
413  if (cell_inside(i, j))
414  {
415  // Shift the phantom
416  // Remind that displacements are defined in the deformed projection
417  // that is why they have to be translated to the Universal
418  // coordinate system
419  Matrix1D<double> cell_shift(3);
420  VECTOR_R3(cell_shift, cell_shiftX(i, j), cell_shiftY(i, j), cell_shiftZ(i, j));
421  //SHIFT still pending
422  //cell_shift = cell_shift*phantom.phantom_scale;
423 #ifdef DEBUG
424 
425  std::cout << "cell_shift on deformed projection plane "
426  << cell_shift.transpose() << std::endl;
427 #endif
428 
429  M3x3_BY_V3x1(cell_shift, AEinv, cell_shift);
430 #ifdef DEBUG
431 
432  std::cout << "cell_shift on real space "
433  << cell_shift.transpose() << std::endl;
434 #endif
435 
436  Phantom aux;
437  aux = phantom;
438  // Now the cell shift is defined in the uncompressed space
439  // Any phantom in the projection line will give the same shift
440  // in the projection we are interested in the phantom whose center
441  // is in the XYplane
442 
443 
444  // the phantom is mapped into a surface of different shapes (parabole,cosine, etc)
445  Matrix1D<double> normal_vector(3);
446  double alpha, beta, gamma;
447  Matrix2D<double> angles_matrix, inverse_angles_matrix;
448  Matrix2D<double> def_cyl_angles_matrix;
449  Matrix2D<double> cyl_angles_matrix;
450 
451  // the phantom is rotated only when there exists a shifts file
452  if (prm_crystal.DF_shift_bool)
453  {
454  // for each (h,k) calculate the normal vector and its corresponding rotation matrix
455  normal_vector(0) = exp_normal_shifts_matrix_X(i, j);
456  normal_vector(1) = exp_normal_shifts_matrix_Y(i, j);
457  normal_vector(2) = exp_normal_shifts_matrix_Z(i, j);
458 
459  Euler_direction2angles(normal_vector, alpha, beta, gamma);
460  gamma = -alpha;
461  Euler_angles2matrix(alpha, beta, gamma, angles_matrix);
462  inverse_angles_matrix = angles_matrix.inv();
463 
464  for (size_t ii = 0; ii < aux.VF.size(); ii++)
465  aux.VF[ii]->rotate(angles_matrix);
466  }
467 
468  cell_shift = cell_shift - ZZ(cell_shift) / ZZ(P.direction) * P.direction;
469 #ifdef DEBUG
470 
471  std::cout << "cell_shift after moving to ground "
472  << cell_shift.transpose() << std::endl;
473 #endif
474 
475  aux.shift(XX(cell_shift), YY(cell_shift), ZZ(cell_shift));
476 
477  // Project this phantom
478  aux.project_to(P, AE, prm_crystal.disappearing_th);
479  // Multiply by factor
480 
481  P() = P() * density_factor;
482 #ifdef DEBUG_MORE
483 
484  std::cout << "After Projecting ...\n" << aux << std::endl;
485  P.write("inter");
486  std::cout << "Hit any key\n";
487  char c;
488  std::cin >> c;
489 #endif
490 
491  }
492 
493 }
494 #undef DEBUG
495 #undef DEBUG_MORE
496 
497 /* Find crystal limits ----------------------------------------------------- */
498 constexpr double MIN_MODULE = 1e-2;
500  const Matrix1D<double> &proj_corner1, const Matrix1D<double> &proj_corner2,
501  const Matrix1D<double> &cell_corner1, const Matrix1D<double> &cell_corner2,
502  const Matrix1D<double> &a, const Matrix1D<double> &b,
503  int &iamin, int &iamax, int &ibmin, int &ibmax)
504 {
505  if (a.module() < MIN_MODULE || b.module() < MIN_MODULE)
506  REPORT_ERROR(ERR_MATRIX_SIZE, "find_crystal_limits: one of the lattice vectors is "
507  "extremely small");
508 
509  // Compute area to cover
510  double x0 = XX(proj_corner1) + XX(cell_corner1);
511  double y0 = YY(proj_corner1) + YY(cell_corner1);
512  double xF = XX(proj_corner2) + XX(cell_corner2);
513  double yF = YY(proj_corner2) + YY(cell_corner2);
514 
515  // Initialize
517  Matrix2D<double> A(2, 2), Ainv(2, 2);
518  A.setCol(0, a);
519  A.setCol(1, b);
520  M2x2_INV(Ainv, A);
521  //#define DEBUG
522 #ifdef DEBUG
523 
524  std::cerr << "A" << A <<std::endl;
525  std::cerr << "Ainv" << Ainv <<std::endl;
526 #endif
527 #undef DEBUG
528 
529  // Now express each corner in the a,b coordinate system
530  Matrix1D<double> r(2);
531  VECTOR_R2(r, x0, y0);
532  //#define DEBUG
533 #ifdef DEBUG
534 
535  std::cerr << "r" << r <<std::endl;
536 #endif
537 #undef DEBUG
538 
539  M2x2_BY_V2x1(r, Ainv, r);
540  iamin = FLOOR(XX(r));
541  iamax = CEIL(XX(r));
542  ibmin = FLOOR(YY(r));
543  ibmax = CEIL(YY(r));
544  //#define DEBUG
545 #ifdef DEBUG
546 
547  std::cerr << "r" << r <<std::endl;
548  std::cerr << "Ainv" << Ainv <<std::endl;
549  std::cerr << "iamin" << iamin <<std::endl;
550  std::cerr << "iamax" << iamax <<std::endl;
551  std::cerr << "ibmin" << ibmin <<std::endl;
552  std::cerr << "ibmax" << ibmax <<std::endl;
553 #endif
554 #undef DEBUG
555 
556 #define CHANGE_COORDS_AND_CHOOSE_CORNERS2D \
557  M2x2_BY_V2x1(r,Ainv,r); \
558  iamin=XMIPP_MIN(FLOOR(XX(r)),iamin); iamax=XMIPP_MAX(CEIL(XX(r)),iamax); \
559  ibmin=XMIPP_MIN(FLOOR(YY(r)),ibmin); ibmax=XMIPP_MAX(CEIL(YY(r)),ibmax);
560 
561  VECTOR_R2(r, x0, yF);
563  VECTOR_R2(r, xF, y0);
565  VECTOR_R2(r, xF, yF);
567 }
568 
569 /* Move following spiral --------------------------------------------------- */
570 /* Given a cell, we study the cells in the inmidiate surrounding, this gives
571  a structure of the like
572 
573  xxx
574  xXx
575  xxx
576 
577  We will mean by . a non-visited cell, by x a visited one and by o the
578  following cell we should visit given this structure. To identify
579  structures we will use the sum of visited cells in rows and columns. The
580  following patterns define the spiral movement:
581 
582  .o.0 ...0 ...0 .xx2 .xx2 xx.2 xo.1 .o.0 ...0
583  .x.1 ox.1 .xx2 .xx2 .xo1 xxo2 xx.2 xx.2 ox.1
584  ...0 .x.1 .ox1 .o.0 ...0 ...0 ...0 xx.2 xx.2 etc
585  010 020 012 022 021 220 210 220 120
586 
587  This function supposes that r is inside the matrix
588 */
590 {
591  int r1 = 0, r2 = 0, r3 = 0, c1 = 0, c2 = 0, c3 = 0;
592 
593 #define x0 STARTINGX(visited)
594 #define y0 STARTINGY(visited)
595 #define xF FINISHINGX(visited)
596 #define yF FINISHINGY(visited)
597 #define i (int)YY(r)
598 #define j (int)XX(r)
599  // Compute row and column sums
600  if (i > y0 && j > x0)
601  {
602  r1 += visited(i - 1, j - 1);
603  c1 += visited(i - 1, j - 1);
604  }
605  if (i > y0)
606  {
607  r1 += visited(i - 1, j);
608  c2 += visited(i - 1, j);
609  }
610  if (i > y0 && j < xF)
611  {
612  r1 += visited(i - 1, j + 1);
613  c3 += visited(i - 1, j + 1);
614  }
615  if (j > x0)
616  {
617  r2 += visited(i , j - 1);
618  c1 += visited(i , j - 1);
619  }
620  r2 += visited(i , j);
621  c2 += visited(i , j);
622  if (j < xF)
623  {
624  r2 += visited(i , j + 1);
625  c3 += visited(i , j + 1);
626  }
627  if (i < yF && j > x0)
628  {
629  r3 += visited(i + 1, j - 1);
630  c1 += visited(i + 1, j - 1);
631  }
632  if (i < yF)
633  {
634  r3 += visited(i + 1, j);
635  c2 += visited(i + 1, j);
636  }
637  if (i < yF && j < xF)
638  {
639  r3 += visited(i + 1, j + 1);
640  c3 += visited(i + 1, j + 1);
641  }
642 
643 #ifdef DEBUG
644  std::cout << r1 << " " << r2 << " " << r3 << " "
645  << c1 << " " << c2 << " " << c3 << std::endl;
646 #endif
647 
648  // Decide where to go
649  if (r1 == 0 && r2 == 1 && r3 == 0 && c1 == 0 && c2 == 1 && c3 == 0)
650  {
651  YY(r)--;
652  }
653  else if (r1 == 0 && r2 == 1 && r3 == 1 && c1 == 0 && c2 == 2 && c3 == 0)
654  {
655  XX(r)--;
656  }
657  else if (r1 == 0 && r2 == 2 && r3 == 1 && c1 == 0 && c2 == 1 && c3 == 2)
658  {
659  YY(r)++;
660  }
661  else if (r1 == 2 && r2 == 2 && r3 == 0 && c1 == 0 && c2 == 2 && c3 == 2)
662  {
663  YY(r)++;
664  }
665  else if (r1 == 2 && r2 == 1 && r3 == 0 && c1 == 0 && c2 == 2 && c3 == 1)
666  {
667  XX(r)++;
668  }
669  else if (r1 == 2 && r2 == 2 && r3 == 0 && c1 == 2 && c2 == 2 && c3 == 0)
670  {
671  XX(r)++;
672  }
673  else if (r1 == 1 && r2 == 2 && r3 == 0 && c1 == 2 && c2 == 1 && c3 == 0)
674  {
675  YY(r)--;
676  }
677  else if (r1 == 0 && r2 == 2 && r3 == 2 && c1 == 2 && c2 == 2 && c3 == 0)
678  {
679  YY(r)--;
680  }
681  else if (r1 == 0 && r2 == 1 && r3 == 2 && c1 == 1 && c2 == 2 && c3 == 0)
682  {
683  XX(r)--;
684  }
685  else if (r1 == 1 && r2 == 2 && r3 == 2 && c1 == 3 && c2 == 2 && c3 == 0)
686  {
687  YY(r)--;
688  }
689  else if (r1 == 0 && r2 == 2 && r3 == 3 && c1 == 1 && c2 == 2 && c3 == 2)
690  {
691  XX(r)--;
692  }
693  else if (r1 == 0 && r2 == 2 && r3 == 2 && c1 == 0 && c2 == 2 && c3 == 2)
694  {
695  XX(r)--;
696  }
697  else if (r1 == 2 && r2 == 2 && r3 == 1 && c1 == 0 && c2 == 2 && c3 == 3)
698  {
699  YY(r)++;
700  }
701  else if (r1 == 3 && r2 == 2 && r3 == 0 && c1 == 2 && c2 == 2 && c3 == 1)
702  {
703  XX(r)++;
704  }
705 }
706 #undef i
707 #undef j
708 #undef x0
709 #undef y0
710 #undef xF
711 #undef yF
712 
713 /* Fill cell rotations and shifts ------------------------------------------ */
714 //#define DEBUG
716  Matrix1D<double> &aproj, Matrix1D<double> &bproj,
717  Matrix1D<double> &aprojd, Matrix1D<double> &bprojd,
718  Matrix1D<double> &corner1, Matrix1D<double> &corner2,
719  const Crystal_Projection_Parameters &prm_crystal,
720  MultidimArray<double> &cell_shiftX,
721  MultidimArray<double> &cell_shiftY,
722  MultidimArray<double> &cell_shiftZ,
723  MultidimArray<int> &cell_inside,
724  MultidimArray<double> &exp_shifts_matrix_X,
725  MultidimArray<double> &exp_shifts_matrix_Y,
726  MultidimArray<double> &exp_shifts_matrix_Z)
727 {
728 
729  // Compute crystal limits
730  int iamin, iamax, ibmin, ibmax;
732  vectorR2(FINISHINGX(P()), FINISHINGY(P())),
733  corner1, corner2, aprojd, bprojd, iamin, iamax, ibmin, ibmax);
734  //#define DEBUG
735 #ifdef DEBUG
736 
737  P().printShape();
738  std::cout << std::endl;
739  std::cout << "aprojd=" << aproj.transpose() << std::endl;
740  std::cout << "bprojd=" << bproj.transpose() << std::endl;
741  std::cout << iamin << " " << iamax << " " << ibmin << " " << ibmax << std::endl;
742 #endif
743 
744  // Compute weight table in the undeformed space
745  MultidimArray<double> weight(3, 3);
746  STARTINGX(weight) = -1;
747  STARTINGY(weight) = -1;
748  weight(0, 0) = 0;
749  weight(-1, 0) = weight(1, 0) = 1 / aproj.module();
750  weight(0, -1) = weight(0, 1) = 1 / bproj.module();
751  weight(-1, 1) = weight(1, -1) = 1 / (aproj - bproj).module();
752  weight(-1, -1) = weight(1, 1) = 1 / (aproj + bproj).module();
753 
754  // Resize all needed matrices
755  cell_shiftX.initZeros(ibmax - ibmin + 1, iamax - iamin + 1);
756  STARTINGX(cell_shiftX) = iamin;
757  STARTINGY(cell_shiftX) = ibmin;
758  cell_shiftY.initZeros(cell_shiftX);
759  //in this routine cell_shiftZ is set to zero and nothing else
760  cell_shiftZ.initZeros(cell_shiftX);
761  cell_inside.initZeros(ibmax - ibmin + 1, iamax - iamin + 1);
762  STARTINGX(cell_inside) = iamin;
763  STARTINGY(cell_inside) = ibmin;
764 
765  // Visited has got one cell more than the rest in all directions
766  MultidimArray<int> visited;
767  int visited_size = XMIPP_MAX(iamax - iamin + 1, ibmax - ibmin + 1) + 2;
768  visited.initZeros(visited_size, visited_size);
769  STARTINGX(visited) = iamin - (visited_size - (iamax - iamin + 1) + 1) / 2;
770  STARTINGY(visited) = ibmin - (visited_size - (ibmax - ibmin + 1) + 1) / 2;
771 #ifdef DEBUG
772 
773  std::cout << "weight=" << weight;
774  std::cout << "cell_shiftX shape ";
775  cell_shiftX.printShape();
776  std::cout << std::endl;
777  std::cout << "cell_inside shape ";
778  cell_inside.printShape();
779  std::cout << std::endl;
780  std::cout << "visited shape ";
781  visited.printShape();
782  std::cout << std::endl;
783 #endif
784 
785  // Perform the crystal deformation starting in the middle of the
786  // crystal and going in spirals until the four corners are visited
787  // we find one corner
788  Matrix1D<double> r(2), ri(2), sh(2);
789  r.initZeros();
790 #define INDEX(r) (int)YY(r),(int)XX(r)
791 
792  while (!visited.isCorner(r))
793  {
794  visited(INDEX(r)) = true;
795 #ifdef DEBUG
796 
797  std::cout << " Visiting " << r.transpose() << std::endl;
798 #endif
799 
800  // Weight is computed in the undeformed space
801  double total_weight = 0;
802  double total_shiftX = 0;
803  double total_shiftY = 0;
804  for (YY(sh) = -1; YY(sh) <= 1; YY(sh)++)
805  for (XX(sh) = -1; XX(sh) <= 1; XX(sh)++)
806  {
807  V2_PLUS_V2(ri, r, sh);
808  if (!cell_shiftX.outside(ri))
809  {
810  total_weight += weight(INDEX(sh));
811  total_shiftX += weight(INDEX(sh)) * cell_shiftX(INDEX(ri));
812  total_shiftY += weight(INDEX(sh)) * cell_shiftY(INDEX(ri));
813  }
814  }
815  if (total_weight == 0)
816  total_weight = 1;
817  if (!cell_shiftX.outside(r))
818  {
819  cell_shiftX(INDEX(r)) = rnd_gaus(prm_crystal.Nshift_avg,
820  prm_crystal.Nshift_dev) + total_shiftX / total_weight;
821  cell_shiftY(INDEX(r)) = rnd_gaus(prm_crystal.Nshift_avg,
822  prm_crystal.Nshift_dev) + total_shiftY / total_weight;
823  }
824 
825  // Move to next position
826  move_following_spiral(r, visited);
827  }
828 
829 #ifdef DEBUG
830  std::cout << "Cell shift X without absolute displacements" << cell_shiftX;
831  std::cout << "Cell shift Y without absolute displacements" << cell_shiftY;
832 #endif
833 
834  // The previous shifts are relative to the final position, now
835  // express the real final position
836 
838  {
839  if (!cell_shiftX.outside(i, j))
840  {
841  // Move to final position
842  cell_shiftX(i, j) += j * XX(aprojd) + i * XX(bprojd);
843  cell_shiftY(i, j) += j * YY(aprojd) + i * YY(bprojd);
844 
845  // Check if there is intersection
846  Matrix1D<double> auxcorner1(2), auxcorner2(2);
847  XX(auxcorner1) = XX(corner1) + cell_shiftX(i, j);
848  YY(auxcorner1) = YY(corner1) + cell_shiftY(i, j);
849  XX(auxcorner2) = XX(corner2) + cell_shiftX(i, j);
850  YY(auxcorner2) = YY(corner2) + cell_shiftY(i, j);
851 
852  cell_inside(i, j) =
853  (XMIPP_MAX(STARTINGY (P()),YY(auxcorner1))<=
854  XMIPP_MIN(FINISHINGY(P()),YY(auxcorner2))) &&
855  (XMIPP_MAX(STARTINGX (P()),XX(auxcorner1))<=
856  XMIPP_MIN(FINISHINGX(P()),XX(auxcorner2)));
857  //TEMPORAL FIX FOR PHANTOM AS BIG AS THE WHOLE CRYSTAL
858  cell_inside(i, j) = 1;
859  //ROBERTO
860 #ifdef DEBUG
861 
862  std::cout << "(i,j)=(" << i << "," << j << ")\n";
863  std::cout << " Projection shape ";
864  P().printShape();
865  std::cout << std::endl;
866  std::cout << " AuxCorner1 " << auxcorner1.transpose() << std::endl
867  << " Origin " << cell_shiftX(i, j) << " "
868  << cell_shiftY(i, j) << std::endl
869  << " AuxCorner2 " << auxcorner2.transpose() << std::endl;
870  std::cout << " Inside= " << cell_inside(i, j) << std::endl;
871 #endif
872 
873  }
874  }
875 }
876 
877 /* Fill aux matrix with experimental shifs to add to unit cell
878  projection********************************************************/
880  MultidimArray<int> &cell_inside,
881  MultidimArray<double> &exp_shifts_matrix_X,
882  MultidimArray<double> &exp_shifts_matrix_Y,
883  MultidimArray<double> &exp_shifts_matrix_Z,
884  MultidimArray<double> &exp_normal_shifts_matrix_X,
885  MultidimArray<double> &exp_normal_shifts_matrix_Y,
886  MultidimArray<double> &exp_normal_shifts_matrix_Z,
887  double phantom_scale)
888 {
889  MetaDataVec aux_DF_shift; //crystal_param is cont
890  aux_DF_shift = prm_crystal.DF_shift;
891  exp_shifts_matrix_X.resize(cell_inside);
892  exp_shifts_matrix_X.initZeros();
893  exp_shifts_matrix_Y.resize(cell_inside);
894  exp_shifts_matrix_Y.initZeros();
895  exp_shifts_matrix_Z.resize(cell_inside);
896  exp_shifts_matrix_Z.initZeros();
897 
898  exp_normal_shifts_matrix_X.resize(cell_inside);
899  exp_normal_shifts_matrix_X.initZeros();
900  exp_normal_shifts_matrix_Y.resize(cell_inside);
901  exp_normal_shifts_matrix_Y.initZeros();
902  exp_normal_shifts_matrix_Z.resize(cell_inside);
903  exp_normal_shifts_matrix_Z.initZeros();
904 
905  //#define DEBUG2
906 #ifdef DEBUG2
907 
908  std::cout << aux_DF_shift;
909  std::cout << "exp_shifts_matrix_X shape" << std::endl;
910  exp_shifts_matrix_X.printShape();
911  std::cout << std::endl;
912 #endif
913 #undef DEBUG2
914  //fill matrix with docfile data
915 
916  for (size_t objId : aux_DF_shift.ids())
917  {
918  //Check that we are not outside the matrix
919  int xcell, ycell;
920  aux_DF_shift.getValue(MDL_CRYSTAL_CELLX,xcell,objId);
921  aux_DF_shift.getValue(MDL_CRYSTAL_CELLY,ycell,objId);
922  if (!exp_shifts_matrix_X.outside(xcell,ycell))
923  {
924  aux_DF_shift.getValue(MDL_SHIFT_X,exp_shifts_matrix_X(ycell, xcell),objId);
925  aux_DF_shift.getValue(MDL_SHIFT_Y,exp_shifts_matrix_Y(ycell, xcell),objId);
926  aux_DF_shift.getValue(MDL_SHIFT_Z,exp_shifts_matrix_Z(ycell, xcell),objId);
927 
928  aux_DF_shift.getValue(MDL_CRYSTAL_SHIFTX,exp_normal_shifts_matrix_X(ycell, xcell),objId);
929  aux_DF_shift.getValue(MDL_CRYSTAL_SHIFTY,exp_normal_shifts_matrix_Y(ycell, xcell),objId);
930  aux_DF_shift.getValue(MDL_CRYSTAL_SHIFTZ,exp_normal_shifts_matrix_Z(ycell, xcell),objId);
931  }
932  }
933  //#define DEBUG2
934 #ifdef DEBUG2
935  std::cout << "exp_shifts_matrix_X" << exp_shifts_matrix_X;
936  std::cout << "exp_shifts_matrix_Y" << exp_shifts_matrix_Y;
937  std::cout << "exp_shifts_matrix_Z" << exp_shifts_matrix_Z;
938 #endif
939 #undef DEBUG2
940 }
941 
#define VECTOR_R2(v, x, y)
Definition: matrix1d.h:112
#define YSIZE(v)
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
#define xF
double module() const
Definition: matrix1d.h:983
void read(const FileName &fn_crystal, double scale=1.0)
#define SPEED_UP_tempsDouble
Definition: xmipp_macros.h:413
double phantom_scale
Param file scale.
Definition: phantom.h:1377
Cell location for crystals.
int proj_Ydim
Projection Ydim.
Definition: project.h:163
void read(const FileName &inFile, const std::vector< MDLabel > *desiredLabels=nullptr, bool decomposeStack=true) override
void clear()
Definition: matrix1d.cpp:67
#define FINISHINGX(v)
void printShape(std::ostream &out=std::cout) const
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Problem with matrix size.
Definition: xmipp_error.h:152
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
doublereal * c
void write(const FileName &fn_crystal)
void Euler_direction2angles(Matrix1D< double > &v0, double &alpha, double &beta, double &gamma)
Definition: geometry.cpp:746
Matrix1D< double > b
Crustal vector b.
double beta(const double a, const double b)
Shift for the image in the X axis (double)
Matrix1D< double > vectorR3(double x, double y, double z)
Definition: matrix1d.cpp:892
bool isCorner(const Matrix1D< double > &v) const
Matrix2D< double > euler
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)
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
int proj_Xdim
Projection Xdim.
Definition: project.h:161
bool orthogonal
Orthogonalize projections.
void shift(double shiftX, double shiftY, double shiftZ)
Definition: phantom.cpp:2479
Matrix1D< double > a
Crystal vector a.
void selfTranspose()
Definition: matrix1d.h:944
double * gamma
#define V2_PLUS_V2(a, b, c)
Definition: matrix1d.h:134
#define STARTINGX(v)
#define i
< Lattice vector for projection (vector double)
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
bool DF_shift_bool
is doc file with shifts available
Shift for the image in the Z axis (double) for crystals.
#define STARTINGY(v)
MetaDataVec DF_shift
Document File for shifts. Order: H K x_SHIFT y_SHIFT z_SHIFT.
void fill_cell_positions(Projection &P, Matrix1D< double > &aproj, Matrix1D< double > &bproj, Matrix1D< double > &aprojd, Matrix1D< double > &bprojd, Matrix1D< double > &corner1, Matrix1D< double > &corner2, const Crystal_Projection_Parameters &prm_crystal, MultidimArray< double > &cell_shiftX, MultidimArray< double > &cell_shiftY, MultidimArray< double > &cell_shiftZ, MultidimArray< int > &cell_inside, MultidimArray< double > &exp_shifts_matrix_X, MultidimArray< double > &exp_shifts_matrix_Y, MultidimArray< double > &exp_shifts_matrix_Z)
void find_crystal_limits(const Matrix1D< double > &proj_corner1, const Matrix1D< double > &proj_corner2, const Matrix1D< double > &cell_corner1, const Matrix1D< double > &cell_corner2, const Matrix1D< double > &a, const Matrix1D< double > &b, int &iamin, int &iamax, int &ibmin, int &ibmax)
void clear() override
#define INDEX(r)
bool isEmpty() const override
double disappearing_th
Disappearing threshold.
Shift for the image in the Y axis (double) for crystals.
#define y0
#define FLOOR(x)
Definition: xmipp_macros.h:240
noise if center of unit cell (vector double)
void rectangle_enclosing(const Matrix1D< double > &v0, const Matrix1D< double > &vF, const Matrix2D< double > &V, Matrix1D< double > &corner1, Matrix1D< double > &corner2)
Definition: geometry.cpp:328
#define XX(v)
Definition: matrix1d.h:85
#define M2x2_BY_V2x1(a, M, b)
Definition: matrix2d.h:225
void transpose(double *array, int size)
< Shift file for crystal projection
bool setValue(const MDObject &mdValueIn, size_t id)
#define CEIL(x)
Definition: xmipp_macros.h:225
size_t addObject() override
< Have a crystal projection (bool)
size_t firstRowId() const override
#define M3x3_BY_M3x3(A, B, C)
Definition: matrix2d.h:182
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
#define XSIZE(v)
#define SPEED_UP_temps01
Definition: xmipp_macros.h:398
constexpr double MIN_MODULE
Noise description for pixels&#39; gray level (when projecting)
#define ROUND(x)
Definition: xmipp_macros.h:210
#define yF
double Nshift_dev
Standard deviation of the magnitude shift.
Matrix1D< double > vectorR2(double x, double y)
Definition: matrix1d.cpp:884
int crystal_Xdim
Crystal X dimension.
Matrix1D< double > direction
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define M2x2_BY_CT(M2, M1, k)
Definition: matrix2d.h:237
#define j
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
#define YY(v)
Definition: matrix1d.h:93
bool getValue(MDObject &mdValueOut, size_t id) const override
#define CHANGE_COORDS_AND_CHOOSE_CORNERS2D
File cannot be open.
Definition: xmipp_error.h:137
virtual void setColumnFormat(bool column)
#define FINISHINGY(v)
int crystal_Ydim
Crystal Y dimension.
bool isMetaData(bool failIfNotExists=true) const
void move_following_spiral(Matrix1D< double > &r, const MultidimArray< int > &visited)
FileName removeBlockName() const
< Lattice vector for projection (vector double)
bool outside(int k, int i, int j) const
float r3
#define FIRST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:439
std::string String
Definition: xmipp_strings.h:34
double psi(const double x)
double rnd_gaus()
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
FileName fn_shift
file with shifts
String formatString(const char *format,...)
Shift for the image in the Z axis (double)
void project_crystal(Phantom &phantom, Projection &P, const ParametersProjection &prm, PROJECT_Side_Info &side, const Crystal_Projection_Parameters &prm_crystal, float rot, float tilt, float psi)
fprintf(glob_prnt.io, "\)
#define x0
float r2
ProgClassifyCL2D * prm
Shift for the image in the Y axis (double)
void setAngles(double _rot, double _tilt, double _psi)
void initZeros(const MultidimArray< T1 > &op)
#define M2x2_INV(Ainv, A)
Definition: matrix2d.h:286
#define LAST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:448
< Disappearing threshold (double)
void project_to(Projection &P, int Ydim, int Xdim, double rot, double tilt, double psi, const Matrix2D< double > *A=nullptr) const
Definition: phantom.cpp:2511
void resize(size_t Ydim, size_t Xdim, bool noCopy=false)
Definition: matrix2d.cpp:1022
#define ZZ(v)
Definition: matrix1d.h:101
void init_shift_matrix(const Crystal_Projection_Parameters &prm_crystal, MultidimArray< int > &cell_inside, MultidimArray< double > &exp_shifts_matrix_X, MultidimArray< double > &exp_shifts_matrix_Y, MultidimArray< double > &exp_shifts_matrix_Z, MultidimArray< double > &exp_normal_shifts_matrix_X, MultidimArray< double > &exp_normal_shifts_matrix_Y, MultidimArray< double > &exp_normal_shifts_matrix_Z, double phantom_scale)
void initIdentity()
Definition: matrix2d.h:673
std::vector< Feature * > VF
List with the features.
Definition: phantom.h:1380
Cell location for crystals.
float r1
double Nshift_avg
Bias to apply to the magnitude shift.