Revision: 21552 http://sourceforge.net/p/jmol/code/21552 Author: hansonr Date: 2017-04-25 21:39:12 +0000 (Tue, 25 Apr 2017) Log Message: ----------- CIP -- very close to complete for Rule 4; just working on Example 6
Modified Paths: -------------- trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java Modified: trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java =================================================================== --- trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java 2017-04-25 15:57:35 UTC (rev 21551) +++ trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java 2017-04-25 21:39:12 UTC (rev 21552) @@ -1621,21 +1621,47 @@ String aStr = rule4List[ia]; String bStr = rule4List[ib]; - if (aStr != null && aStr.indexOf("?") == 0) { - aStr = getMataList(atoms[ia].rule4List); - bStr = getMataList(atoms[ib].rule4List); + if (aStr != null && aStr.indexOf("?") == 1) { + aStr = getMataList(ia); + bStr = getMataList(ib); if (aStr.length() != bStr.length()) { // bStr must have R and S options, but aStr does not return (aStr.length() < bStr.length() ? A_WINS : B_WINS); } - if (aStr.indexOf("|") >= 0 || bStr.indexOf("|") >= 0) - return TIED; // TODO! + if (aStr.indexOf("|") >= 0 || bStr.indexOf("|") >= 0) { + // Mata(2005) Figure 9 + // TODO: Still some issues here.... + // We are trying to ascertain that + // R lull R luuu + // S luuu is the same as S lull + // maybe "min for one is the same as min for the other?" + // + String[] aList = PT.split(aStr, "|"); + String[] bList = PT.split(bStr, "|"); + int minScore = Integer.MAX_VALUE; + aStr = aList[0]; + bStr = bList[0]; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + int score = compareRule4PairStr(aList[i], bList[j], true); + if (score <= minScore) { + minScore = score; + aStr = aList[i]; + bStr = bList[j]; + } + } + } + } + } else { + // trim off priority numbers + aStr = PT.rep(aStr.substring(1), "~", ""); + bStr = PT.rep(bStr.substring(1), "~", ""); } + return compareRule4PairStr(aStr, bStr, false); + } - // TODO: preliminary only. The challenge is to get these strings lined up right. - aStr = PT.rep(aStr, "~", ""); - bStr = PT.rep(bStr, "~", ""); - System.out.println("Rule 4b comparing " + aStr + " " + bStr); + private int compareRule4PairStr(String aStr, String bStr, boolean isRSTest) { + System.out.println(this + " Rule 4b comparing " + aStr + " " + bStr); doCheckPseudo = false; int n = aStr.length(); if (n == 0 || n != bStr.length()) @@ -1646,8 +1672,10 @@ boolean alike = (aref == aStr.charAt(c)); boolean blike = (bref == bStr.charAt(c)); if (alike != blike) - return (alike ? A_WINS : B_WINS); + return (isRSTest ? c : alike ? A_WINS : B_WINS); } + if (isRSTest) + return TIED; if (aref == bref) return IGNORE; doCheckPseudo = (aref == 'R' || aref == 'S'); @@ -1654,8 +1682,16 @@ return aref < bref ? A_WINS : B_WINS; } - private String getMataList(String[] rule4List) { - String[] listA = condenseList(rule4List); + private String getMataList(int ia) { + String[] rule4List = atoms[ia].rule4List; + int n = 0; + for (int i = rule4List.length; --i >= 0;) + if (rule4List[i] != null) + n++; + String[] listA = new String[n]; + for (int i = rule4List.length; --i >= 0;) + if (rule4List[i] != null) + listA[--n] = rule4List[i]; Arrays.sort(listA); String aref = getMataRef(listA); switch (aref.length()) { @@ -1679,17 +1715,21 @@ String rs = lst[i]; if (rs.length() > len) len = rs.length(); - if (rs.startsWith(aref)) + if (rs.indexOf(aref) == 1) sorted[pt++] = rs; } for (int i = 0; i < n; i++) { String rs = lst[i]; - if (!rs.startsWith(aref)) + if (rs.indexOf(aref) != 1) sorted[pt++] = rs; } + + for (int i = 0; i < n; i++) { + System.out.println("Sorted Mata list " + i + " " + sorted[i]); + } String mlist = ""; char ch; - for (int i = 0; i < len; i++) { + for (int i = 1; i < len; i++) { for (int j = 0; j < n; j++) { String rs = sorted[j]; if (i < rs.length() && (ch = rs.charAt(i)) != '~' && ch != ';') @@ -1700,113 +1740,58 @@ } private String getMataRef(String[] lst) { - // TODO: does not take into consideration initial ~~ - switch (lst.length) { + // get highest-ranking chiral unit + int pt = Integer.MAX_VALUE; + for (int i = 0; i < lst.length; i++) { + String s = lst[i]; + int j = 1; + for (int n = s.length(); j < n; j++) + if (s.charAt(j) != '~') + break; + if (j < pt) + pt = j; + } + switch (lst.length) { case 1: // R or S - return lst[0].substring(0, 1); + return lst[0].substring(pt, pt + 1); case 2: - // RR RS SR SS - return (lst[0].charAt(0) == lst[1].charAt(0) ? - lst[0].substring(0, 1) : "RS"); + // 1R2R 1R2S 1S2R 1S2S + // 1R1R 1R1S 1S1R 1S1S + // 1R1~ 1S1~ 1R2~ 1S2~ + // 1~2R 1~2S + char pa = lst[0].charAt(0); + char pb = lst[1].charAt(0); + char ca = lst[0].charAt(pt); + char cb = lst[1].charAt(pt); + return (ca == cb || cb == '~' || pa < pb && ca != '~' ? "" + ca + : pa == pb ? "RS" : "" + cb); case 3: - return lst[1].substring(0, 1); + char p1 = lst[0].charAt(0); + char p2 = lst[1].charAt(0); + char p3 = lst[2].charAt(0); + char c1 = lst[0].charAt(pt); + char c2 = lst[1].charAt(pt); + char c3 = lst[2].charAt(pt); + // 1 1 1 + if (p1 == p2 && p2 == p3) + return (c1 == c2 || c2 == '~' ? "" + c1 // RRR RRS SSS RR~ SS~ R~~ S~~ + : c2 == c3 ? "" + c3 // RSS SSS + : "RS" // RS~ + ); + // 1 1 2 + if (p1 == p2) + return (p1 == '~' ? "" + c3 : c1 == c2 || c2 == '~' ? "" + c1 : "RS"); + // 1 2 2 + if (p2 == p3) + return (p1 != '~' ? "" + c1 : c2 == c3 || c3 == '~' ? "" + c2 : "RS"); + // 1 2 3 + return "" + (c1 != '~' ? c1 : c2 != '~' ? c2 : c3); } return ""; } /** - * remove unnecessary nulls - * @param a - * @return trimmed array - */ - private String[] condenseList(String[] a) { - int n = 0; - for (int i = a.length; --i >= 0;) - if (a[i] != null) - n++; - String[] b = new String[n]; - for (int i = a.length; --i >= 0;) - if (a[i] != null) - b[--n] = a[i]; - return b; - } - - /** - * Reverse the path to the parent and check r/s chirality - * - * @param ties - * @param indices - * - */ - private void checkPseudoHandedness(BS ties, int[] indices) { - int ia = ties.nextSetBit(0); - int ib = ties.nextSetBit(ia + 1); - CIPAtom atom1; - if (auxPseudo == null) { - // critical here that we do NOT include the tied branches - atom1 = (CIPAtom) clone(); - atom1.atoms[indices[ia]] = new CIPAtom(null, atom1, false, isAlkene); - atom1.atoms[indices[ib]] = new CIPAtom(null, atom1, false, isAlkene); - atom1.addReturnPath(null, this); - } else { - atom1 = auxPseudo; - } - int thisRule = currentRule; - currentRule = RULE_1; - atom1.sortSubstituents(); - currentRule = thisRule; - // Now add the tied branches at the end; it doesn't matter where they - // go as long as they are together and in order. - atom1.atoms[bondCount - 2] = atoms[Math.min(indices[ia], indices[ib])]; - atom1.atoms[bondCount - 1] = atoms[Math.max(indices[ia], indices[ib])]; - int rs = atom1.checkHandedness(); - if (Logger.debugging) { - for (int i = 0; i < 4; i++) - Logger.info("pseudo " + rs + " " + priorities[i] + " " - + atoms[i].myPath); - } - if (rs == STEREO_R || rs == STEREO_S) { - isPseudo = true; - } - } - - - /** - * - * Create a priority key that matches elemNo and massNo. - * - * We can skip the duplicate flag, because all these have substituents. - * - * @param a - * @return a shifted key based on elemNo and massNo - */ - private int getBasePriority(CIPAtom a) { - int code = 0; - if (a.atom == null) { - code = 0x7FFFF << PRIORITY_SHIFT[2]; - } else { - code = ((127 - a.elemNo) << PRIORITY_SHIFT[0]) - | ((255 - a.massNo) << PRIORITY_SHIFT[2]); - } - return code; - } - - - /** - * reset auxEZ chirality to "undetermined" - */ - void resetAuxiliaryChirality() { - auxEZ = STEREO_UNDETERMINED; - for (int i = 0; i < 4; i++) - if (atoms[i] != null && atoms[i].atom != null) - atoms[i].resetAuxiliaryChirality(); - if (auxParentReversed != null) - auxParentReversed.resetAuxiliaryChirality(); - if (auxPseudo != null) - auxPseudo.resetAuxiliaryChirality(); - } - /** * This method creates a list of downstream (higher-sphere) auxiliary chirality designators * R, S, r, and s that are passed upstream ultimately to the Sphere-1 root substituent. * @@ -1832,8 +1817,8 @@ for (int i = 0; i < 4; i++) { CIPAtom a = atoms[i]; if (a != null && !a.isDuplicate && !a.isTerminal) { - String ssub = rule4List[i] = a - .createAuxiliaryRSCenters(false); + String ssub = a.createAuxiliaryRSCenters(false); + rule4List[i] = priorities[i] + ssub; if ("sr".indexOf(ssub) >= 0 || ssub.indexOf("R") >= 0 || ssub.indexOf("S") >= 0) { mataList[nRS] = i; nRS++; @@ -1840,7 +1825,7 @@ subRS += ssub + ";"; } else { rule4List[i] = null; - subRS += "~"; +// subRS += "~"; } } } @@ -1860,6 +1845,7 @@ break; case NOT_RELEVANT: // create a ?<sphere>[....] object ? + done = false; adj = TIED; break; case TIED: @@ -1899,8 +1885,7 @@ } } s += subRS; - if (sphere < 2 && !done) - System.out.println(this + " creating aux " + s); + System.out.println(this + " creating aux " + s); return s; } @@ -1915,7 +1900,9 @@ * if diastereomeric */ private int compareRule4aEnantiomers(String rs1, String rs2) { - if (rs1.indexOf("R") < 0 && rs1.indexOf("S") < 0) + + if (rs1.indexOf("R") < 0 && rs1.indexOf("S") < 0 + || rs1.charAt(0) != rs2.charAt(0)) return NOT_RELEVANT; int n = rs1.length(); if (n != rs2.length()) @@ -1935,6 +1922,81 @@ } /** + * Reverse the path to the parent and check r/s chirality + * + * @param ties + * @param indices + * + */ + private void checkPseudoHandedness(BS ties, int[] indices) { + int ia = ties.nextSetBit(0); + int ib = ties.nextSetBit(ia + 1); + CIPAtom atom1; + if (auxPseudo == null) { + // critical here that we do NOT include the tied branches + atom1 = (CIPAtom) clone(); + atom1.atoms[indices[ia]] = new CIPAtom(null, atom1, false, isAlkene); + atom1.atoms[indices[ib]] = new CIPAtom(null, atom1, false, isAlkene); + atom1.addReturnPath(null, this); + } else { + atom1 = auxPseudo; + } + int thisRule = currentRule; + currentRule = RULE_1; + atom1.sortSubstituents(); + currentRule = thisRule; + // Now add the tied branches at the end; it doesn't matter where they + // go as long as they are together and in order. + atom1.atoms[bondCount - 2] = atoms[Math.min(indices[ia], indices[ib])]; + atom1.atoms[bondCount - 1] = atoms[Math.max(indices[ia], indices[ib])]; + int rs = atom1.checkHandedness(); + if (Logger.debugging) { + for (int i = 0; i < 4; i++) + Logger.info("pseudo " + rs + " " + priorities[i] + " " + + atoms[i].myPath); + } + if (rs == STEREO_R || rs == STEREO_S) { + isPseudo = true; + } + } + + + /** + * + * Create a priority key that matches elemNo and massNo. + * + * We can skip the duplicate flag, because all these have substituents. + * + * @param a + * @return a shifted key based on elemNo and massNo + */ + private int getBasePriority(CIPAtom a) { + int code = 0; + if (a.atom == null) { + code = 0x7FFFF << PRIORITY_SHIFT[2]; + } else { + code = ((127 - a.elemNo) << PRIORITY_SHIFT[0]) + | ((255 - a.massNo) << PRIORITY_SHIFT[2]); + } + return code; + } + + + /** + * reset auxEZ chirality to "undetermined" + */ + void resetAuxiliaryChirality() { + auxEZ = STEREO_UNDETERMINED; + for (int i = 0; i < 4; i++) + if (atoms[i] != null && atoms[i].atom != null) + atoms[i].resetAuxiliaryChirality(); + if (auxParentReversed != null) + auxParentReversed.resetAuxiliaryChirality(); + if (auxPseudo != null) + auxPseudo.resetAuxiliaryChirality(); + } + + /** * Swap a substituent and the parent in preparation for reverse traversal of * this path * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits