Revision: 21486 http://sourceforge.net/p/jmol/code/21486 Author: hansonr Date: 2017-04-06 20:58:28 +0000 (Thu, 06 Apr 2017) Log Message: ----------- Jmol.___JmolVersion="14.12.0-beta" // 2017-04-06
new feature: {atom}.chirality -- uses Cohen-Ingold-Prelog rules to assign R or S to a carbon center -- ignores sulfur chirality -- not fully tested -- does not fully implement high symmetry cases Modified Paths: -------------- trunk/Jmol/src/org/jmol/api/SmilesMatcherInterface.java trunk/Jmol/src/org/jmol/api/SymmetryInterface.java trunk/Jmol/src/org/jmol/modelset/Atom.java trunk/Jmol/src/org/jmol/modelset/LabelToken.java trunk/Jmol/src/org/jmol/modelset/ModelSet.java trunk/Jmol/src/org/jmol/script/T.java trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java trunk/Jmol/src/org/jmol/symmetry/Symmetry.java trunk/Jmol/src/org/jmol/util/Elements.java trunk/Jmol/src/org/jmol/util/Node.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties Added Paths: ----------- trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java Modified: trunk/Jmol/src/org/jmol/api/SmilesMatcherInterface.java =================================================================== --- trunk/Jmol/src/org/jmol/api/SmilesMatcherInterface.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/api/SmilesMatcherInterface.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -56,4 +56,6 @@ public int[][] getMapForJME(String jme, Atom[] at, BS bsAtoms); + public int getChirality(Node atom4, Node atom3, Node atom2, Node atom1); + } Modified: trunk/Jmol/src/org/jmol/api/SymmetryInterface.java =================================================================== --- trunk/Jmol/src/org/jmol/api/SymmetryInterface.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/api/SymmetryInterface.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -218,4 +218,6 @@ void toFractionalM(M4 m); + public String getChirality(Viewer vwr, Atom atom); + } Modified: trunk/Jmol/src/org/jmol/modelset/Atom.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/Atom.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/modelset/Atom.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -25,6 +25,8 @@ package org.jmol.modelset; +import javax.annotation.processing.RoundEnvironment; + import javajs.util.CU; import javajs.util.Lst; import javajs.util.PT; @@ -1317,6 +1319,12 @@ return group.chain.model.ms.getVibCoord(i, ch); } + @Override + + public int getNominalMass() { + return Math.round(getMass()); + } + private float getMass() { float mass = getIsotopeNumber(); return (mass > 0 ? mass : Elements.getAtomicMass(getElementNumber())); @@ -1335,6 +1343,8 @@ return getAtomType(); case T.chain: return getChainIDStr(); + case T.chirality: + return getChirality(); case T.sequence: return getGroup1('?'); case T.seqcode: @@ -1373,6 +1383,14 @@ return ""; } + /** + * Determine R/S chirality at this position + * @return "" or "R" or "S" + */ + private String getChirality() { + return group.chain.model.ms.getChirality(this); + } + @Override public char getInsertionCode() { return group.getInsertionCode(); Modified: trunk/Jmol/src/org/jmol/modelset/LabelToken.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/LabelToken.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/modelset/LabelToken.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -168,7 +168,8 @@ T.screeny, T.screenz, T.screenxyz, // added in 12.3.30 T.magneticshielding, T.chemicalshift, T.chainno, T.seqid, T.modx, T.mody, T.modz, T.modo, T.modxyz, T.symop, - T.nbo // added in 14.8.2 + T.nbo, // added in 14.8.2 + T.chirality // added in 14.11.4 }; public LabelToken() { Modified: trunk/Jmol/src/org/jmol/modelset/ModelSet.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/ModelSet.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/modelset/ModelSet.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -4068,7 +4068,11 @@ return (dssrData == null || dssrData.length <= i ? Float.NaN : dssrData[i]); } + public String getChirality(Atom atom) { + return Interface.getSymmetry(vwr, "ms").getChirality(vwr, atom); + } + } Modified: trunk/Jmol/src/org/jmol/script/T.java =================================================================== --- trunk/Jmol/src/org/jmol/script/T.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/script/T.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -555,6 +555,7 @@ public final static int strucid = strproperty |13; public final static int symbol = strproperty |14 | settable; public final static int symmetry = strproperty |15 | predefinedset; + public final static int chirality = strproperty |16; public final static int atomno = intproperty | 1 | settable; public final static int atomid = intproperty | 2; @@ -2361,6 +2362,7 @@ "bondmode", "boundBoxColor", "boundingBoxColor", + "chirality", "currentLocalPath", "dataSeparator", "defaultAngleLabel", @@ -3407,6 +3409,7 @@ bondmode, // "bondmode" boundboxcolor, // "boundBoxColor" -1, // "boundingBoxColor" + chirality, currentlocalpath, // "currentLocalPath" dataseparator, // "dataSeparator" defaultanglelabel, // "defaultAngleLabel" Modified: trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java =================================================================== --- trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -851,5 +851,11 @@ return Float.NaN; } + @Override + public int getNominalMass() { + // TODO + return getAtomicMass(); + } + } Modified: trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java =================================================================== --- trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -581,4 +581,9 @@ return null; } + @Override + public int getChirality(Node atom4, Node atom3, Node atom2, Node atom1) { + return SmilesStereo.getHandedness(atom4, atom3, atom2, atom1, new VTemp()); + } + } Added: trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java =================================================================== --- trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java (rev 0) +++ trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -0,0 +1,233 @@ +package org.jmol.symmetry; + +import java.util.Arrays; + +import javajs.util.BS; + +import org.jmol.api.SmilesMatcherInterface; +import org.jmol.util.Edge; +import org.jmol.util.Logger; +import org.jmol.util.Node; +import org.jmol.viewer.Viewer; + +public class CIPChirality { + + Viewer vwr; + BS bsFound; + + public CIPChirality() { + // for reflection + } + + public CIPChirality setViewer(Viewer vwr) { + this.vwr = vwr; + return this; + } + + public String getChirality(Node atom) { + if (atom.getCovalentBondCount() != 4) + return ""; + bsFound = new BS(); + CIPAtom a = new CIPAtom(atom, null, false); + + String rs = (a.set() ? getRorS(a) : ""); + if (Logger.debugging) + Logger.info(atom + " " + rs); + + return rs; + } + + public String getRorS(CIPAtom a) { + try { + if (!a.sortAtoms()) + return ""; + SmilesMatcherInterface sm = vwr.getSmilesMatcher(); + switch (sm.getChirality(a.atoms[3].atom, a.atoms[2].atom, + a.atoms[1].atom, a.atoms[0].atom)) { + case 1: + return "R"; + case 2: + return "S"; + default: + return ""; + } + } catch (Throwable e) { + e.printStackTrace(); + return ""; + } + } + + private class CIPAtom implements Comparable<CIPAtom> { + String path = ";"; + Node atom; + boolean isDummy = true; + boolean isTerminal; + boolean isSet; + int isAbove; + CIPAtom parent; + CIPAtom[] atoms; + private int nAtoms; + + @Override + public String toString() { + return path + " " + atom + (isDummy ? " *" : ""); + } + + public CIPAtom(Node atom, CIPAtom parent, boolean isDummy) { + if (atom == null) + return; + this.atom = atom; + this.isTerminal = atom.getCovalentBondCount() == 1; + int iatom = atom.getIndex(); + if (bsFound.get(iatom)) { + isDummy = true; + } else { + bsFound.set(iatom); + this.isDummy = isDummy; + } + this.parent = parent; + if (parent != null) + path = parent.path; + path += getPathString(); + } + + private String getPathString() { + String elemno = "000" + atom.getElementNumber(); + String mass = "00" + (isDummy ? 0 : atom.getNominalMass()); + return elemno.substring(elemno.length() - 3) + "_" + + mass.substring(mass.length() - 3) + ";"; + } + + boolean set() { + if (isTerminal) + return true; + if (isSet) + return true; + atoms = new CIPAtom[parent == null ? 4 : 3]; + int nBonds = atom.getBondCount(); + Edge[] bonds = atom.getEdges(); + int pt = 0; + for (int i = 0; i < nBonds; i++) { + Edge bond = bonds[i]; + if (!bond.isCovalent()) + continue; + Node other = bond.getOtherAtomNode(atom); + if (parent != null && parent.atom == other) + continue; + int order = bond.getCovalentOrder(); + switch (order) { + case 3: + if (!addAtom(pt++, other, true)) { + isTerminal = true; + return false; + } + //$FALL-THROUGH$ + case 2: + if (!addAtom(pt++, other, true)) { + isTerminal = true; + return false; + } + //$FALL-THROUGH$ + case 1: + if (!addAtom(pt++, other, false)) { + isTerminal = true; + return false; + } + break; + default: + isTerminal = true; + return false; + } + } + isTerminal = (pt == 0); + nAtoms = pt; + for (; pt < atoms.length; pt++) + atoms[pt] = new CIPAtom(null, null, true); + return !isTerminal; + } + + private boolean addAtom(int i, Node other, boolean isDummy) { + if (i >= atoms.length) + return false; + atoms[i] = new CIPAtom(other, this, isDummy); + return true; + } + + boolean sortAtoms() { + + for (int i = 0; i < nAtoms; i++) { + CIPAtom a = atoms[i]; + for (int j = i + 1; j < nAtoms; j++) { + CIPAtom b = atoms[j]; + int score = (int) Math.signum(a.compareTo(b)); + if (Logger.debugging) + Logger.info("comparing " + a + " and " + b + " = " + score); + switch (score) { + case 1: + a.isAbove++; + break; + case -1: + b.isAbove++; + break; + case 0: + switch (breakTie(a, b)) { + case 1: + a.isAbove++; + break; + case -1: + b.isAbove++; + break; + case 0: + return false; + } + } + } + } + for (int i = 0; i < nAtoms; i++) + atoms[i].path += ";" + atoms[i].isAbove; + Arrays.sort(atoms); + if (Logger.debugging) + for (int i = 0; i < nAtoms; i++) + Logger.info("" + atoms[i]); + return true; + } + + private int breakTie(CIPAtom a, CIPAtom b) { + if (a.isDummy || !a.set() || !b.set() || a.isTerminal || a.atom == b.atom) + return 0; + if (Logger.debugging) + Logger.info("tie for " + a + " and " + b); + Arrays.sort(a.atoms); + Arrays.sort(b.atoms); + // check to see if any of the three connections to a and b are different. + for (int i = 0; i < a.nAtoms; i++) { + int score = (int) Math.signum(a.atoms[i].compareTo(b.atoms[i])); + switch (score) { + case -1: + case 1: + return score; + } + } + // all are the same -- check to break tie next level + for (int i = 0; i < a.nAtoms; i++) { + int score = breakTie(a.atoms[i], b.atoms[i]); + switch (score) { + case -1: + case 1: + return score; + } + } + // all are the same and no tie breakers + return 0; + } + + @Override + public int compareTo(CIPAtom a) { + // check to see that atoms are non-null and are different, and path is different + return a.atom == null && atom == null ? 0 : a.atom == null ? -1 + : atom == null ? 1 : a.atom == atom ? 0 : -a.path.compareTo(path); + } + + } + +} Property changes on: trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Modified: trunk/Jmol/src/org/jmol/symmetry/Symmetry.java =================================================================== --- trunk/Jmol/src/org/jmol/symmetry/Symmetry.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/symmetry/Symmetry.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -765,4 +765,16 @@ return lst; } + @Override + public String getChirality(Viewer vwr, Atom atom) { + CIPChirality cip = getCIPChirality(vwr); + return cip.getChirality(atom); + } + + CIPChirality cip; + + private CIPChirality getCIPChirality(Viewer vwr) { + return (cip == null ? (cip = ((CIPChirality) Interface.getInterface("org.jmol.symmetry.CIPChirality", vwr, "script"))).setViewer(vwr) : cip); + } + } Modified: trunk/Jmol/src/org/jmol/util/Elements.java =================================================================== --- trunk/Jmol/src/org/jmol/util/Elements.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/util/Elements.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -475,7 +475,7 @@ // add as we go - private final static String naturalIsotopes = "1H,12C,14N,"; + private final static String naturalIsotopes = "1H,12C,14N"; public final static boolean isNaturalIsotope(String isotopeSymbol) { return (naturalIsotopes.indexOf(isotopeSymbol + ",") >= 0); Modified: trunk/Jmol/src/org/jmol/util/Node.java =================================================================== --- trunk/Jmol/src/org/jmol/util/Node.java 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/util/Node.java 2017-04-06 20:58:28 UTC (rev 21486) @@ -46,6 +46,7 @@ public int getValence(); public void set(float x, float y, float z); public int getMoleculeNumber(boolean inModel); + public int getNominalMass(); /** Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2017-04-06 12:09:34 UTC (rev 21485) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2017-04-06 20:58:28 UTC (rev 21486) @@ -49,8 +49,16 @@ # 10. Run jmol/tools build-release.xml # -Jmol.___JmolVersion="14.11.3" // 2017-04-06 +Jmol.___JmolVersion="14.12.0-beta" // 2017-04-06 +new feature: {atom}.chirality + -- uses Cohen-Ingold-Prelog rules to assign R or S to a carbon center + -- ignores sulfur chirality + -- not fully tested + -- does not fully implement high symmetry cases + +JmolVersion="14.11.3" // 2017-04-06 + bug fix: partial bond order for orders > 3 not working -- for example: connect {_C} {_C} partial 5.3 bug fix: NBO MODEL loading with no file name goes to wrong directory 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