50 std::string path, std::vector<std::vector<int>> rings,
51 std::vector<std::vector<int>> nList,
53 int *atomID,
int firstFrame,
int currentFrame,
bool doShapeMatching) {
55 std::vector<std::vector<int>>
57 std::vector<int> listPrism;
58 std::vector<ring::strucType>
60 std::vector<ring::strucType>
65 std::vector<int> nPrismList;
67 std::vector<int> nDefPrismList;
73 double avgPrismHeight = 2.845;
75 std::vector<double> rmsdPerAtom;
81 nDefPrismList.resize(maxDepth - 2);
82 heightPercent.resize(maxDepth - 2);
84 atomTypes.resize(yCloud->nop, 1);
87 rmsdPerAtom.resize(yCloud->nop, -1);
89 atomState.resize(yCloud->nop);
93 for (
int ringSize = 3; ringSize <= maxDepth; ringSize++) {
100 if (ringsOneType.size() == 0) {
101 nPrismList[ringSize - 3] = 0;
102 nDefPrismList[ringSize - 3] = 0;
103 heightPercent[ringSize - 3] = 0.0;
112 nImperfectPrisms = 0;
114 ringsOneType.size());
119 &nImperfectPrisms, nList, yCloud, &rmsdPerAtom,
122 nPrismList[ringSize - 3] =
124 nDefPrismList[ringSize - 3] =
126 int totalPrisms = nPerfectPrisms + nImperfectPrisms;
128 heightPercent[ringSize - 3] =
131 if (nPerfectPrisms + nImperfectPrisms == 0) {
139 &atomTypes, &atomState);
147 yCloud->currentFrame, firstFrame);
149 if (doShapeMatching) {
158 if (doShapeMatching) {
194 std::vector<ring::strucType> *ringType,
int *nPerfectPrisms,
195 int *nImperfectPrisms, std::vector<std::vector<int>> nList,
197 std::vector<double> *rmsdPerAtom,
bool doShapeMatching) {
198 std::vector<int> listPrism;
199 int totalRingNum = rings.size();
200 std::vector<int> basal1;
201 std::vector<int> basal2;
207 int ringSize = rings[0].size();
208 *nImperfectPrisms = 0;
211 Eigen::MatrixXd refPointSet(ringSize, 3);
215 int axialDim = std::max_element(yCloud->box.begin(), yCloud->box.end()) -
221 for (
int iring = 0; iring < totalRingNum - 1; iring++) {
224 basal1 = rings[iring];
226 for (
int jring = iring + 1; jring < totalRingNum; jring++) {
227 basal2 = rings[jring];
230 if (doShapeMatching ==
true || ringSize == 4) {
234 if (isAxialPair ==
false ) {
251 if (cond2 ==
false ) {
253 if (!doShapeMatching) {
261 if (relaxedCond ==
false ) {
267 yCloud, nList, refPointSet, &basal1, &basal2, rmsdPerAtom,
false );
270 if (isDeformedPrism) {
273 *nImperfectPrisms += 1;
277 listPrism.push_back(iring);
284 listPrism.push_back(jring);
298 *nPerfectPrisms += 1;
302 listPrism.push_back(iring);
309 listPrism.push_back(jring);
315 if (doShapeMatching) {
317 yCloud, nList, refPointSet, &basal1, &basal2, rmsdPerAtom,
true );
331 sort(listPrism.begin(), listPrism.end());
332 auto ip = std::unique(listPrism.begin(), listPrism.end());
334 listPrism.resize(std::distance(listPrism.begin(), ip));
352 std::vector<int> *basal1,
353 std::vector<int> *basal2) {
354 int l1 = (*basal1)[0];
362 std::vector<bool> isNeighbour(ringSize,
false );
369 for (
int k = 0; k < ringSize; k++) {
370 l1_neighbour =
false ;
375 auto it = std::find(nList[l1].begin() + 1, nList[l1].end(), m_k);
378 if (it != nList[l1].end()) {
393 isNeighbour[kIndex] =
true ;
396 for (
int i = 1; i < ringSize; i++) {
397 lAtomID = (*basal1)[i];
398 for (
int k = 0; k < ringSize; k++) {
400 if (isNeighbour[k]) {
404 kAtomID = (*basal2)[k];
409 std::find(nList[lAtomID].begin() + 1, nList[lAtomID].end(), kAtomID);
412 if (it1 != nList[lAtomID].end()) {
413 isNeighbour[k] =
true ;
421 for (
int k = 0; k < ringSize; k++) {
423 if (!isNeighbour[k]) {
437 std::vector<int> *basal1,
438 std::vector<int> *basal2) {
442 bool isNeighbour =
false ;
449 for (
int l = 0; l < ringSize; l++) {
453 for (
int m = 0; m < ringSize; m++) {
456 auto it = std::find(nList[l_k].begin() + 1, nList[l_k].end(), m_k);
459 if (it != nList[l_k].end()) {
488 std::vector<int> *basal1, std::vector<int> *basal2,
498 bool axialBasal1, axialBasal2;
500 double areaXY, areaXZ,
509 axialDim = std::max_element(yCloud->box.begin(), yCloud->box.end()) -
521 jatomIndex = (*basal1)[0];
524 for (
int k = 1; k < ringSize; k++) {
525 iatomIndex = (*basal1)[k];
530 areaXY += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
531 (yCloud->pts[jatomIndex].y - yCloud->pts[iatomIndex].y);
534 areaXZ += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
535 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
538 areaYZ += (yCloud->pts[jatomIndex].y + yCloud->pts[iatomIndex].y) *
539 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
541 jatomIndex = iatomIndex;
545 iatomIndex = (*basal1)[0];
548 areaXY += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
549 (yCloud->pts[jatomIndex].y - yCloud->pts[iatomIndex].y);
552 areaXZ += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
553 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
556 areaYZ += (yCloud->pts[jatomIndex].y + yCloud->pts[iatomIndex].y) *
557 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
564 areaXY = fabs(areaXY);
565 areaXZ = fabs(areaXZ);
566 areaYZ = fabs(areaYZ);
573 if (areaYZ > areaXY && areaYZ > areaXZ) {
578 else if (axialDim == 1) {
579 if (areaXZ > areaXY && areaXZ > areaYZ) {
584 else if (axialDim == 2) {
585 if (areaXY > areaXZ && areaXY > areaYZ) {
590 std::cerr <<
"Could not find the axial dimension.\n" ;
601 jatomIndex = (*basal2)[0];
604 for (
int k = 1; k < ringSize; k++) {
605 iatomIndex = (*basal2)[k];
610 areaXY += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
611 (yCloud->pts[jatomIndex].y - yCloud->pts[iatomIndex].y);
614 areaXZ += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
615 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
618 areaYZ += (yCloud->pts[jatomIndex].y + yCloud->pts[iatomIndex].y) *
619 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
621 jatomIndex = iatomIndex;
625 iatomIndex = (*basal2)[0];
628 areaXY += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
629 (yCloud->pts[jatomIndex].y - yCloud->pts[iatomIndex].y);
632 areaXZ += (yCloud->pts[jatomIndex].x + yCloud->pts[iatomIndex].x) *
633 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
636 areaYZ += (yCloud->pts[jatomIndex].y + yCloud->pts[iatomIndex].y) *
637 (yCloud->pts[jatomIndex].z - yCloud->pts[iatomIndex].z);
644 areaXY = fabs(areaXY);
645 areaXZ = fabs(areaXZ);
646 areaYZ = fabs(areaYZ);
654 if (areaYZ > areaXY && areaYZ > areaXZ) {
659 else if (axialDim == 1) {
660 if (areaXZ > areaXY && areaXZ > areaYZ) {
665 else if (axialDim == 2) {
666 if (areaXY > areaXZ && areaXY > areaYZ) {
671 std::cerr <<
"Could not find the axial dimension.\n" ;
677 if (axialBasal1 ==
true && axialBasal2 ==
true ) {
697 std::vector<int> listPrism,
int ringSize,
698 std::vector<ring::strucType> ringType,
699 std::vector<int> *atomTypes,
700 std::vector<ring::strucType> *atomState) {
712 for (
int i = 0; i < listPrism.size(); i++) {
713 iring = listPrism[i];
715 currentState = ringType[iring];
717 for (
int j = 0; j < ringSize; j++) {
718 iatom = rings[iring][j];
720 (*atomTypes)[iatom] = ringSize;
724 (*atomState)[iatom] = currentState;
727 if ((*atomState)[iatom] != currentState) {
730 (*atomState)[iatom] = currentState;
760 std::vector<int> *atomTypes,
int maxDepth) {
762 int nop = atomState.size();
765 for (
int iatom = 0; iatom < nop; iatom++) {
769 (*atomTypes)[iatom] += maxDepth - 2;
772 (*atomTypes)[iatom] = 2;
793 int firstFrame,
int currentFrame) {
796 double shiftDistance;
797 double distFrmBoundary;
800 int axialDim = std::max_element(yCloud->box.begin(), yCloud->box.end()) -
803 if (axialDim < 0 || axialDim > 2) {
807 double boxLowAxial = yCloud->boxLow[axialDim];
808 double boxHighAxial = boxLowAxial + yCloud->box[axialDim];
814 if (currentFrame == firstFrame) {
815 *atomID = yCloud->pts[0].atomID;
820 int iatomID = *atomID;
822 auto it = yCloud->idIndexMap.find(iatomID);
824 if (it != yCloud->idIndexMap.end()) {
825 atomIndex = it->second;
828 std::cerr <<
"Lost atoms.\n" ;
836 shiftDistance = boxLowAxial - yCloud->pts[atomIndex].x;
838 else if (axialDim == 1) {
839 shiftDistance = boxLowAxial - yCloud->pts[atomIndex].y;
842 shiftDistance = boxLowAxial - yCloud->pts[atomIndex].z;
846 for (
int iatom = 0; iatom < yCloud->nop; iatom++) {
849 yCloud->pts[iatom].x += shiftDistance;
851 if (yCloud->pts[iatom].x < boxLowAxial) {
852 distFrmBoundary = boxLowAxial - yCloud->pts[iatom].x;
853 yCloud->pts[iatom].x = boxHighAxial - distFrmBoundary;
856 else if (axialDim == 1) {
857 yCloud->pts[iatom].y += shiftDistance;
859 if (yCloud->pts[iatom].y < boxLowAxial) {
860 distFrmBoundary = boxLowAxial - yCloud->pts[iatom].y;
861 yCloud->pts[iatom].y = boxHighAxial - distFrmBoundary;
865 yCloud->pts[iatom].z += shiftDistance;
867 if (yCloud->pts[iatom].z < boxLowAxial) {
868 distFrmBoundary = boxLowAxial - yCloud->pts[iatom].z;
869 yCloud->pts[iatom].z = boxHighAxial - distFrmBoundary;
int deformedPrismTypes(std::vector< ring::strucType > atomState, std::vector< int > *atomTypes, int maxDepth)
Get the atom type values for deformed prisms.
bool discardExtraTetragonBlocks(std::vector< int > *basal1, std::vector< int > *basal2, molSys::PointCloud< molSys::Point< double >, double > *yCloud)
int prismAnalysis(std::string path, std::vector< std::vector< int > > rings, std::vector< std::vector< int > > nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, int maxDepth, int *atomID, int firstFrame, int currentFrame, bool doShapeMatching=false)
int clearRingList(std::vector< std::vector< int > > &rings)
Erases memory for a vector of vectors for a list of rings.
int rmAxialTranslations(molSys::PointCloud< molSys::Point< double >, double > *yCloud, int *atomID, int firstFrame, int currentFrame)
Shift the entire ice nanotube and remove axial translations.
int assignPrismType(std::vector< std::vector< int > > rings, std::vector< int > listPrism, int ringSize, std::vector< ring::strucType > ringType, std::vector< int > *atomTypes, std::vector< ring::strucType > *atomState)
bool hasCommonElements(std::vector< int > ring1, std::vector< int > ring2)
std::vector< std::vector< int > > getSingleRingSize(std::vector< std::vector< int > > rings, int ringSize)
Returns a vector of vectors of rings of a single size.
bool relaxedPrismConditions(std::vector< std::vector< int > > nList, std::vector< int > *basal1, std::vector< int > *basal2)
bool basalPrismConditions(std::vector< std::vector< int > > nList, std::vector< int > *basal1, std::vector< int > *basal2)
std::vector< int > findPrisms(std::vector< std::vector< int > > rings, std::vector< strucType > *ringType, int *nPerfectPrisms, int *nImperfectPrisms, std::vector< std::vector< int > > nList, molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< double > *rmsdPerAtom, bool doShapeMatching=false)
@ Prism
The ring belongs to a prism block, classified according to the prism identification scheme.
@ unclassified
The ring is unclassified, which may be either water or a deformed type which cannot be classified by ...
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)
Eigen::MatrixXd getPointSetRefRing(int n, int axialDim)
int writePrismNum(std::string path, std::vector< int > nPrisms, std::vector< int > nDefPrisms, std::vector< double > heightPercent, int maxDepth, int currentFrame, int firstFrame)
int writeLAMMPSdataAllPrisms(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< std::vector< int > > nList, std::vector< int > atomTypes, int maxDepth, std::string path, bool doShapeMatching=false)
Write a data file for prisms of every type.
int writeLAMMPSdumpINT(molSys::PointCloud< molSys::Point< double >, double > *yCloud, std::vector< double > rmsdPerAtom, std::vector< int > atomTypes, int maxDepth, std::string path)
Write out a LAMMPS dump file containing the RMSD per atom.
double normHeightPercent(molSys::PointCloud< molSys::Point< double >, double > *yCloud, int nPrisms, double avgPrismHeight)
This contains a collection of points; contains information for a particular frame.
This contains per-particle information.
File containing functions used specific to quasi-one-dimensional topological network critera (the pri...
Copy