Xmipp  v3.23.11-Nereus
Classes | Functions
project_crystal (Project crystals)
Collaboration diagram for project_crystal (Project crystals):

Classes

class  Crystal_Projection_Parameters
 

Functions

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)
 
void find_crystal_limits (const Matrix1D< double > &proj_corner1, const Matrix1D< double > &proj_corner2, const Matrix1D< double > &corner1, const Matrix1D< double > &corner2, const Matrix1D< double > &a, const Matrix1D< double > &b, int &iamin, int &iamax, int &ibmin, int &ibmax)
 
void move_following_spiral (Matrix1D< double > &r, const MultidimArray< int > &visited)
 
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 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 param_file_scale)
 

Detailed Description

Function Documentation

◆ fill_cell_positions()

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 
)

Fill cell positions. This function returns the random shifts corresponding to all cells that can be seen in a projection using the lattice vectors given. It also returns a matrix telling if a lattice combination falls inside the projection or not. You must provide the vectors in the undeformed space (for orthogonal projections), the lattice vectors in the deformed space (if it is not deformed, supply the same as in the undeformed), and the corners of the projection of a single cell. Corners must be the unit cell corners in the deformed space. Output shifts are in the deformed space.

Definition at line 715 of file project_crystal.cpp.

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 }
#define XMIPP_MAX(x, y)
Definition: xmipp_macros.h:193
double module() const
Definition: matrix1d.h:983
#define FINISHINGX(v)
void printShape(std::ostream &out=std::cout) const
#define V2_PLUS_V2(a, b, c)
Definition: matrix1d.h:134
#define STARTINGX(v)
#define i
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
#define STARTINGY(v)
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)
#define INDEX(r)
#define XX(v)
Definition: matrix1d.h:85
double Nshift_dev
Standard deviation of the magnitude shift.
Matrix1D< double > vectorR2(double x, double y)
Definition: matrix1d.cpp:884
#define XMIPP_MIN(x, y)
Definition: xmipp_macros.h:181
#define j
#define YY(v)
Definition: matrix1d.h:93
#define FINISHINGY(v)
void move_following_spiral(Matrix1D< double > &r, const MultidimArray< int > &visited)
bool outside(int k, int i, int j) const
double rnd_gaus()
void initZeros(const MultidimArray< T1 > &op)
double Nshift_avg
Bias to apply to the magnitude shift.

◆ find_crystal_limits()

void find_crystal_limits ( const Matrix1D< double > &  proj_corner1,
const Matrix1D< double > &  proj_corner2,
const Matrix1D< double > &  corner1,
const Matrix1D< double > &  corner2,
const Matrix1D< double > &  a,
const Matrix1D< double > &  b,
int &  iamin,
int &  iamax,
int &  ibmin,
int &  ibmax 
)

Find crystal limits. This function returns imin and imax such that imin*v and imax*v are still inside the projection. v is supposed to be in R2. proj_Corner1 and proj_corner2 are the top-left and right-bottom corners of the space to fit (for instance the projection). a and b are the lattice vectors where the unit cell defined by the two cell corners will be copied. iamin, iamax, ibmin, ibmax are the minimum and maximum indexes that you can use with these lattice vectors, unit cell and projection size such that the unit cell intersects the projection.

Definition at line 499 of file project_crystal.cpp.

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 }
#define VECTOR_R2(v, x, y)
Definition: matrix1d.h:112
#define xF
double module() const
Definition: matrix1d.h:983
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
Problem with matrix size.
Definition: xmipp_error.h:152
#define y0
#define FLOOR(x)
Definition: xmipp_macros.h:240
#define XX(v)
Definition: matrix1d.h:85
#define M2x2_BY_V2x1(a, M, b)
Definition: matrix2d.h:225
#define CEIL(x)
Definition: xmipp_macros.h:225
#define SPEED_UP_temps01
Definition: xmipp_macros.h:398
constexpr double MIN_MODULE
#define yF
#define YY(v)
Definition: matrix1d.h:93
#define CHANGE_COORDS_AND_CHOOSE_CORNERS2D
#define x0
#define M2x2_INV(Ainv, A)
Definition: matrix2d.h:286

◆ init_shift_matrix()

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  param_file_scale 
)

Fill auxiliary matrix with experimental shifts. the values 3D shifts stored in the doc file DF_shift are transfer to two 2D matrices

Definition at line 879 of file project_crystal.cpp.

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 }
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
Cell location for crystals.
void printShape(std::ostream &out=std::cout) const
Shift for the image in the X axis (double)
Shift for the image in the Z axis (double) for crystals.
MetaDataVec DF_shift
Document File for shifts. Order: H K x_SHIFT y_SHIFT z_SHIFT.
Shift for the image in the Y axis (double) for crystals.
< Have a crystal projection (bool)
bool outside(int k, int i, int j) const
Shift for the image in the Z axis (double)
Shift for the image in the Y axis (double)
void initZeros(const MultidimArray< T1 > &op)
Cell location for crystals.

◆ move_following_spiral()

void move_following_spiral ( Matrix1D< double > &  r,
const MultidimArray< int > &  visited 
)

Move following a spiral. Starting in a given position this function visits a matrix using an spiral like this

                DCBA
                E329
                F418
                G567
                HIJKL...

r is the actual position in the matrix.

Definition at line 589 of file project_crystal.cpp.

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 }
#define xF
#define i
#define y0
#define XX(v)
Definition: matrix1d.h:85
#define yF
#define j
#define YY(v)
Definition: matrix1d.h:93
float r3
#define x0
float r2
float r1

◆ project_crystal()

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 
)

Project a Mathematical volume as a crystal.

Definition at line 170 of file project_crystal.cpp.

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 }
#define YSIZE(v)
#define SPEED_UP_tempsDouble
Definition: xmipp_macros.h:413
double phantom_scale
Param file scale.
Definition: phantom.h:1377
int proj_Ydim
Projection Ydim.
Definition: project.h:163
void printShape(std::ostream &out=std::cout) const
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
doublereal * c
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)
Matrix1D< double > vectorR3(double x, double y, double z)
Definition: matrix1d.cpp:892
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.
double * gamma
#define i
#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
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)
double disappearing_th
Disappearing threshold.
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
void transpose(double *array, int size)
#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)
int crystal_Xdim
Crystal X dimension.
Matrix1D< double > direction
#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
int crystal_Ydim
Crystal Y dimension.
#define FIRST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:439
double psi(const double x)
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
void setAngles(double _rot, double _tilt, double _psi)
#define LAST_XMIPP_INDEX(size)
Definition: xmipp_macros.h:448
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
#define ZZ(v)
Definition: matrix1d.h:101
void resize(size_t Ydim, size_t Xdim, bool noCopy=false)
Definition: matrix2d.cpp:1022
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