selection.cpp
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------------
2 // d-SEAMS - Deferred Structural Elucidation Analysis for Molecular Simulations
3 //
4 // Copyright (c) 2018--present d-SEAMS core team
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the MIT License as published by
8 // the Open Source Initiative.
9 //
10 // A copy of the MIT License is included in the LICENSE file of this repository.
11 // You should have received a copy of the MIT License along with this program.
12 // If not, see <https://opensource.org/licenses/MIT>.
13 //-----------------------------------------------------------------------------------
14 
15 #include <selection.hpp>
16 
17 #include <icecream.hpp>
18 
19 // -----------------------------------------------------------------------------------------------------
20 // FUNCTIONS FOR SELECTIONS
21 // -----------------------------------------------------------------------------------------------------
22 
39  molSys::PointCloud<molSys::Point<double>, double> *outCloud,
40  int atomTypeI, bool isSlice, std::array<double, 3> coordLow,
41  std::array<double, 3> coordHigh) {
42  //
43  int natoms = 0; // Number of atoms of the desired type
44  bool pointInSlice = true; // If the current point is in the slice, this is true (otherwise this is false)
45 
46  // --------
47  // Before filling up the PointCloud, if the vectors are filled
48  // empty them
49  *outCloud = molSys::clearPointCloud(outCloud);
50  // --------
51 
52  // Loop through every iatom and check the type
53  for (int iatom = 0; iatom < yCloud->nop; iatom++) {
54  // Skip if the atom is not of the desired type
55  if (yCloud->pts[iatom].type != atomTypeI) {
56  continue;
57  } // end of checking for the type
58  // ----------------
59  // only if a slice has been requested
60  if (isSlice) {
61  pointInSlice = sinp::atomInSlice(yCloud->pts[iatom].x, yCloud->pts[iatom].y, yCloud->pts[iatom].z,
62  coordLow, coordHigh);
63  // Skip if the atom is not part of the slice
64  if (!pointInSlice) {
65  continue;
66  } // skipped for atoms not in the slice
67  } // end of slice handling
68  //
69  // Actually add the atoms to the outCloud
70  natoms++; // Update the number of atoms in outCloud
71  outCloud->pts.push_back(yCloud->pts[iatom]); // Update the pts vector
72  outCloud->idIndexMap[yCloud->pts[iatom].atomID] =
73  outCloud->pts.size() - 1; // array index
74  }
75 
76  // Update the number of particles in the PointCloud
77  outCloud->nop = outCloud->pts.size();
78 
79  // Box and box lengths
80  outCloud->box = yCloud->box;
81  outCloud->boxLow = yCloud->boxLow;
82 
83  // Update the frame number
84  outCloud->currentFrame = yCloud->currentFrame;
85 
86  return *outCloud;
87 }
88 
102  molSys::PointCloud<molSys::Point<double>, double> *yCloud,
103  bool clearPreviousSliceSelection,
104  std::array<double, 3> coordLow,
105  std::array<double, 3> coordHigh) {
106  //
107  bool pointInSlice = true; // If the current point is in the slice, this is true (otherwise this is false)
108 
109  // --------------------
110  // Set inSlice to false for every atom first
111  if (clearPreviousSliceSelection)
112  {
113  for (int iatom = 0; iatom < yCloud->nop; iatom++) {
114  yCloud->pts[iatom].inSlice = false;
115  }
116  } // end of init
117  // --------------------
118 
119  // Loop through every iatom and check if the atom is in the slice or not
120  for (int iatom = 0; iatom < yCloud->nop; iatom++) {
121  // Check if the current atom is in the slice
122  pointInSlice = sinp::atomInSlice(yCloud->pts[iatom].x, yCloud->pts[iatom].y, yCloud->pts[iatom].z,
123  coordLow, coordHigh);
124 
125  yCloud->pts[iatom].inSlice = pointInSlice; // iatom is inside the slice
126  //
127  }
128 
129  return;
130 }
131 
148  molSys::PointCloud<molSys::Point<double>, double> *yCloud,
149  bool clearPreviousSliceSelection,
150  std::array<double, 3> coordLow,
151  std::array<double, 3> coordHigh) {
152  //
153  bool pointInSlice = true; // If the current point is in the slice, this is true (otherwise this is false)
155  molIDAtomIDmap; // Unordered multimap with molecule IDs of the atoms as the keys and the
156  // atom IDs as the values. More than one atom can have the same molecule ID
157  int iatomMolID; // molID of the current iatom
158  int jatomID; // atom ID of the current jatom
159  int jatomIndex; // index of jatom
160 
161  // --------------------
162  // Get the unordered map of the atom IDs (keys) and the molecular IDs
163  // (values)
164  molIDAtomIDmap = molSys::createMolIDAtomIDMultiMap(yCloud);
165  // --------------------
166  // Set inSlice to false for every atom first
167  if (clearPreviousSliceSelection)
168  {
169  for (int iatom = 0; iatom < yCloud->nop; iatom++) {
170  yCloud->pts[iatom].inSlice = false;
171  }
172  } // end of init
173  // --------------------
174 
175  // Loop through every iatom and check if the atom is in the slice or not
176  for (int iatom = 0; iatom < yCloud->nop; iatom++) {
177  // Check if the current atom is in the slice
178  pointInSlice = sinp::atomInSlice(yCloud->pts[iatom].x, yCloud->pts[iatom].y, yCloud->pts[iatom].z,
179  coordLow, coordHigh);
180  //
181  // Set the inSlice bool for the particular Point
182  if (pointInSlice)
183  {
184  yCloud->pts[iatom].inSlice = true; // iatom is inside the slice
185  // Find mol ID and atoms with that particular molecular ID
186  iatomMolID = yCloud->pts[iatom].molID; // molecule ID
187  // -----------
188  // Find all atoms with iatomMolID and set the inSlice bool
189  // to true
190  auto range = molIDAtomIDmap.equal_range(iatomMolID);
191  // Loop through all atoms with iatomMolID
192  for (auto it = range.first; it != range.second; it++)
193  {
194  // it->second gives the value (in this case, the atom ID)
195  jatomID = it->second; // Atom ID with molecule ID equal to iatomMolID
196  auto gotJ = yCloud->idIndexMap.find(jatomID);
197  jatomIndex = gotJ->second;
198  // Set the jatom inSlice bool to true
199  yCloud->pts[jatomIndex].inSlice = true; // jatomIndex is inside the slice
200  }
201  // -----------
202  } // the atom is in the slice
203  else{
204  yCloud->pts[iatom].inSlice = false; // iatom is not in the slice
205  } // atom is not in the slice
206  }
207 
208  return;
209 }
210 
226  molSys::PointCloud<molSys::Point<double>, double> *yCloud,
227  std::unordered_multimap<int,int> molIDAtomIDmap,
228  int molID, bool inSliceValue) {
229  //
230  int jatomID; // atom ID of the current jatom
231  int jatomIndex; // index of jatom
232 
233  // Find all atoms with molID and set the inSlice bool to inSliceValue
234  auto range = molIDAtomIDmap.equal_range(molID);
235 
236  // Loop through all atoms with molID
237  for (auto it = range.first; it != range.second; it++){
238  // it->second gives the value (in this case, the atom ID)
239  jatomID = it->second; // Atom ID with molecule ID equal to iatomMolID
240  auto gotJ = yCloud->idIndexMap.find(jatomID);
241  jatomIndex = gotJ->second;
242  // Set the jatom inSlice bool to true
243  yCloud->pts[jatomIndex].inSlice = inSliceValue; // jatomIndex is assigned inSliceValue
244  } // end of loop through all atoms with molID
245 
246  // IC(yCloud->pts[jatomIndex]);
247 
248  return;
249 }
250 
267  molSys::PointCloud<molSys::Point<double>, double> *yCloud,
268  std::array<double, 3> coordLow, std::array<double, 3> coordHigh, bool identicalCloud) {
269  //
270  // A vector of bool values, such that every ring has a value of true (in the slice) or false (not in the slice)
271  std::vector<bool> ringInSlice(rings.size(), false); // all set to false initially.
272  int jatomIndex, jatomID; // Index and ID in oCloud
273  int jatomIndex1; // Index in yCloud
275  molIDAtomIDmap; // Unordered multimap with molecule IDs of the atoms as the keys and the
276  // atom IDs as the values. More than one atom can have the same molecule ID
277 
278  // --------------------
279  // Sets all O atoms within the slice to an inSlice bool value of true. If a single atom of a molecule is in the
280  // slice, then all atoms in the molecule will also be inside the slice
281  gen::moleculesInSingleSlice(oCloud, true, coordLow, coordHigh);
282  // --------------------
283  // Get the unordered map of the atom IDs (keys) and the molecular IDs
284  // (values)
285  molIDAtomIDmap = molSys::createMolIDAtomIDMultiMap(yCloud);
286  // --------------------
287 
288  // Loop through every iatom present in the slice in oCloud
289  // Check to see if iatom is in any ring. If it is present in a ring, set that ring to true
290  // Change the inSlice bool of every iatom in the ring to true if false. Set also the inSlice bool
291  // of the output cloud if it is not identical.
292 
293  // Loop through every iatom present in the slice in oCloud to determine which rings are in the slice
294  // The indices of oCloud and rings should match (or this will produce unexpected results)
295  for (int iatom = 0; iatom < oCloud->nop; iatom++) {
296  // Skip if iatom is not in the slice
297  if (!oCloud->pts[iatom].inSlice)
298  {
299  continue;
300  } // skip for iatom not in slice
301  //
302  // For iatom in the slice,
303  // loop through all rings to find all the rings it is a part of
304  for (int iring = 0; iring < rings.size(); iring++)
305  {
306  // Skip if iring is in the slice already
307  if (ringInSlice[iring])
308  {
309  continue;
310  } // skip for iring in slice
311  // Check and see if iatom is in iring
312  if(std::find(rings[iring].begin(), rings[iring].end(), iatom)!=rings[iring].end()){
313  // Found iatom; ring is part of the slice
314  ringInSlice[iring] = true; // update the vector of bool values
315  // --------------------------
316  // Change the inSlice bool of every iatom in oCloud
317  // (and optionally, yCloud) in the ring to true
318  // Loop through the elements of the ring
319  for (int j = 0; j < rings[iring].size(); j++)
320  {
321  jatomIndex = rings[iring][j]; // Index of the atom in oCloud
322  // Set this to true in oCloud
323  oCloud->pts[jatomIndex].inSlice = true; // part of slice
324  jatomID = oCloud->pts[jatomIndex].atomID; // Atom ID
325  // Now if oCloud and yCloud are not the same, use the
326  // atom ID to set the inSlice bool value in yCloud
327  if (!identicalCloud)
328  {
329  // Find the index corresponding to the same atom in yCloud
330  auto gotJ = yCloud->idIndexMap.find(jatomID);
331  jatomIndex1 = gotJ->second;
332  // throw if not found ?
333  // Set the jatom inSlice bool to true
334  yCloud->pts[jatomIndex1].inSlice = true; // jatomIndex is inside the slice
335  // set the inSlice value of all atoms in yCloud with the current molecule ID
336  gen::setAtomsWithSameMolID(yCloud, molIDAtomIDmap,
337  yCloud->pts[jatomIndex1].molID, true);
338  } // end of setting values in yCloud
339  } // end of loop through the elements of the current ring
340  // --------------------------
341  } // found iatom in the ring
342  //
343  } // end of loop through all rings searching for iatom
344  //
345  } // end of loop through atoms in oCloud in the slice
346 
347 
348  // Optionally add support for molecule slice update if yCloud and oCloud are not identical?
349  // Some other bool?
350  // IC(ringInSlice);
351 
352  return;
353 }
354 
355 // -----------------------------------------------------------------------------------------------------
356 // FUNCTIONS FOR SELECTIONS (RINGS)
357 // -----------------------------------------------------------------------------------------------------
358 
377  molSys::PointCloud<molSys::Point<double>, double> *oCloud,
378  molSys::PointCloud<molSys::Point<double>, double> *yCloud,
379  std::array<double, 3> coordLow, std::array<double, 3> coordHigh, bool identicalCloud) {
380  //
381 
382  //Given the full yCloud PointCloud, set the inSlice bool for every atom,
383  // if the molecules are inside the specified (single) region.
384  // gen::atomsInSingleSlice(yCloud, true, coordLow, coordHigh);
385  gen::moleculesInSingleSlice(yCloud, true, coordLow, coordHigh);
386 
387  // Make sure that molecules which participate in the rings inside the slice are also
388  // in the selection
389  ring::getEdgeMoleculesInRings(rings, oCloud, yCloud, coordLow, coordHigh, identicalCloud);
390 
391  // Print out the molecule IDs of all the atoms in the slice
392  sout::writeMoleculeIDsInSlice(path, yCloud);
393  // Print out a command that could be used for an expression select command in OVITO
395 
396  // Print out the dump of all atoms and molecules, with an inSlice value printed in a separate column
397  // H atoms not included in the slice (TODO: fix)
398  sout::writeLAMMPSdumpSlice(yCloud, path);
399 
400  IC(rings[0]);
401 
402  return;
403 }
T equal_range(T... args)
T find(T... args)
std::unordered_multimap< int, int > createMolIDAtomIDMultiMap(molSys::PointCloud< molSys::Point< double >, double > *yCloud)
Definition: mol_sys.cpp:67
molSys::PointCloud< molSys::Point< double >, double > clearPointCloud(molSys::PointCloud< molSys::Point< double >, double > *yCloud)
//! Function for clearing vectors in PointCloud after multiple usage
Definition: mol_sys.cpp:24
molSys::PointCloud< molSys::Point< double >, double > getPointCloudOneAtomType(molSys::PointCloud< molSys::Point< double >, double > *yCloud, molSys::PointCloud< molSys::Point< double >, double > *outCloud, int atomTypeI, bool isSlice=false, std::array< double, 3 > coordLow=std::array< double, 3 >{0, 0, 0}, std::array< double, 3 > coordHigh=std::array< double, 3 >{0, 0, 0})
Definition: selection.cpp:37
void atomsInSingleSlice(molSys::PointCloud< molSys::Point< double >, double > *yCloud, bool clearPreviousSliceSelection=true, std::array< double, 3 > coordLow=std::array< double, 3 >{0, 0, 0}, std::array< double, 3 > coordHigh=std::array< double, 3 >{0, 0, 0})
Definition: selection.cpp:101
void setAtomsWithSameMolID(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::unordered_multimap< int, int > molIDAtomIDmap, int molID, bool inSliceValue=true)
Definition: selection.cpp:225
void moleculesInSingleSlice(molSys::PointCloud< molSys::Point< double >, double > *yCloud, bool clearPreviousSliceSelection=true, std::array< double, 3 > coordLow=std::array< double, 3 >{0, 0, 0}, std::array< double, 3 > coordHigh=std::array< double, 3 >{0, 0, 0})
Definition: selection.cpp:147
void getEdgeMoleculesInRings(std::vector< std::vector< int >> rings, molSys::PointCloud< molSys::Point< double >, double > *oCloud, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::array< double, 3 > coordLow, std::array< double, 3 > coordHigh, bool identicalCloud=false)
Definition: selection.cpp:265
void printSliceGetEdgeMoleculesInRings(std::string path, std::vector< std::vector< int >> rings, molSys::PointCloud< molSys::Point< double >, double > *oCloud, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::array< double, 3 > coordLow, std::array< double, 3 > coordHigh, bool identicalCloud=false)
Definition: selection.cpp:375
bool atomInSlice(double x, double y, double z, std::array< double, 3 > coordLow, std::array< double, 3 > coordHigh)
Definition: seams_input.hpp:88
int writeMoleculeIDsInSlice(std::string path, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
int writeLAMMPSdumpSlice(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::string path)
int writeMoleculeIDsExpressionSelectOVITO(std::string path, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
File containing functions used to define 'selections' in a given range, using ring information.
This contains a collection of points; contains information for a particular frame.
Definition: mol_sys.hpp:170
This contains per-particle information.
Definition: mol_sys.hpp:149