match Namespace Reference

Functions

bool matchPrism (molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, const Eigen::MatrixXd &refPoints, std::vector< int > *basal1, std::vector< int > *basal2, std::vector< double > *rmsdPerAtom, bool isPerfect=true)
 
bool matchUntetheredPrism (molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, const Eigen::MatrixXd &refPoints, std::vector< int > *basal1, std::vector< int > *basal2, std::vector< double > *rmsdPerAtom)
 
bool matchPrismBlock (molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, const Eigen::MatrixXd &refPoints, std::vector< int > *basal1, std::vector< int > *basal2, int *beginIndex)
 
int updatePerAtomRMSDRing (std::vector< int > basalRing, int startingIndex, std::vector< double > rmsdFromMatch, std::vector< double > *rmsdPerAtom)
 Update the per-particle RMSD for a prism block basal ring. More...
 
int updateRMSDRing (std::vector< int > basalRing, int startingIndex, double rmsdVal, std::vector< double > *rmsdPerAtom)
 

Function Documentation

◆ matchPrism()

bool match::matchPrism ( molSys::PointCloud< molSys::Point< double >, double > *  yCloud,
std::vector< std::vector< int >>  nList,
const Eigen::MatrixXd &  refPoints,
std::vector< int > *  basal1,
std::vector< int > *  basal2,
std::vector< double > *  rmsdPerAtom,
bool  isPerfect = true 
)

Shape-matching for a pair of polygon basal rings. Returns true if the pair of basal rings form a prism block.

Definition at line 21 of file shapeMatch.cpp.

25  {
26  //
27  int ringSize = (*basal1).size(); // Number of nodes in each basal ring
28  std::vector<int> matchedBasal1,
29  matchedBasal2; // Re-ordered basal rings 1 and 2
30  int dim = 3; // Number of dimensions
31  // Matrices for the point sets of the target basal rings
32  Eigen::MatrixXd basal1Set(ringSize,
33  dim); // Point set for the first basal ring
34  Eigen::MatrixXd basal2Set(ringSize,
35  dim); // Point set for the second basal ring
36  int startingIndex; // Index in the basal rings from which the reference point
37  // set is matched
38  double cutoffAngle = 15; // Tolerance for the angular distance between the
39  // quaternions of the basal rings
40  double angDist; // Calculated angular distance between the two basal rings
41  // Variables for the absolute orientation
42  std::vector<double> quat1, quat2; // quaternion rotation
43  double rmsd1, rmsd2; // least total RMSD
44  std::vector<double> rmsdList1,
45  rmsdList2; // List of RMSD per atom in the order fed in
46  double scale1, scale2; // Scale factor
47  // Deformed block classification
48  bool doAngleCriterion = false; // For deformed blocks
49  // -----------------------
50  // Getting the target Eigen vectors
51  // Get the re-ordered matched basal rings, ordered with respect to each other
52  pntToPnt::relOrderPrismBlock(yCloud, *basal1, *basal2, nList, &matchedBasal1,
53  &matchedBasal2);
54  // -----------------------
55  // Match the basal rings with a complete prism block, given the relatively
56  // ordered basal rings This actually only needs to be done for deformed prism
57  // blocks
58  bool blockMatch = match::matchPrismBlock(
59  yCloud, nList, refPoints, &matchedBasal1, &matchedBasal2, &startingIndex);
60  // -----------------------
61  // Check for deformed prisms
62  if (!isPerfect) {
63  if (!blockMatch) {
64  return blockMatch;
65  }
66  }
67  // If the deformed prism does not fulfil the shape matching criterion, then do
68  // not calculate the RMSD per atom
69  // -----------------------
70  // Section for RMSD per atom, based on basal ring matching
71 
72  basal1Set =
73  pntToPnt::fillPointSetPrismRing(yCloud, matchedBasal1, startingIndex);
74  // Fill up the point set for basal2
75  basal2Set =
76  pntToPnt::fillPointSetPrismRing(yCloud, matchedBasal2, startingIndex);
77  // Use Horn's algorithm to calculate the absolute orientation and RMSD etc.
78  absor::hornAbsOrientation(refPoints, basal1Set, &quat1, &rmsd1, &rmsdList1,
79  &scale1); // basal1
80  absor::hornAbsOrientation(refPoints, basal2Set, &quat2, &rmsd2, &rmsdList2,
81  &scale2); // basal2
82  // // ------------
83  // // Update the per-atom RMSD for each particle
84  // // Basal1
85  // match::updatePerAtomRMSDRing(matchedBasal1, startingIndex, rmsdList1,
86  // rmsdPerAtom);
87  // // Basal2
88  // match::updatePerAtomRMSDRing(matchedBasal2, startingIndex, rmsdList2,
89  // rmsdPerAtom);
90  // // ------------
91  // ------------
92  // Update the RMSD (obtained for each ring) for each particle
93  // Basal1
94  match::updateRMSDRing(matchedBasal1, startingIndex, rmsd1, rmsdPerAtom);
95  // Basal2
96  match::updateRMSDRing(matchedBasal2, startingIndex, rmsd2, rmsdPerAtom);
97  // ------------
98 
99  return true;
100 } // end of function
int hornAbsOrientation(const Eigen::MatrixXd &refPoints, const Eigen::MatrixXd &targetPoints, std::vector< double > *quat, double *rmsd, std::vector< double > *rmsdList, double *scale)
Get the absolute orientation using Horn's algorithm (with quaternions)
bool matchPrismBlock(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int >> nList, const Eigen::MatrixXd &refPoints, std::vector< int > *basal1, std::vector< int > *basal2, int *beginIndex)
Definition: shapeMatch.cpp:251
int updateRMSDRing(std::vector< int > basalRing, int startingIndex, double rmsdVal, std::vector< double > *rmsdPerAtom)
Definition: shapeMatch.cpp:220
Eigen::MatrixXd fillPointSetPrismRing(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< int > basalRing, int startingIndex)
int relOrderPrismBlock(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< int > basal1, std::vector< int > basal2, std::vector< std::vector< int >> nList, std::vector< int > *outBasal1, std::vector< int > *outBasal2)

◆ matchPrismBlock()

bool match::matchPrismBlock ( molSys::PointCloud< molSys::Point< double >, double > *  yCloud,
std::vector< std::vector< int >>  nList,
const Eigen::MatrixXd &  refPoints,
std::vector< int > *  basal1,
std::vector< int > *  basal2,
int *  beginIndex 
)

Shape-matching for a pair of polygon basal rings, comparing with a complete prism block. Returns true if the pair of basal rings form a prism block.

Definition at line 251 of file shapeMatch.cpp.

254  {
255  //
256  int ringSize = (*basal1).size(); // Number of nodes in the basal rings
257  bool isMatch; // Qualifier for whether the prism block matches or not
258  int dim = 3; // Number of dimensions
259  int nop = 2 * ringSize; // Number of particles in the prism block
260  Eigen::MatrixXd refPrismBlock(
261  nop, dim); // eigen matrix for the reference prism block
262  Eigen::MatrixXd targetPrismBlock(
263  nop, dim); // eigen matrix for the target prism block
264  int startingIndex; // Index from which the basal rings will be ordered
265  // (permutations)
266  // variables for shape-matching
267  std::vector<double> quat; // Quaternion for the rotation
268  double rmsd; // RMSD value for the entire shape
269  std::vector<double> rmsdList; // RMSD value for each point
270  double scale; // Scale factor
271  // ----------------------------------------------------
272  // Get the reference prism block
273  refPrismBlock =
274  pntToPnt::createPrismBlock(yCloud, refPoints, ringSize, *basal1, *basal2);
275  // ----------------------------------------------------
276 
277  // Loop through possible point-to-point correspondences
278  if (ringSize % 2 == 0 || ringSize == 3) {
279  startingIndex = 0;
280  // Fill up the point set for the target prism block
281  targetPrismBlock =
282  pntToPnt::fillPointSetPrismBlock(yCloud, *basal1, *basal2, 0);
283  // Shape-matching
284  absor::hornAbsOrientation(refPrismBlock, targetPrismBlock, &quat, &rmsd,
285  &rmsdList,
286  &scale); // basal2
287  } // even or if there are 3 nodes
288  else {
289  // Define the vector, RMSD etc:
290  std::vector<double> currentQuat; // quaternion rotation
291  double currentRmsd; // least total RMSD
293  currentRmsdList; // List of RMSD per atom in the order fed in
294  double currentScale;
295  // Loop through all possible startingIndex
296  for (int i = 0; i < ringSize; i++) {
297  //
298  // Fill up the point set for basal1
299  targetPrismBlock =
300  pntToPnt::fillPointSetPrismBlock(yCloud, *basal1, *basal2, i);
301  // Use Horn's algorithm to calculate the absolute orientation and RMSD
302  // etc. for basal1
303  absor::hornAbsOrientation(refPrismBlock, targetPrismBlock, &currentQuat,
304  &currentRmsd, &currentRmsdList, &currentScale);
305  // Comparison to get the least RMSD for the correct mapping
306  if (i == 0) {
307  // Init
308  quat = currentQuat;
309  rmsd = currentRmsd;
310  rmsdList = currentRmsdList;
311  scale = currentScale;
312  startingIndex = i;
313  } // init
314  else {
315  // Check to see if the calculated RMSD is less than the RMSD already
316  // saved
317  if (currentRmsd < rmsd) {
318  quat = currentQuat;
319  rmsd = currentRmsd;
320  rmsdList = currentRmsdList;
321  scale = currentScale;
322  startingIndex = i;
323  } // end of check to see if the current RMSD is smaller
324  } // end of comparison and filling
325  } // end of loop through startingIndex
326  } // ringSize is odd, so every point must be tried
327 
328  // Update the index from which matching is started
329  *beginIndex = startingIndex;
330 
331  // // TEST DELETE BLOCK LATER
332  // if (ringSize == 6) {
333  // std::fstream rmsdFile;
334  // rmsdFile.open("../runOne/topoINT/rmsd6.dat",
335  // std::fstream::in | std::fstream::out | std::fstream::app);
336  // rmsdFile << rmsd << "\n";
337  // rmsdFile.close();
338  // } else if (ringSize == 4) {
339  // std::fstream rmsdFile;
340  // rmsdFile.open("../runOne/topoINT/rmsd4.dat",
341  // std::fstream::in | std::fstream::out | std::fstream::app);
342  // rmsdFile << rmsd << "\n";
343  // rmsdFile.close();
344  // }
345  // // END OF BLOCK TO BE DELETED
346 
347  // Condition for shape-matching
348  if (rmsd <= 6) {
349  isMatch = true; // Is a prism block
350  } // within RMSD range
351  else {
352  isMatch = false;
353  }
354 
355  // Return
356  return isMatch;
357 }
Eigen::MatrixXd createPrismBlock(molSys::PointCloud< molSys::Point< double >, double > *yCloud, const Eigen::MatrixXd &refPoints, int ringSize, std::vector< int > basal1, std::vector< int > basal2)
Eigen::MatrixXd fillPointSetPrismBlock(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< int > basal1, std::vector< int > basal2, int startingIndex)

◆ matchUntetheredPrism()

bool match::matchUntetheredPrism ( molSys::PointCloud< molSys::Point< double >, double > *  yCloud,
std::vector< std::vector< int >>  nList,
const Eigen::MatrixXd &  refPoints,
std::vector< int > *  basal1,
std::vector< int > *  basal2,
std::vector< double > *  rmsdPerAtom 
)

Shape-matching for a pair of polygon basal rings. Returns true if the pair of basal rings form a prism block.

For the pentagonal nanochannels in amorphous ice.

These must be aligned.

Shape-matching for a pair of polygon basal rings. Returns true if the pair of basal rings form a prism block.

Definition at line 110 of file shapeMatch.cpp.

114  {
115  //
116  int ringSize = (*basal1).size(); // Number of nodes in each basal ring
117  std::vector<int> matchedBasal1,
118  matchedBasal2; // Re-ordered basal rings 1 and 2
119  int dim = 3; // Number of dimensions
120  // Matrices for the point sets of the target basal rings
121  Eigen::MatrixXd basal1Set(ringSize,
122  dim); // Point set for the first basal ring
123  Eigen::MatrixXd basal2Set(ringSize,
124  dim); // Point set for the second basal ring
125  int startingIndex; // Index in the basal rings from which the reference point
126  // set is matched
127  double angDist; // Calculated angular distance between the two basal rings
128  // Variables for the absolute orientation
129  std::vector<double> quat1, quat2; // quaternion rotation
130  double rmsd1, rmsd2; // least total RMSD
131  std::vector<double> rmsdList1,
132  rmsdList2; // List of RMSD per atom in the order fed in
133  double scale1, scale2; // Scale factor
134  // Deformed block classification
135  bool doAngleCriterion = false; // For deformed blocks
136 
137  // Getting the target Eigen vectors
138  // Get the re-ordered matched basal rings, ordered with respect to each other
139  pntToPnt::relOrderPrismBlock(yCloud, *basal1, *basal2, &matchedBasal1,
140  &matchedBasal2);
141  // -----------------------
142  // Match the basal rings with a complete prism block, given the relatively
143  // ordered basal rings This actually only needs to be done for deformed prism
144  // blocks
145  bool blockMatch = match::matchPrismBlock(
146  yCloud, nList, refPoints, &matchedBasal1, &matchedBasal2, &startingIndex);
147  // -----------------------
148  // Check to see if the prism matches the reference prism block
149  if (!blockMatch) {
150  return blockMatch;
151  }
152 
153  // If the deformed prism does not fulfil the shape matching criterion, then do
154  // not calculate the RMSD per atom
155  // -----------------------
156  // Section for RMSD per atom, based on basal ring matching
157 
158  basal1Set =
159  pntToPnt::fillPointSetPrismRing(yCloud, matchedBasal1, startingIndex);
160  // Fill up the point set for basal2
161  basal2Set =
162  pntToPnt::fillPointSetPrismRing(yCloud, matchedBasal2, startingIndex);
163  // Use Horn's algorithm to calculate the absolute orientation and RMSD etc.
164  absor::hornAbsOrientation(refPoints, basal1Set, &quat1, &rmsd1, &rmsdList1,
165  &scale1); // basal1
166  absor::hornAbsOrientation(refPoints, basal2Set, &quat2, &rmsd2, &rmsdList2,
167  &scale2); // basal2
168  // // Calculate the angular distance between basal1 and basal2
169  // angDist = gen::angDistDegQuaternions(quat1, quat2);
170  // // Check if the shapes are aligned
171  // if (angDist > cutoffAngle) {
172  // return false;
173  // } // If not aligned, it is not a prism block
174  // ------------
175  // Update the RMSD (obtained for each ring) for each particle
176  // Basal1
177  match::updateRMSDRing(matchedBasal1, startingIndex, rmsd1, rmsdPerAtom);
178  // Basal2
179  match::updateRMSDRing(matchedBasal2, startingIndex, rmsd2, rmsdPerAtom);
180  // ------------
181 
182  return true;
183 } // end of function

◆ updatePerAtomRMSDRing()

int match::updatePerAtomRMSDRing ( std::vector< int >  basalRing,
int  startingIndex,
std::vector< double >  rmsdFromMatch,
std::vector< double > *  rmsdPerAtom 
)

Update the per-particle RMSD for a prism block basal ring.

Definition at line 186 of file shapeMatch.cpp.

188  {
189  //
190  int atomIndex; // Atom particle index, in rmsdPerAtom
191  int ringSize = basalRing.size(); // Size of the basal ring
192  int index; // Corresponding index in the basal ring
193  double iRMSD; // Per-particle RMSD
194 
195  // -----------------
196  // Update the RMSD per particle
197  for (int i = 0; i < ringSize; i++) {
198  index = i + startingIndex; // Corresponding index in the basal ring
199  // Wrap-around
200  if (index >= ringSize) {
201  index -= ringSize;
202  } // end of wrap-around
203  //
204  // Get the atom index
205  atomIndex = basalRing[index];
206  // Get and update the RMSD per particle
207  iRMSD = rmsdFromMatch[i];
208  if ((*rmsdPerAtom)[atomIndex] == -1) {
209  (*rmsdPerAtom)[atomIndex] = iRMSD;
210  } // end of update of RMSD
211 
212  } // end of updating the RMSD per particle
213  // -----------------
214  // finito
215  return 0;
216 } // end of function
T size(T... args)

◆ updateRMSDRing()

int match::updateRMSDRing ( std::vector< int >  basalRing,
int  startingIndex,
double  rmsdVal,
std::vector< double > *  rmsdPerAtom 
)

Update the RMSD of each particle in a prism block basal ring with the RMSD of the ring.

Update the RMSD for each particle with the RMSD of each ring for a prism block basal ring.

Definition at line 220 of file shapeMatch.cpp.

221  {
222  //
223  int atomIndex; // Atom particle index, in rmsdPerAtom
224  int ringSize = basalRing.size(); // Size of the basal ring
225  int index; // Corresponding index in the basal ring
226 
227  // -----------------
228  // Update the RMSD per particle
229  for (int i = 0; i < ringSize; i++) {
230  index = i + startingIndex; // Corresponding index in the basal ring
231  // Wrap-around
232  if (index >= ringSize) {
233  index -= ringSize;
234  } // end of wrap-around
235  //
236  // Get the atom index
237  atomIndex = basalRing[index];
238  // The RMSD value to update with is rmsdVal
239  if ((*rmsdPerAtom)[atomIndex] == -1) {
240  (*rmsdPerAtom)[atomIndex] = rmsdVal;
241  } // end of update of RMSD
242 
243  } // end of updating the RMSD for each particle
244  // -----------------
245  // finito
246  return 0;
247 } // end of function