Xmipp  v3.23.11-Nereus
Public Member Functions | Public Attributes | List of all members
SymList Class Reference

#include <symmetries.h>

Collaboration diagram for SymList:
Collaboration graph
[legend]

Public Member Functions

 SymList ()
 
 SymList (const FileName &fn_sym, double accuracy=SYM_ACCURACY)
 
bool isSymmetryGroup (FileName fn_sym, int &pgGroup, int &pgOrder)
 
void fillSymmetryClass (const FileName &symmetry, int pgGroup, int pgOrder, std::vector< std::string > &fileContent)
 
void getMatrices (int i, Matrix2D< double > &L, Matrix2D< double > &R, bool homogeneous=true) const
 
void setMatrices (int i, const Matrix2D< double > &L, const Matrix2D< double > &R)
 
void getShift (int i, Matrix1D< double > &shift) const
 
void setShift (int i, const Matrix1D< double > &shift)
 
void addShift (const Matrix1D< double > &shift)
 
int readSymmetryFile (FileName fn_sym, double accuracy=SYM_ACCURACY)
 
void addMatrices (const Matrix2D< double > &L, const Matrix2D< double > &R, int chain_length)
 
void computeSubgroup (double accuracy=SYM_ACCURACY)
 
int symsNo () const
 
int spaceGroup () const
 
int trueSymsNo () const
 
int crystallographicSpaceGroup (double mag_a, double mag_b, double ang_a2b_deg) const
 
double nonRedundantProjectionSphere (int pgGroup, int pgOrder)
 
double computeDistance (double rot1, double tilt1, double psi1, double &rot2, double &tilt2, double &psi2, bool projdir_mode, bool check_mirrors, bool object_rotation=false, bool write_mirrors=true)
 
void computeDistance (MetaData &md, bool projdir_mode, bool check_mirrors, bool object_rotation=false)
 
void breakSymmetry (double rot1, double tilt1, double psi1, double &rot2, double &tilt2, double &psi2)
 

Public Attributes

Matrix2D< double > __L
 
Matrix2D< double > __R
 
Matrix2D< double > __shift
 
Matrix1D< int > __chain_length
 
int true_symNo
 
int __sym_elements
 

Detailed Description

Symmetry List class. Internally the symmetry list class is implemented as a single 2D matrix, where every 4 rows (remember that in 3D the geometrical transformation matrices are 4x4) comprise a symmetry matrix. Access, and ways to modify the symmetry list are supplied. Remind that any symmetry is expressed in terms of two matrices L and R, so that any Euler matrix must be transformed by L*Euler*R resulting into a new perspective of the volume which is equivalent to the original one.

The typical use of the symmetry lists is to read the symmetry file, and do nothing else but reading matrices from it.

The symmetry file format is

#This is a comment
# The following line is a 6-fold rotational symmetry axis along Z-axis.
# The fold is the number of times that the volume can be rotated along
# the symmetry axis giving the same view from different view points.
# the structure for the rotational axis is
# rot_axis <fold> <X0> <Y0> <Z0>
# mirror_plane <X0> <Y0> <Z0>
rot_axis 6 0 0 1
mirror_plane 0 0 1

Definition at line 138 of file symmetries.h.

Constructor & Destructor Documentation

◆ SymList() [1/2]

SymList::SymList ( )
inline

Create an empty list. The 2D matrices are 0x0. \ Ex: SymList SL;

Definition at line 162 of file symmetries.h.

163  {
164  __sym_elements = true_symNo = space_group = 0;
165  }
int __sym_elements
Definition: symmetries.h:156
int true_symNo
Definition: symmetries.h:153

◆ SymList() [2/2]

SymList::SymList ( const FileName fn_sym,
double  accuracy = SYM_ACCURACY 
)
inline

Create Symmetry List from a Symmetry file. All the subgroup elements are computed automatically. \ Ex: SymList SL("sym.txt");

Definition at line 170 of file symmetries.h.

171  {
172  readSymmetryFile(fn_sym, accuracy);
173  }
int readSymmetryFile(FileName fn_sym, double accuracy=SYM_ACCURACY)
Definition: symmetries.cpp:33

Member Function Documentation

◆ addMatrices()

void SymList::addMatrices ( const Matrix2D< double > &  L,
const Matrix2D< double > &  R,
int  chain_length 
)

Add symmetry matrices to the symmetry list. The given matrix must specify a point of view equivalent to the actual point of view. The matrices are added to the subgroup generator but the subgroup is not updated, you must do it manually using computeSubgroup. What is more, the subgroup after the insertion is corrupted.

The chain length is the number of single matrices multiplication of which the inserted one is compound.

Definition at line 418 of file symmetries.cpp.

420 {
421  if (MAT_XSIZE(L) != 4 || MAT_YSIZE(L) != 4 || MAT_XSIZE(R) != 4 || MAT_YSIZE(R) != 4)
422  REPORT_ERROR(ERR_MATRIX_SIZE, "SymList::add_matrix: Transformation matrix is not 4x4");
423  if (trueSymsNo() == symsNo())
424  {
425  __L.resize(MAT_YSIZE(__L) + 4, 4);
426  __R.resize(MAT_YSIZE(__R) + 4, 4);
428  }
429 
430  setMatrices(true_symNo, L, R);
431  __chain_length(__chain_length.size() - 1) = chain_length;
432  true_symNo++;
433 }
#define MAT_YSIZE(m)
Definition: matrix2d.h:124
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
size_t size() const
Definition: matrix1d.h:508
Problem with matrix size.
Definition: xmipp_error.h:152
int symsNo() const
Definition: symmetries.h:268
Matrix1D< int > __chain_length
Definition: symmetries.h:148
void setMatrices(int i, const Matrix2D< double > &L, const Matrix2D< double > &R)
Definition: symmetries.cpp:378
Matrix2D< double > __R
Definition: symmetries.h:146
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
Matrix2D< double > __L
Definition: symmetries.h:146
int true_symNo
Definition: symmetries.h:153
#define MAT_XSIZE(m)
Definition: matrix2d.h:120
int trueSymsNo() const
Definition: symmetries.h:283
void resize(size_t Ydim, size_t Xdim, bool noCopy=false)
Definition: matrix2d.cpp:1022

◆ addShift()

void SymList::addShift ( const Matrix1D< double > &  shift)

Add shift. Add a shift vector to the shift matrix. An exception is thrown if the input vector is not a 3x1 vector.

Definition at line 408 of file symmetries.cpp.

409 {
410  if (shift.size() != 3)
411  REPORT_ERROR(ERR_MATRIX_SIZE, "SymList::add_shift: Shift vector is not 3x1");
412  int i = MAT_YSIZE(__shift);
413  __shift.resize(i + 1, 3);
414  setShift(i, shift);
415 }
#define MAT_YSIZE(m)
Definition: matrix2d.h:124
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
size_t size() const
Definition: matrix1d.h:508
Problem with matrix size.
Definition: xmipp_error.h:152
Matrix2D< double > __shift
Definition: symmetries.h:147
#define i
void setShift(int i, const Matrix1D< double > &shift)
Definition: symmetries.cpp:399
void resize(size_t Ydim, size_t Xdim, bool noCopy=false)
Definition: matrix2d.cpp:1022

◆ breakSymmetry()

void SymList::breakSymmetry ( double  rot1,
double  tilt1,
double  psi1,
double &  rot2,
double &  tilt2,
double &  psi2 
)

Return equivalent set of angles for a given symmetry

Definition at line 1253 of file symmetries.cpp.

1256 {
1257  Matrix2D<double> E1;
1258  Euler_angles2matrix(rot1, tilt1, psi1, E1, true);
1259  static bool doRandomize=true;
1260  Matrix2D<double> L(3, 3), R(3, 3); // A matrix from the list
1261 
1262  int i;
1263  if (doRandomize)
1264  {
1265  srand ( time(NULL) );
1266  doRandomize=false;
1267  }
1268  int symOrder = symsNo()+1;
1269  //std::cerr << "DEBUG_ROB: symOrder: " << symOrder << std::endl;
1270  i = rand() % symOrder;//59+1
1271  //std::cerr << "DEBUG_ROB: i: " << i << std::endl;
1272  if (i < symOrder-1)
1273  {
1274  getMatrices(i, L, R);
1275  //std::cerr << R << std::endl;
1276  Euler_matrix2angles(E1 * R, rot2, tilt2, psi2);
1277  }
1278  else
1279  {
1280  //std::cerr << "else" <<std::endl;
1281  rot2=rot1; tilt2=tilt1;psi2=psi1;
1282  }
1283 // if (rot2==0)
1284 //: std::cerr << "rot2 is zero " << i << R << L << std::endl;
1285 }
void getMatrices(int i, Matrix2D< double > &L, Matrix2D< double > &R, bool homogeneous=true) const
Definition: symmetries.cpp:348
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
int symsNo() const
Definition: symmetries.h:268
#define i
void Euler_matrix2angles(const Matrix2D< double > &A, double &alpha, double &beta, double &gamma, bool homogeneous)
Definition: geometry.cpp:839

◆ computeDistance() [1/2]

double SymList::computeDistance ( double  rot1,
double  tilt1,
double  psi1,
double &  rot2,
double &  tilt2,
double &  psi2,
bool  projdir_mode,
bool  check_mirrors,
bool  object_rotation = false,
bool  write_mirrors = true 
)

Check symmetries. Given two sets of angles, modify set2 to be as close to set1 as possible considering the symmetries. Distances are measured over the sphere. If the projdir_mode is set to true, then the similarity is measured only using the projection direction. The function returns the minimum distance between the two angle sets after the symmetry is considered. If check_mirrors is set, up-down corrections are also considered. Object_rotation controls the way that symmetry is applied (LR if object_rotation=false or RL if object_rotation=true). Normally it is set to false.

Definition at line 1188 of file symmetries.cpp.

1192 {
1193  Matrix2D<double> E1, E2;
1194  Euler_angles2matrix(rot1, tilt1, psi1, E1, false);
1195 
1196  int imax = symsNo() + 1;
1197  Matrix2D<double> L(3, 3), R(3, 3); // A matrix from the list
1198  double best_ang_dist = 3600;
1199  double best_rot2=0, best_tilt2=0, best_psi2=0;
1200 
1201  for (int i = 0; i < imax; i++)
1202  {
1203  double rot2p, tilt2p, psi2p;
1204  if (i == 0)
1205  {
1206  rot2p = rot2;
1207  tilt2p = tilt2;
1208  psi2p = psi2;
1209  }
1210  else
1211  {
1212  getMatrices(i - 1, L, R, false);
1213  if (object_rotation)
1214  Euler_apply_transf(R, L, rot2, tilt2, psi2, rot2p, tilt2p, psi2p);
1215  else
1216  Euler_apply_transf(L, R, rot2, tilt2, psi2, rot2p, tilt2p, psi2p);
1217  }
1218 
1219  double ang_dist = Euler_distanceBetweenAngleSets_fast(E1,rot2p, tilt2p, psi2p,
1220  projdir_mode, E2);
1221 
1222  if (ang_dist < best_ang_dist)
1223  {
1224  best_rot2 = rot2p;
1225  best_tilt2 = tilt2p;
1226  best_psi2 = psi2p;
1227  best_ang_dist = ang_dist;
1228  }
1229 
1230  if (check_mirrors)
1231  {
1232  double rot2pm, tilt2pm, psi2pm;
1233  Euler_mirrorY(rot2p, tilt2p, psi2p, rot2pm, tilt2pm, psi2pm);
1234  double ang_dist_mirror = Euler_distanceBetweenAngleSets_fast(E1,
1235  rot2pm, tilt2pm, psi2pm,projdir_mode, E2);
1236 
1237  if (ang_dist_mirror < best_ang_dist)
1238  {
1239  best_rot2 = write_mirrors ? rot2pm : rot2p;
1240  best_tilt2 = write_mirrors ? tilt2pm : tilt2p;
1241  best_psi2 = write_mirrors ? psi2pm : psi2p;
1242  best_ang_dist = ang_dist_mirror;
1243  }
1244 
1245  }
1246  }
1247  rot2 = best_rot2;
1248  tilt2 = best_tilt2;
1249  psi2 = best_psi2;
1250  return best_ang_dist;
1251 }
void getMatrices(int i, Matrix2D< double > &L, Matrix2D< double > &R, bool homogeneous=true) const
Definition: symmetries.cpp:348
void Euler_angles2matrix(T alpha, T beta, T gamma, Matrix2D< T > &A, bool homogeneous)
Definition: geometry.cpp:624
void Euler_mirrorY(double rot, double tilt, double psi, double &newrot, double &newtilt, double &newpsi)
Definition: geometry.cpp:1011
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
T Euler_distanceBetweenAngleSets_fast(const Matrix2D< T > &E1, T rot2, T tilt2, T psi2, bool only_projdir, Matrix2D< T > &E2)
Definition: geometry.cpp:693

◆ computeDistance() [2/2]

void SymList::computeDistance ( MetaData md,
bool  projdir_mode,
bool  check_mirrors,
bool  object_rotation = false 
)

auxiliary function that calls double computeDistance(double rot1, double tilt1, double psi1, double &rot2, double &tilt2, double &psi2, bool projdir_mode, bool check_mirrors, bool object_rotation=false); from a metadata. Input metadata _angleRot _angleRot2 _angleTilt _angleTilt2 _anglePsi _anglePsi2 _anglePsiDiff _image

output metadata

_angleRot _angleRot2 _angleRotDiff _angleTilt _angleTilt2 _angleTiltDiff _anglePsi _anglePsi2 _anglePsiDiff _angleDiff _image

Definition at line 1157 of file symmetries.cpp.

1160 {
1161  double rot1, tilt1, psi1;
1162  double rot2, tilt2, psi2;
1163  double angDistance;
1164  for (const auto& row : md)
1165  {
1166  row.getValue(MDL_ANGLE_ROT, rot1);
1167  row.getValue(MDL_ANGLE_ROT2, rot2);
1168 
1169  row.getValue(MDL_ANGLE_TILT, tilt1);
1170  row.getValue(MDL_ANGLE_TILT2, tilt2);
1171 
1172  row.getValue(MDL_ANGLE_PSI, psi1);
1173  row.getValue(MDL_ANGLE_PSI2, psi2);
1174 
1175  angDistance=computeDistance( rot1, tilt1, psi1,
1176  rot2, tilt2, psi2,
1177  projdir_mode, check_mirrors,
1178  object_rotation);
1179 
1180  md.setValue(MDL_ANGLE_ROT_DIFF,rot1 - rot2, row.id());
1181  md.setValue(MDL_ANGLE_TILT_DIFF,tilt1 - tilt2, row.id());
1182  md.setValue(MDL_ANGLE_PSI_DIFF,psi1 - psi2, row.id());
1183  md.setValue(MDL_ANGLE_DIFF,angDistance, row.id());
1184  }
1185 
1186 }
Rotation angle of an image (double,degrees)
Tilting angle of an image (double,degrees)
difference between rot angles (double,degrees)
Tilting angle of an image (double,degrees)
Special label to be used when gathering MDs in MpiMetadataPrograms.
Rotation angle of an image (double,degrees)
double computeDistance(double rot1, double tilt1, double psi1, double &rot2, double &tilt2, double &psi2, bool projdir_mode, bool check_mirrors, bool object_rotation=false, bool write_mirrors=true)
difference between psi angles (double,degrees)
Psi angle of an image (double,degrees)
difference between two angles (double,degrees)
difference between tilt angles (double,degrees)

◆ computeSubgroup()

void SymList::computeSubgroup ( double  accuracy = SYM_ACCURACY)

Compute subgroup for this structure. After adding or setting a matrix, the subgroup information is lost, you must recalculate it using this function. The different matrices are multiplied until no more different matrices are produced. The accuracy is used in order to compare when two matrix elements are the same.

So far, all the shifts associated to generated matrices are set to 0

Definition at line 467 of file symmetries.cpp.

468 {
469  Matrix2D<double> I(4, 4);
470  I.initIdentity();
471  Matrix2D<double> L1(4, 4), R1(4, 4), L2(4, 4), R2(4, 4), newL(4, 4), newR(4, 4),identity(4,4);
473  Matrix1D<double> shift(3);
474  shift.initZeros();
475  int i, j;
476  int new_chain_length;
477  identity.initIdentity();
478  while (found_not_tried(tried, i, j, true_symNo))
479  {
480  tried(i, j) = 1;
481 
482  // Form new symmetry matrices
483  // if (__chain_length(i)+__chain_length(j)>__sym_elements+2) continue;
484 
485  getMatrices(i, L1, R1);
486  getMatrices(j, L2, R2);
487  newL = L1 * L2;
488  newR = R1 * R2;
489  new_chain_length = __chain_length(i) + __chain_length(j);
490 
491  //if (newL.isIdentity() && newR.isIdentity()) continue;
492  //rounding error make newR different from identity
493  if (newL.equal(identity, accuracy) &&
494  newR.equal(identity, accuracy))
495  continue;
496 
497  // Try to find it in current ones
498  bool found;
499  found = false;
500  for (int l = 0; l < symsNo(); l++)
501  {
502  getMatrices(l, L1, R1);
503  if (newL.equal(L1, accuracy) && newR.equal(R1, accuracy))
504  {
505  found = true;
506  break;
507  }
508  }
509 
510  if (!found)
511  {
512  //#define DEBUG
513 #ifdef DEBUG
514  static int kjhg=0;
515  /* std::cout << "Matrix size " << tried.Xdim() << " "
516  << "trying " << i << " " << j << " "
517  << "chain length=" << new_chain_length << std::endl;
518  std::cout << "Result R Sh\n" << newR << shift;
519  */
520  //std::cerr << "shift" << __shift <<std::endl;
521  std::cerr << "newR " << kjhg++ << "\n" << newR <<std::endl;
522 #endif
523 
524  addMatrices(newL, newR, new_chain_length);
525  addShift(shift);
526  tried.resize(MAT_YSIZE(tried) + 1, MAT_XSIZE(tried) + 1);
527  }
528  }
529 #ifdef DEBUG
530  std::cerr << "__R" << __R <<std::endl;
531 #endif
532 #undef DEBUG
533 }
#define MAT_YSIZE(m)
Definition: matrix2d.h:124
void getMatrices(int i, Matrix2D< double > &L, Matrix2D< double > &R, bool homogeneous=true) const
Definition: symmetries.cpp:348
int symsNo() const
Definition: symmetries.h:268
Matrix1D< int > __chain_length
Definition: symmetries.h:148
#define i
Matrix2D< double > __R
Definition: symmetries.h:146
bool found_not_tried(const Matrix2D< int > &tried, int &i, int &j, int true_symNo)
Definition: symmetries.cpp:436
void addMatrices(const Matrix2D< double > &L, const Matrix2D< double > &R, int chain_length)
Definition: symmetries.cpp:418
void addShift(const Matrix1D< double > &shift)
Definition: symmetries.cpp:408
int true_symNo
Definition: symmetries.h:153
#define j
#define MAT_XSIZE(m)
Definition: matrix2d.h:120

◆ crystallographicSpaceGroup()

int SymList::crystallographicSpaceGroup ( double  mag_a,
double  mag_b,
double  ang_a2b_deg 
) const

Guess Crystallographic space group. Return the http://www.cryst.ehu.es/cgi-bin/cryst/programs/nph-getgen number. So far it has only been implemented for P1 (1), P2122 & P2212 (17), P4 (75), P4212 (90) and P6 (168).

Mag_a and Mag_b are the crystal vector magnitude.

Guess Crystallographic space group. Return the group number http://www.cryst.ehu.es/cgi-bin/cryst/programs/nph-getgen. So far it has only been implemented for P1 (1), P2_122 (17) , P22_12, P4 (75), P4212 (90) and P6 (168)

Definition at line 541 of file symmetries.cpp.

543 {
544 
545  switch (space_group)
546  {
547  case sym_undefined:
548  case sym_P1:
549  return(space_group);
550  case sym_P4:
551  if (fabs((mag_a - mag_b)) > XMIPP_EQUAL_ACCURACY ||
552  fabs(ang_a2b_deg - 90) > XMIPP_EQUAL_ACCURACY)
553  std::cerr << "\nWARNING: P42 but mag_a != mag_b\n"
554  << " or ang_a2b !=90" << std::endl;
555  return(space_group);
556  break;
557  case sym_P2_122:
558  if (fabs((mag_a - mag_b)) > XMIPP_EQUAL_ACCURACY ||
559  fabs(ang_a2b_deg - 90) > XMIPP_EQUAL_ACCURACY)
560  std::cerr << "\nWARNING: P2_122 but mag_a != mag_b\n"
561  << " or ang_a2b !=90" << std::endl;
562  return(space_group);
563  break;
564  case sym_P22_12:
565  if (fabs((mag_a - mag_b)) > XMIPP_EQUAL_ACCURACY ||
566  fabs(ang_a2b_deg - 90) > XMIPP_EQUAL_ACCURACY)
567  std::cerr << "\nWARNING: P22_12 but mag_a != mag_b\n"
568  << " or ang_a2b !=90" << std::endl;
569  return(space_group);
570  break;
571  case sym_P42_12:
572  if (fabs((mag_a - mag_b)) > XMIPP_EQUAL_ACCURACY ||
573  fabs(ang_a2b_deg - 90) > XMIPP_EQUAL_ACCURACY)
574  std::cerr << "\nWARNING: P42_12 but mag_a != mag_b\n"
575  << " or ang_a2b !=90" << std::endl;
576  return(space_group);
577  break;
578  case sym_P6:
579  if (fabs((mag_a - mag_b)) > XMIPP_EQUAL_ACCURACY ||
580  fabs(ang_a2b_deg - 120.) > XMIPP_EQUAL_ACCURACY)
581  {
582  std::cerr << "\nWARNING: marked as P6 but mag_a != mag_b\n"
583  << "or ang_a2b !=120" << std::endl;
584  std::cerr << "\nWARNING: P1 is assumed\n";
585  return(sym_P1);
586  }
587  else
588  return(space_group);
589  break;
590  default:
591  std::cerr << "\n Congratulations: you have found a bug in the\n"
592  << "routine crystallographic_space_group or\n"
593  << "You have called to this rotuine BEFORE reading\n"
594  << "the symmetry info" << std::endl;
595  exit(0);
596  break;
597  }//switch(space_group) end
598 
599 }//crystallographicSpaceGroup end
#define sym_P22_12
Definition: symmetries.h:60
#define sym_P4
Definition: symmetries.h:63
#define sym_P6
Definition: symmetries.h:68
#define sym_P2_122
Definition: symmetries.h:59
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
#define sym_P42_12
Definition: symmetries.h:65
#define sym_P1
Definition: symmetries.h:54
#define sym_undefined
Definition: symmetries.h:53

◆ fillSymmetryClass()

void SymList::fillSymmetryClass ( const FileName symmetry,
int  pgGroup,
int  pgOrder,
std::vector< std::string > &  fileContent 
)

fill fileContect with symmetry information

Definition at line 879 of file symmetries.cpp.

881 {
882  std::ostringstream line1;
883  std::ostringstream line2;
884  std::ostringstream line3;
885  std::ostringstream line4;
886  if (pgGroup == pg_CN)
887  {
888  line1 << "rot_axis " << pgOrder << " 0 0 1";
889  }
890  else if (pgGroup == pg_CI)
891  {
892  line1 << "inversion ";
893  }
894  else if (pgGroup == pg_CS)
895  {
896  line1 << "mirror_plane 0 0 1";
897  }
898  else if (pgGroup == pg_CNV)
899  {
900  line1 << "rot_axis " << pgOrder << " 0 0 1";
901  line2 << "mirror_plane 0 1 0";
902  }
903  else if (pgGroup == pg_CNH)
904  {
905  line1 << "rot_axis " << pgOrder << " 0 0 1";
906  line2 << "mirror_plane 0 0 1";
907  }
908  else if (pgGroup == pg_SN)
909  {
910  int order = pgOrder / 2;
911  if(2*order != pgOrder)
912  {
913  std::cerr << "ERROR: order for SN group must be even" << std::endl;
914  exit(0);
915  }
916  line1 << "rot_axis " << order << " 0 0 1";
917  line2 << "inversion ";
918  }
919  else if (pgGroup == pg_DN)
920  {
921  line1 << "rot_axis " << pgOrder << " 0 0 1";
922  line2 << "rot_axis " << "2" << " 1 0 0";
923  }
924  else if (pgGroup == pg_DNV)
925  {
926  line1 << "rot_axis " << pgOrder << " 0 0 1";
927  line2 << "rot_axis " << "2" << " 1 0 0";
928  line3 << "mirror_plane 1 0 0";
929  }
930  else if (pgGroup == pg_DNH)
931  {
932  line1 << "rot_axis " << pgOrder << " 0 0 1";
933  line2 << "rot_axis " << "2" << " 1 0 0";
934  line3 << "mirror_plane 0 0 1";
935  }
936  else if (pgGroup == pg_T)
937  {
938  line1 << "rot_axis " << "3" << " 0. 0. 1.";
939  line2 << "rot_axis " << "2" << " 0. 0.816496 0.577350";
940  }
941  else if (pgGroup == pg_TD)
942  {
943  line1 << "rot_axis " << "3" << " 0. 0. 1.";
944  line2 << "rot_axis " << "2" << " 0. 0.816496 0.577350";
945  line3 << "mirror_plane 1.4142136 2.4494897 0.0000000";
946  }
947  else if (pgGroup == pg_TH)
948  {
949  line1 << "rot_axis " << "3" << " 0. 0. 1.";
950  line2 << "rot_axis " << "2" << " 0. -0.816496 -0.577350";
951  line3 << "inversion";
952  }
953  else if (pgGroup == pg_O)
954  {
955  line1 << "rot_axis " << "3" << " .5773502 .5773502 .5773502";
956  line2 << "rot_axis " << "4" << " 0 0 1";
957  }
958  else if (pgGroup == pg_OH)
959  {
960  line1 << "rot_axis " << "3" << " .5773502 .5773502 .5773502";
961  line2 << "rot_axis " << "4" << " 0 0 1";
962  line3 << "mirror_plane 0 1 1";
963  }
964  else if (pgGroup == pg_I || pgGroup == pg_I2)
965  {
966  line1 << "rot_axis 2 0 0 1";
967  line2 << "rot_axis 5 0.525731114 0 0.850650807";
968  line3 << "rot_axis 3 0 0.356822076 0.934172364";
969  }
970  else if (pgGroup == pg_I1)
971  {
972  line1 << "rot_axis 2 1 0 0";
973  line2 << "rot_axis 5 0.85065080702670 0 -0.5257311142635";
974  line3 << "rot_axis 3 0.9341723640 0.3568220765 0";
975  }
976  else if (pgGroup == pg_I3)
977  {
978  line1 << "rot_axis 2 -0.5257311143 0 0.8506508070";
979  line3 << "rot_axis 5 0. 0. 1.";
980  line2 << "rot_axis 3 -0.4911234778630044, 0.3568220764705179, 0.7946544753759428";
981  }
982  else if (pgGroup == pg_I4)
983  {
984  line1 << "rot_axis 2 0.5257311143 0 0.8506508070";
985  line3 << "rot_axis 5 0.8944271932547096 0 0.4472135909903704";
986  line2 << "rot_axis 3 0.4911234778630044 0.3568220764705179 0.7946544753759428";
987  }
988  else if (pgGroup == pg_I5)
989  {
990  std::cerr << "ERROR: Symmetry pg_I5 not implemented" << std::endl;
991  exit(0);
992  }
993  else if (pgGroup == pg_IH || pgGroup == pg_I2H)
994  {
995  line1 << "rot_axis 2 0 0 1";
996  line2 << "rot_axis 5 0.525731114 0 0.850650807";
997  line3 << "rot_axis 3 0 0.356822076 0.934172364";
998  line4 << "mirror_plane 1 0 0";
999  }
1000  else if (pgGroup == pg_I1H)
1001  {
1002  line1 << "rot_axis 2 1 0 0";
1003  line2 << "rot_axis 5 0.85065080702670 0 -0.5257311142635";
1004  line3 << "rot_axis 3 0.9341723640 0.3568220765 0";
1005  line4 << "mirror_plane 0 0 -1";
1006  }
1007  else if (pgGroup == pg_I3H)
1008  {
1009  line1 << "rot_axis 2 -0.5257311143 0 0.8506508070";
1010  line3 << "rot_axis 5 0. 0. 1.";
1011  line2 << "rot_axis 3 -0.4911234778630044, 0.3568220764705179, 0.7946544753759428";
1012  line4 << "mirror_plane 0.850650807 0 0.525731114";
1013  }
1014  else if (pgGroup == pg_I4H)
1015  {
1016  line1 << "rot_axis 2 0.5257311143 0 0.8506508070";
1017  line3 << "rot_axis 5 0.8944271932547096 0 0.4472135909903704";
1018  line2 << "rot_axis 3 0.4911234778630044 0.3568220764705179 0.7946544753759428";
1019  line4 << "mirror_plane 0.850650807 0 -0.525731114";
1020  }
1021  else if (pgGroup == pg_I5H)
1022  {
1023  std::cerr << "ERROR: Symmetry pg_I5H not implemented" << std::endl;
1024  exit(0);
1025  }
1026  else
1027  {
1028  std::cerr << "ERROR: Symmetry " << symmetry << "is not known" << std::endl;
1029  exit(0);
1030  }
1031  if (line1.str().size()>0)
1032  fileContent.push_back(line1.str());
1033  if (line2.str().size()>0)
1034  fileContent.push_back(line2.str());
1035  if (line3.str().size()>0)
1036  fileContent.push_back(line3.str());
1037  if (line4.str().size()>0)
1038  fileContent.push_back(line4.str());
1039  //#define DEBUG5
1040 #ifdef DEBUG5
1041 
1042  for (int n=0; n<fileContent.size(); n++)
1043  std::cerr << fileContent[n] << std::endl;
1044  std::cerr << "fileContent.size()" << fileContent.size() << std::endl;
1045 #endif
1046  #undef DEBUG5
1047 }
#define pg_I2H
Definition: symmetries.h:98
#define pg_TD
Definition: symmetries.h:84
#define pg_DN
Definition: symmetries.h:80
#define pg_T
Definition: symmetries.h:83
#define pg_DNH
Definition: symmetries.h:82
#define pg_O
Definition: symmetries.h:86
#define pg_I3H
Definition: symmetries.h:99
#define pg_I3
Definition: symmetries.h:93
#define pg_I1H
Definition: symmetries.h:97
#define pg_I4H
Definition: symmetries.h:100
#define pg_CNV
Definition: symmetries.h:77
#define pg_OH
Definition: symmetries.h:87
#define pg_CS
Definition: symmetries.h:75
#define pg_I5H
Definition: symmetries.h:101
#define pg_I4
Definition: symmetries.h:94
#define pg_I1
Definition: symmetries.h:91
#define pg_DNV
Definition: symmetries.h:81
#define pg_CNH
Definition: symmetries.h:78
#define pg_TH
Definition: symmetries.h:85
#define pg_CN
Definition: symmetries.h:76
#define pg_I2
Definition: symmetries.h:92
#define pg_SN
Definition: symmetries.h:79
#define pg_CI
Definition: symmetries.h:74
#define pg_IH
Definition: symmetries.h:89
int * n
#define pg_I
Definition: symmetries.h:88
#define pg_I5
Definition: symmetries.h:95

◆ getMatrices()

void SymList::getMatrices ( int  i,
Matrix2D< double > &  L,
Matrix2D< double > &  R,
bool  homogeneous = true 
) const

Get matrices from the symmetry list. The number of matrices inside the list is given by symsNo. This function return the 4x4 (homogeneous=true) or 3x3 (homogeneous=false) transformation matrices associated to the one in the list which occupies the position 'i'. The matrix numbering within the list starts at 0. The output transformation matrices is given as a pointer to gain speed. \ Ex:

for (i=0; i<SL.symsNo; i++) {
SL.getMatrices(i,L,R);
...
}

Definition at line 348 of file symmetries.cpp.

351 {
352  int k, kp, l;
353  if (homogeneous)
354  {
355  L.initZeros(4, 4);
356  R.initZeros(4, 4);
357  for (k = 4 * i, kp=0; k < 4*i + 4; k++, kp++)
358  for (l = 0; l < 4; l++)
359  {
360  dMij(L,kp, l) = dMij(__L,k, l);
361  dMij(R,kp, l) = dMij(__R,k, l);
362  }
363  }
364  else
365  {
366  L.initZeros(3, 3);
367  R.initZeros(3, 3);
368  for (k = 4 * i, kp=0; k < 4*i + 3; k++, kp++)
369  for (l = 0; l < 3; l++)
370  {
371  dMij(L,kp, l) = dMij(__L,k, l);
372  dMij(R,kp, l) = dMij(__R,k, l);
373  }
374  }
375 }
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
Matrix2D< double > __R
Definition: symmetries.h:146
#define dMij(m, i, j)
Definition: matrix2d.h:139
Matrix2D< double > __L
Definition: symmetries.h:146
void initZeros()
Definition: matrix2d.h:626

◆ getShift()

void SymList::getShift ( int  i,
Matrix1D< double > &  shift 
) const

Get shift. Returns the shift associated to a certain symmetry.

Definition at line 391 of file symmetries.cpp.

392 {
393  shift.resize(3);
394  XX(shift) = __shift(i, 0);
395  YY(shift) = __shift(i, 1);
396  ZZ(shift) = __shift(i, 2);
397 }
Matrix2D< double > __shift
Definition: symmetries.h:147
#define i
#define XX(v)
Definition: matrix1d.h:85
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
#define YY(v)
Definition: matrix1d.h:93
#define ZZ(v)
Definition: matrix1d.h:101

◆ isSymmetryGroup()

bool SymList::isSymmetryGroup ( FileName  fn_sym,
int &  pgGroup,
int &  pgOrder 
)

translate string fn_sym to symmetry group, return false is translation is not possible. See http://xmipp.cnb.csic.es/twiki/bin/view/Xmipp/Symmetry for details. It also fill the symmetry information

Definition at line 601 of file symmetries.cpp.

602 {
603  char G1,G2,G3='\0',G4;
604  char auxChar[3];
605  //each case check length, check first letter, second, is number
606  //Non a point group
607 
608  //remove path
609  FileName fn_sym_tmp;
610  fn_sym_tmp=fn_sym.removeDirectories();
611  int mySize=fn_sym_tmp.size();
612  bool return_true;
613  return_true=false;
614  auxChar[2]='\0';
615  //size maybe 4 because n maybe a 2 digit number
616  if(mySize>4 || mySize<1)
617  {
618  pgGroup=-1;
619  pgOrder=-1;
620  return false;
621  }
622  //get the group character by character
623  G1=toupper((fn_sym_tmp.c_str())[0]);
624  G2=toupper((fn_sym_tmp.c_str())[1]);
625  if (mySize > 2)
626  {
627  G3=toupper((fn_sym_tmp.c_str())[2]);
628  if(mySize > 3)
629  G4=toupper((fn_sym.c_str())[3]);
630  }
631  else
632  G4='\0';
633  //CN
634  if (mySize==2 && G1=='C' && isdigit(G2))
635  {
636  pgGroup=pg_CN;
637  pgOrder=int(G2)-48;
638  return_true=true;
639  }
640  if (mySize==3 && G1=='C' && isdigit(G2) && isdigit(G3))
641  {
642  pgGroup=pg_CN;
643  auxChar[0]=G2;
644  auxChar[1]=G3;
645  pgOrder=atoi(auxChar);
646  return_true=true;
647  }
648  //CI
649  else if (mySize==2 && G1=='C' && G2=='I')
650  {
651  pgGroup=pg_CI;
652  pgOrder=-1;
653  return_true=true;
654  }
655  //CS
656  else if (mySize==2 && G1=='C' && G2=='S')
657  {
658  pgGroup=pg_CS;
659  pgOrder=-1;
660  return_true=true;
661  }
662  //CNH
663  else if (mySize==3 && G1=='C' && isdigit(G2) && G3=='H')
664  {
665  pgGroup=pg_CNH;
666  pgOrder=int(G2)-48;
667  return_true=true;
668  }
669  else if (mySize==4 && G1=='C' && isdigit(G2) && isdigit(G3) && G4=='H')
670  {
671  pgGroup=pg_CNH;
672  auxChar[0]=G2;
673  auxChar[1]=G3;
674  pgOrder=atoi(auxChar);
675  return_true=true;
676  }
677  //CNV
678  else if (mySize==3 && G1=='C' && isdigit(G2) && G3=='V')
679  {
680  pgGroup=pg_CNV;
681  pgOrder=int(G2)-48;
682  return_true=true;
683  }
684  else if (mySize==4 && G1=='C' && isdigit(G2) && isdigit(G3) && G4=='V')
685  {
686  pgGroup=pg_CNV;
687  auxChar[0]=G2;
688  auxChar[1]=G3;
689  pgOrder=atoi(auxChar);
690  return_true=true;
691  }
692  //SN
693  else if (mySize==2 && G1=='S' && isdigit(G2) )
694  {
695  pgGroup=pg_SN;
696  pgOrder=int(G2)-48;
697  return_true=true;
698  }
699  else if (mySize==3 && G1=='S' && isdigit(G2) && isdigit(G3) )
700  {
701  pgGroup=pg_SN;
702  auxChar[0]=G2;
703  auxChar[1]=G3;
704  pgOrder=atoi(auxChar);
705  return_true=true;
706  }
707  //DN
708  else if (mySize==2 && G1=='D' && isdigit(G2) )
709  {
710  pgGroup=pg_DN;
711  pgOrder=int(G2)-48;
712  return_true=true;
713  }
714  if (mySize==3 && G1=='D' && isdigit(G2) && isdigit(G3))
715  {
716  pgGroup=pg_DN;
717  auxChar[0]=G2;
718  auxChar[1]=G3;
719  pgOrder=atoi(auxChar);
720  return_true=true;
721  }
722  //DNV
723  else if (mySize==3 && G1=='D' && isdigit(G2) && G3=='V')
724  {
725  pgGroup=pg_DNV;
726  pgOrder=int(G2)-48;
727  return_true=true;
728  }
729  else if (mySize==4 && G1=='D' && isdigit(G2) && isdigit(G3) && G4=='V')
730  {
731  pgGroup=pg_DNV;
732  auxChar[0]=G2;
733  auxChar[1]=G3;
734  pgOrder=atoi(auxChar);
735  return_true=true;
736  }
737  //DNH
738  else if (mySize==3 && G1=='D' && isdigit(G2) && G3=='H')
739  {
740  pgGroup=pg_DNH;
741  pgOrder=int(G2)-48;
742  return_true=true;
743  }
744  else if (mySize==4 && G1=='D' && isdigit(G2) && isdigit(G3) && G4=='H')
745  {
746  pgGroup=pg_DNH;
747  auxChar[0]=G2;
748  auxChar[1]=G3;
749  pgOrder=atoi(auxChar);
750  return_true=true;
751  }
752  //T
753  else if (mySize==1 && G1=='T')
754  {
755  pgGroup=pg_T;
756  pgOrder=-1;
757  return_true=true;
758  }
759  //TD
760  else if (mySize==2 && G1=='T' && G2=='D')
761  {
762  pgGroup=pg_TD;
763  pgOrder=-1;
764  return_true=true;
765  }
766  //TH
767  else if (mySize==2 && G1=='T' && G2=='H')
768  {
769  pgGroup=pg_TH;
770  pgOrder=-1;
771  return_true=true;
772  }
773  //O
774  else if (mySize==1 && G1=='O')
775  {
776  pgGroup=pg_O;
777  pgOrder=-1;
778  return_true=true;
779  }
780  //OH
781  else if (mySize==2 && G1=='O'&& G2=='H')
782  {
783  pgGroup=pg_OH;
784  pgOrder=-1;
785  return_true=true;
786  }
787  //I
788  else if (mySize==1 && G1=='I')
789  {
790  pgGroup=pg_I;
791  pgOrder=-1;
792  return_true=true;
793  }
794  //I1
795  else if (mySize==2 && G1=='I'&& G2=='1')
796  {
797  pgGroup=pg_I1;
798  pgOrder=-1;
799  return_true=true;
800  }
801  //I2
802  else if (mySize==2 && G1=='I'&& G2=='2')
803  {
804  pgGroup=pg_I2;
805  pgOrder=-1;
806  return_true=true;
807  }
808  //I3
809  else if (mySize==2 && G1=='I'&& G2=='3')
810  {
811  pgGroup=pg_I3;
812  pgOrder=-1;
813  return_true=true;
814  }
815  //I4
816  else if (mySize==2 && G1=='I'&& G2=='4')
817  {
818  pgGroup=pg_I4;
819  pgOrder=-1;
820  return_true=true;
821  }
822  //I5
823  else if (mySize==2 && G1=='I'&& G2=='5')
824  {
825  pgGroup=pg_I5;
826  pgOrder=-1;
827  return_true=true;
828  }
829  //IH
830  else if (mySize==2 && G1=='I'&& G2=='H')
831  {
832  pgGroup=pg_IH;
833  pgOrder=-1;
834  return_true=true;
835  }
836  //I1H
837  else if (mySize==3 && G1=='I'&& G2=='1'&& G3=='H')
838  {
839  pgGroup=pg_I1H;
840  pgOrder=-1;
841  return_true=true;
842  }
843  //I2H
844  else if (mySize==3 && G1=='I'&& G2=='2'&& G3=='H')
845  {
846  pgGroup=pg_I2H;
847  pgOrder=-1;
848  return_true=true;
849  }
850  //I3H
851  else if (mySize==3 && G1=='I'&& G2=='3'&& G3=='H')
852  {
853  pgGroup=pg_I3H;
854  pgOrder=-1;
855  return_true=true;
856  }
857  //I4H
858  else if (mySize==3 && G1=='I'&& G2=='4'&& G3=='H')
859  {
860  pgGroup=pg_I4H;
861  pgOrder=-1;
862  return_true=true;
863  }
864  //I5H
865  else if (mySize==3 && G1=='I'&& G2=='5'&& G3=='H')
866  {
867  pgGroup=pg_I5H;
868  pgOrder=-1;
869  return_true=true;
870  }
871  //#define DEBUG7
872 #ifdef DEBUG7
873  std::cerr << "pgGroup" << pgGroup << " pgOrder " << pgOrder << std::endl;
874 #endif
875 #undef DEBUG7
876 
877  return return_true;
878 }
#define pg_I2H
Definition: symmetries.h:98
#define pg_TD
Definition: symmetries.h:84
#define pg_DN
Definition: symmetries.h:80
#define pg_T
Definition: symmetries.h:83
#define pg_DNH
Definition: symmetries.h:82
#define pg_O
Definition: symmetries.h:86
#define pg_I3H
Definition: symmetries.h:99
#define pg_I3
Definition: symmetries.h:93
#define pg_I1H
Definition: symmetries.h:97
#define pg_I4H
Definition: symmetries.h:100
FileName removeDirectories(int keep=0) const
#define pg_CNV
Definition: symmetries.h:77
#define pg_OH
Definition: symmetries.h:87
#define pg_CS
Definition: symmetries.h:75
#define pg_I5H
Definition: symmetries.h:101
#define pg_I4
Definition: symmetries.h:94
#define pg_I1
Definition: symmetries.h:91
#define pg_DNV
Definition: symmetries.h:81
#define pg_CNH
Definition: symmetries.h:78
#define pg_TH
Definition: symmetries.h:85
#define pg_CN
Definition: symmetries.h:76
#define pg_I2
Definition: symmetries.h:92
#define pg_SN
Definition: symmetries.h:79
#define pg_CI
Definition: symmetries.h:74
#define pg_IH
Definition: symmetries.h:89
#define pg_I
Definition: symmetries.h:88
#define pg_I5
Definition: symmetries.h:95

◆ nonRedundantProjectionSphere()

double SymList::nonRedundantProjectionSphere ( int  pgGroup,
int  pgOrder 
)

Return the area of the non redundant part of the projection sphere

Definition at line 1048 of file symmetries.cpp.

1049 {
1050  if (pgGroup == pg_CN)
1051  {
1052  return 4.*PI/pgOrder;
1053  }
1054  else if (pgGroup == pg_CI)
1055  {
1056  return 4.*PI/2.;
1057  }
1058  else if (pgGroup == pg_CS)
1059  {
1060  return 4.*PI/2.;
1061  }
1062  else if (pgGroup == pg_CNV)
1063  {
1064  return 4.*PI/pgOrder/2;
1065  }
1066  else if (pgGroup == pg_CNH)
1067  {
1068  return 4.*PI/pgOrder/2;
1069  }
1070  else if (pgGroup == pg_SN)
1071  {
1072  return 4.*PI/pgOrder;
1073  }
1074  else if (pgGroup == pg_DN)
1075  {
1076  return 4.*PI/pgOrder/2;
1077  }
1078  else if (pgGroup == pg_DNV)
1079  {
1080  return 4.*PI/pgOrder/4;
1081  }
1082  else if (pgGroup == pg_DNH)
1083  {
1084  return 4.*PI/pgOrder/4;
1085  }
1086  else if (pgGroup == pg_T)
1087  {
1088  return 4.*PI/12;
1089  }
1090  else if (pgGroup == pg_TD)
1091  {
1092  return 4.*PI/24;
1093  }
1094  else if (pgGroup == pg_TH)
1095  {
1096  return 4.*PI/24;
1097  }
1098  else if (pgGroup == pg_O)
1099  {
1100  return 4.*PI/24;
1101  }
1102  else if (pgGroup == pg_OH)
1103  {
1104  return 4.*PI/48;
1105  }
1106  else if (pgGroup == pg_I || pgGroup == pg_I2)
1107  {
1108  return 4.*PI/60;
1109  }
1110  else if (pgGroup == pg_I1)
1111  {
1112  return 4.*PI/60;
1113  }
1114  else if (pgGroup == pg_I3)
1115  {
1116  return 4.*PI/60;
1117  }
1118  else if (pgGroup == pg_I4)
1119  {
1120  return 4.*PI/60;
1121  }
1122  else if (pgGroup == pg_I5)
1123  {
1124  return 4.*PI/60;
1125  }
1126  else if (pgGroup == pg_IH || pgGroup == pg_I2H)
1127  {
1128  return 4.*PI/120;
1129  }
1130  else if (pgGroup == pg_I1H)
1131  {
1132  return 4.*PI/120;
1133  }
1134  else if (pgGroup == pg_I3H)
1135  {
1136  return 4.*PI/120;
1137  }
1138  else if (pgGroup == pg_I4H)
1139  {
1140  return 4.*PI/120;
1141  }
1142  else if (pgGroup == pg_I5H)
1143  {
1144  return 4.*PI/120;
1145  }
1146  else
1147  {
1148  std::cerr << "ERROR: Symmetry group, order=" << pgGroup
1149  << " "
1150  << pgOrder
1151  << "is not known"
1152  << std::endl;
1153  exit(0);
1154  }
1155 }
#define pg_I2H
Definition: symmetries.h:98
#define pg_TD
Definition: symmetries.h:84
#define pg_DN
Definition: symmetries.h:80
#define pg_T
Definition: symmetries.h:83
#define pg_DNH
Definition: symmetries.h:82
#define pg_O
Definition: symmetries.h:86
#define pg_I3H
Definition: symmetries.h:99
#define pg_I3
Definition: symmetries.h:93
#define pg_I1H
Definition: symmetries.h:97
#define pg_I4H
Definition: symmetries.h:100
#define pg_CNV
Definition: symmetries.h:77
#define pg_OH
Definition: symmetries.h:87
#define pg_CS
Definition: symmetries.h:75
#define pg_I5H
Definition: symmetries.h:101
#define pg_I4
Definition: symmetries.h:94
#define pg_I1
Definition: symmetries.h:91
#define pg_DNV
Definition: symmetries.h:81
#define pg_CNH
Definition: symmetries.h:78
#define pg_TH
Definition: symmetries.h:85
#define pg_CN
Definition: symmetries.h:76
#define pg_I2
Definition: symmetries.h:92
#define pg_SN
Definition: symmetries.h:79
#define pg_CI
Definition: symmetries.h:74
#define pg_IH
Definition: symmetries.h:89
#define PI
Definition: tools.h:43
#define pg_I
Definition: symmetries.h:88
#define pg_I5
Definition: symmetries.h:95

◆ readSymmetryFile()

int SymList::readSymmetryFile ( FileName  fn_sym,
double  accuracy = SYM_ACCURACY 
)

Read a symmetry file into a symmetry list. The former symmetry list is overwritten with the new one. All the subgroup members are added to the list. If the accuracy is negative then the subgroup is not generated. return symmetry group \ Ex: SL.readSymmetryFile("sym.txt");

Definition at line 33 of file symmetries.cpp.

34 {
35  int i, j;
36  FILE *fpoii;
37  char line[80];
38  char *auxstr;
39  double ang_incr, rot_ang;
40  int fold;
41  Matrix2D<double> L(4, 4), R(4, 4);
42  Matrix1D<double> axis(3), shift(3);
43  int pgGroup = sym_undefined;
44  int pgOrder;
45  std::vector<std::string> fileContent;
46 
47  //check if reserved word
48 
49  // Open file ---------------------------------------------------------
50  if ((fpoii = fopen(fn_sym.c_str(), "r")) == NULL)
51  {
52  //check if reserved word and return group and order
53  if (isSymmetryGroup(fn_sym, pgGroup, pgOrder))
54  {
55  fillSymmetryClass(fn_sym, pgGroup, pgOrder,fileContent);
56  }
57  else
58  REPORT_ERROR(ERR_IO_NOTOPEN, (std::string)"SymList::read_sym_file:Can't open file: "
59  + " or do not recognize symmetry group" + fn_sym);
60  }
61  else
62  {
63  while (fgets(line, 79, fpoii) != NULL)
64  {
65  if (line[0] == ';' || line[0] == '#' || line[0] == '\0')
66  continue;
67  fileContent.push_back(line);
68  }
69  fclose(fpoii);
70  }
71 
72  //reset space_group
73  space_group = 0;
74  // Count the number of symmetries ------------------------------------
75  true_symNo = 0;
76  // count number of axis and mirror planes. It will help to identify
77  // the crystallographic symmetry
78 
79  int no_axis, no_mirror_planes, no_inversion_points;
80  no_axis = no_mirror_planes = no_inversion_points = 0;
81 
82  for (size_t n=0; n<fileContent.size(); n++)
83  {
84  strcpy(line,fileContent[n].c_str());
85  auxstr = firstToken(line);
86  if (auxstr == NULL)
87  {
88  std::cout << line;
89  std::cout << "Wrong line in symmetry file, the line is skipped\n";
90  continue;
91  }
92  if (strcmp(auxstr, "rot_axis") == 0)
93  {
94  auxstr = nextToken();
95  fold = textToInteger(auxstr);
96  true_symNo += (fold - 1);
97  no_axis++;
98  }
99  else if (strcmp(auxstr, "mirror_plane") == 0)
100  {
101  true_symNo++;
102  no_mirror_planes++;
103  }
104  else if (strcmp(auxstr, "inversion") == 0)
105  {
106  true_symNo += 1;
107  no_inversion_points = 1;
108  }
109  else if (strcmp(auxstr, "P4212") == 0)
110  true_symNo += 7;
111  else if (strcmp(auxstr, "P2_122") == 0)
112  true_symNo += 3;
113  else if (strcmp(auxstr, "P22_12") == 0)
114  true_symNo += 3;
115  }
116  // Ask for memory
117  __L.resize(4*true_symNo, 4);
118  __R.resize(4*true_symNo, 4);
122 
123  // Read symmetry parameters
124  i = 0;
125  shift.initZeros();
126 
127  for (size_t n=0; n<fileContent.size(); n++)
128  {
129  strcpy(line,fileContent[n].c_str());
130  auxstr = firstToken(line);
131  // Rotational axis ---------------------------------------------------
132  if (strcmp(auxstr, "rot_axis") == 0)
133  {
134  auxstr = nextToken();
135  fold = textToInteger(auxstr);
136  auxstr = nextToken();
137  XX(axis) = textToFloat(auxstr);
138  auxstr = nextToken();
139  YY(axis) = textToFloat(auxstr);
140  auxstr = nextToken();
141  ZZ(axis) = textToFloat(auxstr);
142  ang_incr = 360. / fold;
143  L.initIdentity();
144  for (j = 1, rot_ang = ang_incr; j < fold; j++, rot_ang += ang_incr)
145  {
146  rotation3DMatrix(rot_ang, axis, R);
147  setShift(i, shift);
148  setMatrices(i++, L, R.transpose());
149  }
150  __sym_elements++;
151  // inversion ------------------------------------------------------
152  }
153  else if (strcmp(auxstr, "inversion") == 0)
154  {
155  L.initIdentity();
156  L(2, 2) = -1;
157  R.initIdentity();
158  R(0, 0) = -1.;
159  R(1, 1) = -1.;
160  R(2, 2) = -1.;
161  setShift(i, shift);
162  setMatrices(i++, L, R);
163  __sym_elements++;
164  // mirror plane -------------------------------------------------------------
165  }
166  else if (strcmp(auxstr, "mirror_plane") == 0)
167  {
168  auxstr = nextToken();
169  XX(axis) = textToFloat(auxstr);
170  auxstr = nextToken();
171  YY(axis) = textToFloat(auxstr);
172  auxstr = nextToken();
173  ZZ(axis) = textToFloat(auxstr);
174  L.initIdentity();
175  L(2, 2) = -1;
177  alignWithZ(axis,A);
178  A = A.transpose();
179  R = A * L * A.inv();
180  setShift(i, shift);
181  L.initIdentity();
182  setMatrices(i++, L, R);
183  __sym_elements++;
184  // P4212 -------------------------------------------------------------
185  }
186  else if (strcmp(auxstr, "P4212") == 0)
187  {
188  space_group = sym_P42_12;
189  accuracy = -1; // Do not compute subgroup
190  L.initIdentity();
191 
192  // With 0 shift
193  R.initZeros();
194  R(3, 3) = 1;
195  R(0, 0) = R(1, 1) = -1;
196  R(2, 2) = 1;
197  setShift(i, shift);
198  setMatrices(i++, L, R);
199  R.initZeros();
200  R(3, 3) = 1;
201  R(2, 2) = -1;
202  R(0, 1) = R(1, 0) = 1;
203  setShift(i, shift);
204  setMatrices(i++, L, R);
205  R.initZeros();
206  R(3, 3) = 1;
207  R(2, 2) = R(0, 1) = R(1, 0) = -1;
208  setShift(i, shift);
209  setMatrices(i++, L, R);
210 
211  // With 1/2 shift
212  VECTOR_R3(shift, 0.5, 0.5, 0);
213  R.initZeros();
214  R(3, 3) = 1;
215  R(0, 1) = -1;
216  R(1, 0) = R(2, 2) = 1;
217  setShift(i, shift);
218  setMatrices(i++, L, R);
219  R.initZeros();
220  R(3, 3) = 1;
221  R(1, 0) = -1;
222  R(0, 1) = R(2, 2) = 1;
223  setShift(i, shift);
224  setMatrices(i++, L, R);
225  R.initZeros();
226  R(3, 3) = 1;
227  R(0, 0) = R(2, 2) = -1;
228  R(1, 1) = 1;
229  setShift(i, shift);
230  setMatrices(i++, L, R);
231  R.initZeros();
232  R(3, 3) = 1;
233  R(1, 1) = R(2, 2) = -1;
234  R(0, 0) = 1;
235  setShift(i, shift);
236  setMatrices(i++, L, R);
237 
238  __sym_elements++;
239  }
240  else if (strcmp(auxstr, "P2_122") == 0)
241  {
242  space_group = sym_P2_122;
243  accuracy = -1; // Do not compute subgroup
244  L.initIdentity();
245 
246  // With 0 shift
247  R.initZeros();
248  R(3, 3) = 1;
249  R(0, 0) = -1;
250  R(1, 1) = -1;
251  R(2, 2) = 1;
252  setShift(i, shift);
253  setMatrices(i++, L, R);
254 
255  // With 1/2 shift
256  VECTOR_R3(shift, 0.5, 0.0, 0.0);
257  R.initZeros();
258  R(3, 3) = 1;
259  R(0, 0) = -1;
260  R(1, 1) = 1;
261  R(2, 2) = -1;
262  setShift(i, shift);
263  setMatrices(i++, L, R);
264  R.initZeros();
265  R(3, 3) = 1;
266  R(0, 0) = 1;
267  R(1, 1) = -1;
268  R(2, 2) = -1;
269  setShift(i, shift);
270  setMatrices(i++, L, R);
271  __sym_elements++;
272  }
273  else if (strcmp(auxstr, "P22_12") == 0)
274  {
275  space_group = sym_P22_12;
276  accuracy = -1; // Do not compute subgroup
277  L.initIdentity();
278 
279  // With 0 shift
280  R.initZeros();
281  R(3, 3) = 1;
282  R(0, 0) = -1;
283  R(1, 1) = -1;
284  R(2, 2) = 1;
285  setShift(i, shift);
286  setMatrices(i++, L, R);
287 
288  // With 1/2 shift
289  VECTOR_R3(shift, 0.0, 0.5, 0.0);
290  R.initZeros();
291  R(3, 3) = 1;
292  R(0, 0) = 1;
293  R(1, 1) = -1;
294  R(2, 2) = -1;
295  setShift(i, shift);
296  setMatrices(i++, L, R);
297  R.initZeros();
298  R(3, 3) = 1;
299  R(0, 0) = -1;
300  R(1, 1) = 1;
301  R(2, 2) = -1;
302  setShift(i, shift);
303  setMatrices(i++, L, R);
304  __sym_elements++;
305  }
306  }
307 
308  if (accuracy > 0)
309  computeSubgroup(accuracy);
310 
311  //possible crystallographic symmetry
312  if (no_axis == 0 && no_mirror_planes == 0 && no_inversion_points == 0 &&
313  true_symNo == 7 && space_group == sym_P42_12)
314  space_group = sym_P42_12;
315  else if (no_axis == 0 && no_mirror_planes == 0 && no_inversion_points == 0 &&
316  true_symNo == 3 && space_group == sym_P2_122)
317  space_group = sym_P2_122;
318  else if (no_axis == 0 && no_mirror_planes == 0 && no_inversion_points == 0 &&
319  true_symNo == 3 && space_group == sym_P22_12)
320  space_group = sym_P22_12;
321  // P4 and P6
322  else if (no_axis == 1 && no_mirror_planes == 0 && no_inversion_points == 0 &&
323  fabs(R(2, 2) - 1.) < XMIPP_EQUAL_ACCURACY &&
324  fabs(R(0, 0) - R(1, 1)) < XMIPP_EQUAL_ACCURACY &&
325  fabs(R(0, 1) + R(1, 0)) < XMIPP_EQUAL_ACCURACY)
326  {
327  switch (true_symNo)
328  {
329  case(5):
330  space_group = sym_P6;
331  break;
332  case(3):
333  space_group = sym_P4;
334  break;
335  default:
336  space_group = sym_undefined;
337  break;
338  }//switch end
339  }//end else if (no_axis==1 && no_mirror_planes== 0
340  else if (no_axis == 0 && no_inversion_points == 0 && no_mirror_planes == 0)
341  space_group = sym_P1;
342  else
343  space_group = sym_undefined;
344  return pgGroup;
345 }
#define sym_P22_12
Definition: symmetries.h:60
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
#define sym_P4
Definition: symmetries.h:63
bool isSymmetryGroup(FileName fn_sym, int &pgGroup, int &pgOrder)
Definition: symmetries.cpp:601
#define sym_P6
Definition: symmetries.h:68
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
Matrix2D< T > transpose() const
Definition: matrix2d.cpp:1314
Matrix1D< int > __chain_length
Definition: symmetries.h:148
int __sym_elements
Definition: symmetries.h:156
Matrix2D< double > __shift
Definition: symmetries.h:147
void computeSubgroup(double accuracy=SYM_ACCURACY)
Definition: symmetries.cpp:467
#define i
void fillSymmetryClass(const FileName &symmetry, int pgGroup, int pgOrder, std::vector< std::string > &fileContent)
Definition: symmetries.cpp:879
void setMatrices(int i, const Matrix2D< double > &L, const Matrix2D< double > &R)
Definition: symmetries.cpp:378
void rotation3DMatrix(double ang, char axis, Matrix2D< double > &result, bool homogeneous)
#define sym_P2_122
Definition: symmetries.h:59
char axis
Matrix2D< double > __R
Definition: symmetries.h:146
#define XX(v)
Definition: matrix1d.h:85
float textToFloat(const char *str)
#define XMIPP_EQUAL_ACCURACY
Definition: xmipp_macros.h:119
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
Matrix2D< double > __L
Definition: symmetries.h:146
int true_symNo
Definition: symmetries.h:153
#define sym_P42_12
Definition: symmetries.h:65
#define j
#define YY(v)
Definition: matrix1d.h:93
File cannot be open.
Definition: xmipp_error.h:137
void setShift(int i, const Matrix1D< double > &shift)
Definition: symmetries.cpp:399
#define sym_P1
Definition: symmetries.h:54
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
int textToInteger(const char *str)
char * firstToken(const char *str)
void alignWithZ(const Matrix1D< double > &axis, Matrix2D< double > &result, bool homogeneous)
String nextToken(const String &str, size_t &i)
void initConstant(T val)
Definition: matrix1d.cpp:83
int * n
#define sym_undefined
Definition: symmetries.h:53
#define ZZ(v)
Definition: matrix1d.h:101
void resize(size_t Ydim, size_t Xdim, bool noCopy=false)
Definition: matrix2d.cpp:1022

◆ setMatrices()

void SymList::setMatrices ( int  i,
const Matrix2D< double > &  L,
const Matrix2D< double > &  R 
)

Set a couple of matrices in the symmetry list. The number of matrices inside the list is given by symsNo. This function sets the 4x4 transformation matrices associated to the one in the list which occupies the position 'i'. The matrix numbering within the list starts at 0. \ Ex:

for (i=0; i<SL.symsNo; i++) {
SL.set_matrix(i,L,R);
...
}

Definition at line 378 of file symmetries.cpp.

380 {
381  int k, l;
382  for (k = 4 * i; k < 4*i + 4; k++)
383  for (l = 0; l < 4; l++)
384  {
385  __L(k, l) = L(k - 4 * i, l);
386  __R(k, l) = R(k - 4 * i, l);
387  }
388 }
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
Matrix2D< double > __R
Definition: symmetries.h:146
Matrix2D< double > __L
Definition: symmetries.h:146

◆ setShift()

void SymList::setShift ( int  i,
const Matrix1D< double > &  shift 
)

Set shift. Set the shift associated to a certain symmetry.

Definition at line 399 of file symmetries.cpp.

400 {
401  if (shift.size() != 3)
402  REPORT_ERROR(ERR_MATRIX_SIZE, "SymList::add_shift: Shift vector is not 3x1");
403  __shift(i, 0) = XX(shift);
404  __shift(i, 1) = YY(shift);
405  __shift(i, 2) = ZZ(shift);
406 }
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
size_t size() const
Definition: matrix1d.h:508
Problem with matrix size.
Definition: xmipp_error.h:152
Matrix2D< double > __shift
Definition: symmetries.h:147
#define i
#define XX(v)
Definition: matrix1d.h:85
#define YY(v)
Definition: matrix1d.h:93
#define ZZ(v)
Definition: matrix1d.h:101

◆ spaceGroup()

int SymList::spaceGroup ( ) const
inline

Return space group

Definition at line 275 of file symmetries.h.

276  {
277  return space_group;
278  }

◆ symsNo()

int SymList::symsNo ( ) const
inline

Number of symmetry matrices inside the structure. This is the number of all the matrices inside the subgroup. \ Ex:

for (i=0; i<SL.symsNo; i++) {
SL.get_matrix(i,A);
...
}

Definition at line 268 of file symmetries.h.

269  {
270  return MAT_YSIZE(__L) / 4;
271  }
#define MAT_YSIZE(m)
Definition: matrix2d.h:124
Matrix2D< double > __L
Definition: symmetries.h:146

◆ trueSymsNo()

int SymList::trueSymsNo ( ) const
inline

Number of symmetry matrices which generated the structure. This is the number of the matrices which generated the structure, notice that it should be always less or equal to the total number of matrices in the subgroup.

Definition at line 283 of file symmetries.h.

284  {
285  return true_symNo;
286  }
int true_symNo
Definition: symmetries.h:153

Member Data Documentation

◆ __chain_length

Matrix1D<int> SymList::__chain_length

Definition at line 148 of file symmetries.h.

◆ __L

Matrix2D<double> SymList::__L

Definition at line 146 of file symmetries.h.

◆ __R

Matrix2D<double> SymList::__R

Definition at line 146 of file symmetries.h.

◆ __shift

Matrix2D<double> SymList::__shift

Definition at line 147 of file symmetries.h.

◆ __sym_elements

int SymList::__sym_elements

Definition at line 156 of file symmetries.h.

◆ true_symNo

int SymList::true_symNo

Definition at line 153 of file symmetries.h.


The documentation for this class was generated from the following files: