Revision: 20749 http://sourceforge.net/p/jmol/code/20749 Author: hansonr Date: 2015-08-31 18:04:43 +0000 (Mon, 31 Aug 2015) Log Message: ----------- Jmol.___JmolVersion="14.3.16_2015.08.31"
new feature: Jmol SMILES/SMARTS generic stereoSMILES polyhedron option @PHn(....) -- totally generic; will work with any number of connected atoms -- suitable replacement for all TP, OH, etc. -- standard equivalence to [C@] is [C@PH4(234)] -- standard equivalence to [C@@] is [C@PH4(432)] -- "reverse" option via "!": [C@PH4(!234)] -- designation around any or all of the attached atoms is possible. For tetrahedra, this is redundant, but for higher number of vertices, it may not be. This designation is done using "." to separate atoms. -- so [C@] is [C@PH4(234)] or [C@PH4(!432)] or [C@PH4(.134)] -- implied H as in [CH@] will be atom 1 if this is the first atom; 2 if not -- Br[CH@].... (same as in standard tetrahedral) -- not implemented yet for SMARTS searching of SMILES strings $ load $2-bromobutane $ show smiles Br[C@@H](C)CC $ print {*}.find("Br[C@](C)(H)CC") ({0:5}) $ print {*}.find("Br[C@PH4(234)](C)(H)CC") ({0:5}) $ print {*}.find("Br[C@PH4(234)](H)(C)CC") ({}) $ print {*}.find("Br[C@PH4(432)](H)(C)CC") ({0:5}) $ print {*}.find("Br[CH@@](C)CC") ({0:4}) $ print {*}.find("Br[CH@PH4(.134)](C)CC") ({0:4}) $ print {*}.find("Br[CH@PH4(!.134)](C)CC") ({}) -- :) Modified Paths: -------------- trunk/Jmol/src/javajs/util/PT.java trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java trunk/Jmol/src/org/jmol/smiles/SmilesStereo.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties Modified: trunk/Jmol/src/javajs/util/PT.java =================================================================== --- trunk/Jmol/src/javajs/util/PT.java 2015-08-31 14:19:11 UTC (rev 20748) +++ trunk/Jmol/src/javajs/util/PT.java 2015-08-31 18:04:43 UTC (rev 20749) @@ -367,11 +367,11 @@ } public static int countChar(String line, char c) { - int tokenCount = 0; - int pt = -1; - while ((pt = line.indexOf(c, pt + 1)) >= 0) - tokenCount++; - return tokenCount; + int n = 0; + for (int i = line.lastIndexOf(c) + 1; --i >= 0;) + if (line.charAt(i) == '@') + n++; + return n; } public static int countTokens(String line, int ich) { Modified: trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java =================================================================== --- trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java 2015-08-31 14:19:11 UTC (rev 20748) +++ trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java 2015-08-31 18:04:43 UTC (rev 20749) @@ -224,8 +224,8 @@ return "none"; boolean check; // note: find smiles1 IN smiles2 here - int n1 = countStereo(smiles1); - int n2 = countStereo(smiles2); + int n1 = PT.countChar(PT.rep(smiles1, "@@", "@"), '@'); + int n2 = PT.countChar(PT.rep(smiles2, "@@", "@"), '@'); check = (n1 == n2 && areEqual(smiles2, smiles1) > 0); if (!check) { // MF matched, but didn't match SMILES @@ -250,15 +250,18 @@ /** * Note, this may be incompatible with [$(select(..))] + * + * THIS IS NOT DEPENDABLE. USE /invertStereo/ INSTEAD */ @Override public String reverseChirality(String smiles) { smiles = PT.rep(smiles, "@@", "!@"); smiles = PT.rep(smiles, "@", "@@"); smiles = PT.rep(smiles, "!@@", "@"); - smiles = PT.rep(smiles, "@@SP", "@SP"); - smiles = PT.rep(smiles, "@@OH", "@OH"); - smiles = PT.rep(smiles, "@@TB", "@TB"); + // note -- @@SP does not exist +// smiles = PT.rep(smiles, "@@SP", "@SP"); +// smiles = PT.rep(smiles, "@@OH", "@OH"); +// smiles = PT.rep(smiles, "@@TP", "@TP"); return smiles; } @@ -494,16 +497,6 @@ return null; } - private static int countStereo(String s) { - s = PT.rep(s, "@@", "@"); - int i = s.lastIndexOf('@') + 1; - int n = 0; - for (; --i >= 0;) - if (s.charAt(i) == '@') - n++; - return n; - } - @Override public String cleanSmiles(String smiles) { return SmilesParser.cleanPattern(smiles); Modified: trunk/Jmol/src/org/jmol/smiles/SmilesStereo.java =================================================================== --- trunk/Jmol/src/org/jmol/smiles/SmilesStereo.java 2015-08-31 14:19:11 UTC (rev 20748) +++ trunk/Jmol/src/org/jmol/smiles/SmilesStereo.java 2015-08-31 18:04:43 UTC (rev 20749) @@ -53,7 +53,6 @@ private SmilesSearch search; private Node[] jmolAtoms; private String directives; - final static int STEREOCHEMISTRY_MASK = 0xF; final static int STEREOCHEMISTRY_SQUARE_PLANAR = 8; final static int STEREOCHEMISTRY_OCTAHEDRAL = 6; final static int STEREOCHEMISTRY_TRIGONAL_BIPYRAMIDAL = 5; @@ -84,6 +83,7 @@ } private int[][] polyhedralOrders; + private boolean isNot; static PolyhedronStereoSorter polyhedronStereoSorter; private void getPolyhedralOrders() throws InvalidSmilesException { @@ -102,10 +102,14 @@ do { char ch = s.charAt(index); switch (ch) { + case '!': + isNot = true; + index++; + break; case '/': case '.': if ((pt = atomPt) >= atomCount) { - msg = "Too many descriptors."; + msg = "Too many descriptors"; break; } int[] a = po[atomPt] = new int[n]; @@ -123,13 +127,17 @@ default: index = SmilesParser.getRingNumber(s, index, ch, ret); pt = temp[n++] = ret[0] - 1; - if (pt < 0 || pt >= atomCount) + if (pt == atomPt) + msg = "Atom cannot connect to itself"; + else if (pt < 0 || pt >= atomCount) msg = "Connection number outside of range (1-" + atomCount + ")"; else if (n >= atomCount) msg = "Too many connections indicated"; } - if (msg != null) + if (msg != null) { + msg += ": " + s.substring(0, index) + "<<"; throw new InvalidSmilesException(msg); + } } while (index < len); } @@ -452,38 +460,63 @@ int nH = Math.max(sAtom.missingHydrogenCount, 0); int order = sAtom.stereo.chiralOrder; int chiralClass = sAtom.stereo.chiralClass; - if (isSmilesFind && ((SmilesAtom) atom0).getChiralClass() != chiralClass) + // SMILES string must match pattern for chiral class. + // but we could do something about changing those if desired. + if (isSmilesFind && sAtom0.getChiralClass() != chiralClass) return false; if (Logger.debugging) Logger.debug("...type " + chiralClass + " for pattern atom " + sAtom + " " + atom0); switch (chiralClass) { case STEREOCHEMISTRY_POLYHEDRAL: + if (sAtom.stereo.isNot) + isNot = !isNot; if (nH > 1) - continue; - if (nH == 1) { - // must create this atom temporarily - // TODO - continue; - } + continue; // no chirality for [CH2@] if (isSmilesFind) { // TODO continue; } + SmilesBond[] bonds = sAtom.bonds; + int jHpt = -1; + if (nH == 1) { + jHpt = (sAtom.isFirst ? 0 : 1); + // can't process this unless it is tetrahedral or perhaps square planar + if (sAtom.getBondCount() != 3) + return false; + v.vA.set(0, 0, 0); + for (int j = 0; j < 3; j++) + v.vA.add((T3)bonds[j].getOtherAtom(sAtom0).getMatchingAtom()); + v.vA.scale(0.3333f); + v.vA.sub2((T3) atom0, v.vA); + v.vA.add((T3) atom0); + } int[][] po = sAtom.stereo.polyhedralOrders; - SmilesBond[] bonds = sAtom.bonds; + int pt; for (int j = po.length; --j >= 0;) { int[] orders = po[j]; if (orders == null || orders.length < 2) continue; - sAtom1 = bonds[j - nH].getOtherAtom(sAtom); - atom1 = sAtom1.getMatchingAtom(); // the atom we are looking down - sAtom2 = bonds[orders[0] - nH].getOtherAtom(sAtom); - atom2 = sAtom2.getMatchingAtom(); + // the atom we are looking down + pt = (j > jHpt ? j - nH: j); + T3 ta1 = (j == jHpt ? v.vA : (T3) bonds[pt].getOtherAtom(sAtom).getMatchingAtom()); float flast = (isNot ? Float.MAX_VALUE : 0); - for (int k = 1; k < orders.length; k++) { - atom3 = bonds[orders[k] - nH].getOtherAtom(sAtom).getMatchingAtom(); - float f = Measure.computeTorsion((T3) atom3, (T3)atom1, (T3) atom0, (T3) atom2, true); + T3 ta2 = null; + for (int k = 0; k < orders.length; k++) { + pt = orders[k]; + T3 ta3; + if (pt == jHpt) { // attached H + ta3 = v.vA; + } else { + if (pt > jHpt) + pt--; + ta3 = (T3) bonds[pt].getOtherAtom(sAtom).getMatchingAtom(); + } + if (k == 0) { + ta2 = ta3; + continue; + } + float f = Measure.computeTorsion(ta3, ta1, (T3) atom0, ta2, true); if (Float.isNaN(f)) f = 180; // directly across the center from the previous atom if (orders.length == 2) Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-08-31 14:19:11 UTC (rev 20748) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2015-08-31 18:04:43 UTC (rev 20749) @@ -66,11 +66,16 @@ -- suitable replacement for all TP, OH, etc. -- standard equivalence to [C@] is [C@PH4(234)] -- standard equivalence to [C@@] is [C@PH4(432)] + -- "reverse" option via "!": [C@PH4(!234)] + -- designation around any or all of the attached atoms is possible. For tetrahedra, this is + redundant, but for higher number of vertices, it may not be. This designation is + done using "." to separate atoms. + -- so [C@] is [C@PH4(234)] or [C@PH4(!432)] or [C@PH4(.134)] + -- implied H as in [CH@] will be atom 1 if this is the first atom; 2 if not -- Br[CH@].... + (same as in standard tetrahedral) - -- not implemented yet for implied H -- not implemented yet for SMARTS searching of SMILES strings - - + $ load $2-bromobutane $ show smiles Br[C@@H](C)CC @@ -82,6 +87,12 @@ ({}) $ print {*}.find("Br[C@PH4(432)](H)(C)CC") ({0:5}) + $ print {*}.find("Br[CH@@](C)CC") + ({0:4}) + $ print {*}.find("Br[CH@PH4(.134)](C)CC") + ({0:4}) + $ print {*}.find("Br[CH@PH4(!.134)](C)CC") + ({}) -- :) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits