Revision: 21533
          http://sourceforge.net/p/jmol/code/21533
Author:   hansonr
Date:     2017-04-22 12:47:41 +0000 (Sat, 22 Apr 2017)
Log Message:
-----------
CIP carbonyl fixes; adding P and S

Modified Paths:
--------------
    trunk/Jmol/src/javajs/util/Measure.java
    trunk/Jmol/src/org/jmol/modelset/Atom.java
    trunk/Jmol/src/org/jmol/scriptext/MathExt.java
    trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java
    trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java
    trunk/Jmol/src/org/jmol/util/Node.java
    trunk/Jmol/src/org/jmol/viewer/JC.java
    trunk/Jmol/src/org/jmol/viewer/Jmol.properties

Modified: trunk/Jmol/src/javajs/util/Measure.java
===================================================================
--- trunk/Jmol/src/javajs/util/Measure.java     2017-04-21 23:05:05 UTC (rev 
21532)
+++ trunk/Jmol/src/javajs/util/Measure.java     2017-04-22 12:47:41 UTC (rev 
21533)
@@ -232,7 +232,6 @@
   }
   
   /**
-   * if vAC is dispensible vNorm can be vAC
    * @param pointA
    * @param pointB
    * @param pointC

Modified: trunk/Jmol/src/org/jmol/modelset/Atom.java
===================================================================
--- trunk/Jmol/src/org/jmol/modelset/Atom.java  2017-04-21 23:05:05 UTC (rev 
21532)
+++ trunk/Jmol/src/org/jmol/modelset/Atom.java  2017-04-22 12:47:41 UTC (rev 
21533)
@@ -90,11 +90,6 @@
   private final static int VIBRATION_VECTOR_FLAG = 1;
   private final static int IS_HETERO_FLAG = 2;
   private final static int CIP_CHIRALITY_OFFSET = 4;
-  private final static int CIP_CHIRALITY_R_FLAG = 1;
-  private final static int CIP_CHIRALITY_S_FLAG = 2; // 3 is "no chirality"
-  private final static int CIP_CHIRALITY_PSEUDO_FLAG = 4;  // 5=r, 6=s, 7=* 
(undetermined)
-  private final static int CIP_CHIRALITY_Z_FLAG = 8;
-  private final static int CIP_CHIRALITY_E_FLAG = 0x10; // Z|E is "no 
chirality"
   private final static int CIP_CHIRALITY_MASK = 0xFF0;
   private final static int FLAG_MASK = 0xF;
 
@@ -749,6 +744,11 @@
     return (ch == 'X' ? pt.x : ch == 'Y' ? pt.y : pt.z);
   }
     
+  @Override
+  public P3 getXYZ() {
+    return this;
+  }
+  
   public P3 getFractionalCoordPt(boolean fixJavaFloat, boolean ignoreOffset, 
P3 pt) {
     // ignoreOffset TRUE uses the original unshifted matrix
     SymmetryInterface c = getUnitCell();
@@ -1399,7 +1399,7 @@
    * Determine R/S chirality at this position; non-H atoms only; cached in 
formalChargeAndFlags
    * @param doCalculate 
    * 
-   * @return one of "", "R", "S", "E", "Z", "(r)", "(s)", "(*)"
+   * @return one of "", "R", "S", "E", "Z", "r", "s", "?"
    */
   @Override
   public String getCIPChirality(boolean doCalculate) {
@@ -1408,24 +1408,7 @@
       flags = group.chain.model.ms.getAtomCIPChirality(this);
       formalChargeAndFlags |= ((flags == 0 ? 3 : flags) << 
CIP_CHIRALITY_OFFSET);
     }
-    switch (flags) {
-    case CIP_CHIRALITY_Z_FLAG:
-      return "Z";
-    case CIP_CHIRALITY_E_FLAG:
-      return "E";
-    case CIP_CHIRALITY_R_FLAG:
-      return "R";
-    case CIP_CHIRALITY_S_FLAG:
-      return "S";
-    case CIP_CHIRALITY_PSEUDO_FLAG | CIP_CHIRALITY_R_FLAG:
-      return "(r)";
-    case CIP_CHIRALITY_PSEUDO_FLAG | CIP_CHIRALITY_S_FLAG:
-      return "(s)";
-    case CIP_CHIRALITY_PSEUDO_FLAG | CIP_CHIRALITY_S_FLAG | 
CIP_CHIRALITY_R_FLAG:
-      return "(*)";
-    default:
-      return "";
-    }
+    return (JC.getCIPChiralityName(flags));
   }
   
   /**

Modified: trunk/Jmol/src/org/jmol/scriptext/MathExt.java
===================================================================
--- trunk/Jmol/src/org/jmol/scriptext/MathExt.java      2017-04-21 23:05:05 UTC 
(rev 21532)
+++ trunk/Jmol/src/org/jmol/scriptext/MathExt.java      2017-04-22 12:47:41 UTC 
(rev 21533)
@@ -3003,7 +3003,11 @@
         : "\n");
     switch (args.length) {
     case 0:
+      break;
     case 1:
+      if (args[0].tok ==  T.on) {
+        return mp.addX(SV.getVariable(PT.getTokens(x.asString())));
+      }
       break;
     case 2:
       if (x.tok == T.varray)

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java      2017-04-21 23:05:05 UTC 
(rev 21532)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java      2017-04-22 12:47:41 UTC 
(rev 21533)
@@ -868,5 +868,10 @@
     // n/a
   }
 
+  @Override
+  public P3 getXYZ() {
+    return this;
+  }
 
+
 }

Modified: trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java
===================================================================
--- trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java  2017-04-21 23:05:05 UTC 
(rev 21532)
+++ trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java  2017-04-22 12:47:41 UTC 
(rev 21533)
@@ -7,6 +7,7 @@
 import javajs.util.Lst;
 import javajs.util.Measure;
 import javajs.util.P3;
+import javajs.util.P4;
 import javajs.util.PT;
 import javajs.util.V3;
 
@@ -265,6 +266,11 @@
   
   boolean useAuxiliaries;
 
+  
+  V3 vNorm = new V3();
+  V3 vNorm2 = new V3();
+  V3 vTemp = new V3();
+
   public CIPChirality() {
     // for reflection 
   }
@@ -313,7 +319,7 @@
       
     for (int i = bsToDo.nextSetBit(0); i >= 0; i = bsToDo.nextSetBit(i + 1)) {
       Node a = atoms[i];
-      if (a.getCovalentBondCount() != 4)
+      if (!couldBeChiral(a))
         continue;
       a.setCIPChirality(0);
       a.setCIPChirality(getAtomChiralityLimited(a, null, null, 5, -1));
@@ -320,6 +326,53 @@
     }
   }
 
+  private boolean couldBeChiral(Node a) {
+    boolean  mustBePlanar = false;
+    switch (a.getCovalentBondCount()) {
+    case 4:
+      break;
+    case 3:
+      switch (a.getElementNumber()) {
+      case 6: // C
+        mustBePlanar = true;
+        break;
+      case 15: // P
+      case 16: // S
+      case 33: // As
+      case 34: // Se
+      case 51: // Sb
+      case 52: // Te
+      case 83: // Bi
+      case 84: // Po
+        break;
+      default:
+        return false;
+      }
+      break;
+      // could add case 2 for imines here
+    default:
+      return false;
+    }
+    float d = getTrigonality(a);
+    return ((Math.abs(d) < 0.2f) == mustBePlanar); // arbitrarily set 
+  }
+
+  /**
+   * Determine the trigonality of an atom.
+   * 
+   * @param a
+   * @return height from plane of first three covalently bonded nodes to this 
node
+   */
+  float getTrigonality(Node a) {
+    P3[] pts = new P3[3];
+    Edge[] bonds = a.getEdges();
+    for (int i = bonds.length, pt = 0; --i >= 0 && pt < 3;)
+      if (bonds[i].isCovalent())
+        pts[pt++] = bonds[i].getOtherAtomNode(a).getXYZ();
+    P4 plane = Measure.getPlaneThroughPoints(pts[0], pts[1], pts[2], vNorm, 
vTemp, new P4());
+    return Measure.distanceToPlane(plane, a.getXYZ());
+  }
+
   private void init() {
     useAuxiliaries = false;
     nPriorityMax = maxRingSize = 0;
@@ -388,68 +441,71 @@
                                       CIPAtom parent, int ruleMax, int iref) {
     int rs = NO_CHIRALITY;
     boolean isChiral = false;
-    if (cipAtom != null)
+    boolean isAlkene = false;
+    if (cipAtom == null) {
+      int nSubs = atom.getCovalentBondCount();
+      int elemNo = atom.getElementNumber();
+      isAlkene = (nSubs == 3 && elemNo < 10);
+      if (nSubs != (parent == null ? 4 : 3) - (nSubs == 3 && !isAlkene ? 1 : 
0))
+        return rs;
+      htPathPoints = new Hashtable<String, Integer>();
+      cipAtom = new CIPAtom(atom, null, false, isAlkene);
+    } else {
       atom = cipAtom.atom;
-    int nSubs = atom.getCovalentBondCount();
-    boolean isAlkene = (nSubs == 3);
-    if (nSubs == (parent == null ? 4 : 3)) {
-      if (cipAtom == null) {
-        htPathPoints = new Hashtable<String, Integer>();
-        cipAtom = new CIPAtom(atom, null, false);
-      }
-      root = cipAtom;
-      cipAtom.parent = parent;
-      currentRule = RULE_1;
-      if (cipAtom.set()) {
-        try {
-          if (iref >= 0)
-            cipAtom.bsPath.set(iref);
-          boolean doResetAux = false;
-          for (currentRule = RULE_1; currentRule <= ruleMax && !isChiral; 
currentRule++) {
-            if (Logger.debugging)
-              Logger.info("-Rule " + getRuleName() + " CIPChirality for "
-                  + cipAtom + "-----");
-            
-            if (currentRule == RULE_4 && useAuxiliaries) {
-              cipAtom.createAuxiliaryRSCenters("", true);
-              doResetAux = true;
-            }
+      isAlkene = cipAtom.isAlkene;
+    }
+    root = cipAtom;
+    cipAtom.parent = parent;
+    currentRule = RULE_1;
+    if (cipAtom.set()) {
+      try {
+        if (iref >= 0)
+          cipAtom.bsPath.set(iref);
+        boolean doResetAux = false;
+        for (currentRule = RULE_1; currentRule <= ruleMax && !isChiral; 
currentRule++) {
+          if (Logger.debugging)
+            Logger.info("-Rule " + getRuleName() + " CIPChirality for "
+                + cipAtom + "-----");
+
+          if (currentRule == RULE_4 && useAuxiliaries) {
+            cipAtom.createAuxiliaryRSCenters("", true);
+            doResetAux = true;
+          }
+          isChiral = false;
+          cipAtom.sortSubstituents();
+          isChiral = true;
+          if (Logger.debugging) {
+            Logger.info(currentRule + ">>>>" + cipAtom);
+            for (int i = 0; i < cipAtom.bondCount; i++)
+              Logger.info(cipAtom.atoms[i] + " "
+                  + Integer.toHexString(cipAtom.prevPriorities[i]));
+          }
+          if (cipAtom.aChiral)
             isChiral = false;
-            cipAtom.sortSubstituents();
-            isChiral = true;
-            if (Logger.debugging) {
-              Logger.info(currentRule + ">>>>" + cipAtom);
-              for (int i = 0; i < cipAtom.bondCount; i++)
-                Logger.info(cipAtom.atoms[i] + " "
-                    + Integer.toHexString(cipAtom.prevPriorities[i]));
+          else
+            for (int i = 0; i < cipAtom.bondCount - 1; i++) {
+              if (cipAtom.prevPriorities[i] == cipAtom.prevPriorities[i + 1]) {
+                isChiral = false;
+                break;
+              }
             }
-            if (cipAtom.aChiral)
-              isChiral = false;
-            else
-              for (int i = 0; i < cipAtom.bondCount - 1; i++) {
-                if (cipAtom.prevPriorities[i] == cipAtom.prevPriorities[i + 
1]) {
-                  isChiral = false;
-                  break;
-                }
-              }
-          }
-          if (doResetAux) {
-            cipAtom.resetAuxiliaryChirality();
-          }
-          if (isChiral) {
-            rs = (!isAlkene ? checkHandedness(cipAtom)
-                : cipAtom.atoms[0].isDuplicate ? STEREO_S : STEREO_R);
-          }
-          if (cipAtom.isPseudo && !isAlkene)
-            rs = rs | JC.CIP_CHIRALITY_PSEUDO_FLAG;
-        } catch (Throwable e) {
-          System.out.println(e + " in CIPChirality");
-          if (!vwr.isJS)
-            e.printStackTrace();
         }
-        if (Logger.debugging)
-          Logger.info(atom + " " + rs);
+        if (doResetAux) {
+          cipAtom.resetAuxiliaryChirality();
+        }
+        if (isChiral) {
+          rs = (!isAlkene ? cipAtom.checkHandedness()
+              : cipAtom.atoms[0].isDuplicate ? STEREO_S : STEREO_R);
+        }
+        if (cipAtom.isPseudo && !isAlkene)
+          rs = rs | JC.CIP_CHIRALITY_PSEUDO_FLAG;
+      } catch (Throwable e) {
+        System.out.println(e + " in CIPChirality");
+        if (!vwr.isJS)
+          e.printStackTrace();
       }
+      if (Logger.debugging)
+        Logger.info(atom + " " + rs);
     }
     if (Logger.debugging)
       Logger.info("----------------------------------");
@@ -470,14 +526,17 @@
     if (bond.getCovalentOrder() == 2) {
       Node a = atoms[bond.getAtomIndex1()];
       Node b = atoms[bond.getAtomIndex2()];
+      // no imines for now
+      if (a.getCovalentBondCount() != 2 || b.getCovalentBondCount() != 2)
+        return ez;
       htPathPoints = new Hashtable<String, Integer>();
-      CIPAtom a1 = new CIPAtom(a, null, false);
-      CIPAtom b1 = new CIPAtom(b, null, false);
+      CIPAtom a1 = new CIPAtom(a, null, false, true);
+      CIPAtom b1 = new CIPAtom(b, null, false, true);
       //b1.fillNull(0);
       int atop = getAtomChiralityLimited(a, a1, b1, ruleMax, -1) - 1;
       htPathPoints = new Hashtable<String, Integer>();
-      CIPAtom a2 = new CIPAtom(a, null, false);
-      CIPAtom b2 = new CIPAtom(b, null, false);
+      CIPAtom a2 = new CIPAtom(a, null, false, true);
+      CIPAtom b2 = new CIPAtom(b, null, false, true);
       //a2.fillNull(0);
       int btop = getAtomChiralityLimited(b, b2, a2, ruleMax, -1) - 1;
       if (atop >= 0 && btop >= 0) {
@@ -495,32 +554,14 @@
     return ez;
   }
 
-  /**
-   * determine the winding of the circuit p1--p2--p3 relative to point p4
-   * 
-   * @param a
-   * @return 1 for "R", 2 for "S"
-   */
-  static int checkHandedness(CIPAtom a) {
-    P3 p1 = (P3) a.atoms[0].atom; // highest priority
-    P3 p2 = (P3) a.atoms[1].atom;
-    P3 p3 = (P3) a.atoms[2].atom;
-    P3 p4 = (P3) a.atoms[3].atom; // lowest priority
-    V3 vNorm = new V3();
-    float d = Measure.getNormalThroughPoints(p1, p2, p3, vNorm, new V3());
-    return (Measure.distanceToPlaneV(vNorm, d, p4) > 0 ? STEREO_R : STEREO_S);
-  }
-
-  static boolean isCIS(CIPAtom me, CIPAtom parent, CIPAtom grandParent,
+  boolean isCIS(CIPAtom me, CIPAtom parent, CIPAtom grandParent,
                        CIPAtom greatGrandParent) {
-    V3 vNorm1 = new V3();
-    V3 vTemp = new V3();
-    Measure.getNormalThroughPoints((P3) me.atom, (P3) parent.atom,
-        (P3) grandParent.atom, vNorm1, vTemp);
+    Measure.getNormalThroughPoints(me.atom.getXYZ(), parent.atom.getXYZ(),
+        grandParent.atom.getXYZ(), vNorm, vTemp);
     V3 vNorm2 = new V3();
-    Measure.getNormalThroughPoints((P3) parent.atom, (P3) grandParent.atom,
-        (P3) greatGrandParent.atom, vNorm2, vTemp);
-    return (vNorm1.dot(vNorm2) > 0);
+    Measure.getNormalThroughPoints(parent.atom.getXYZ(), 
grandParent.atom.getXYZ(),
+        greatGrandParent.atom.getXYZ(), vNorm2, vTemp);
+    return (vNorm.dot(vNorm2) > 0);
   }
 
   final static int[] PRIORITY_SHIFT = new int[] { 24, 20, 12, 8, 4, 0 };
@@ -658,6 +699,12 @@
     private boolean isTerminal;
 
     /**
+     * is one atom of a double bond
+     */
+
+    boolean isAlkene;
+
+    /**
      * a flag used in Rule 3 to indicate the second carbon of a double bond
      */
 
@@ -706,6 +753,8 @@
 
     private String[] rule4List;
 
+    private P3 lonePair;
+
     /**
      * 
      * @param atom
@@ -712,14 +761,21 @@
      *        or null to indicate a null placeholder
      * @param parent
      * @param isDuplicate
+     * @param isAlkene 
      */
-    CIPAtom(Node atom, CIPAtom parent, boolean isDuplicate) {
+    CIPAtom(Node atom, CIPAtom parent, boolean isDuplicate, boolean isAlkene) {
       this.id = ++ptID;
       this.parent = parent;
       if (atom == null)
         return;
+      this.isAlkene = isAlkene;
       this.atom = atom;
       bondCount = atom.getCovalentBondCount();
+      if (bondCount == 3 && !isAlkene) {
+        getTrigonality(atom);
+        lonePair = new P3();
+        lonePair.sub2(atom.getXYZ(), vNorm);
+      }
       String c = atom.getCIPChirality(false);
       // What we are doing here is creating a lexigraphically sortable string
       // R < S < r < s < ~ and C < T < ~ 
@@ -740,7 +796,6 @@
         rootSubstituent = this;
       else if (parent != null)
         rootSubstituent = parent.rootSubstituent;
-      this.isTerminal = atom.getCovalentBondCount() == 1;
       this.elemNo = atom.getElementNumber();
       this.massNo = atom.getNominalMass();
       this.bsPath = (parent == null ? new BS() : BSUtil.copy(parent.bsPath));
@@ -784,9 +839,9 @@
       if (isSet)
         return true;
       isSet = true;
-      if (isTerminal || isDuplicate)
+      if (isDuplicate)
         return true;
-      atoms = new CIPAtom[4];
+//      atoms = new CIPAtom[4];
       int nBonds = atom.getBondCount();
       Edge[] bonds = atom.getEdges();
       if (Logger.debugging)
@@ -799,25 +854,34 @@
         Node other = bond.getOtherAtomNode(atom);
         boolean isParent = (parent != null && parent.atom == other);
         int order = bond.getCovalentOrder();
-        if (isParent && order == 2) {
-          isAlkeneAtom2 = true;
-          knownAtomChirality = bond.getCIPChirality(false);
+        if (nBonds == 1 && order == 1 && isParent) {
+          isTerminal = true;
+          return true;
         }
+        if (order == 2) {
+          isAlkene = true;
+          if (isParent) {
+            isAlkeneAtom2 = true;
+            knownAtomChirality = bond.getCIPChirality(false);
+          }
+        }
         switch (order) {
         case 3:
-          if (addAtom(pt++, other, isParent) == null) {
+          if (addAtom(pt++, other, isParent, false) == null) {
             isTerminal = true;
             return false;
           }
           //$FALL-THROUGH$
         case 2:
-          if (addAtom(pt++, other, order != 2 || isParent) == null) {
+          // look out for S=X, which is not planar
+          if (elemNo < 10
+              && addAtom(pt++, other, order != 2 || isParent, order == 2) == 
null) {
             isTerminal = true;
             return false;
           }
           //$FALL-THROUGH$
         case 1:
-          if (!isParent && addAtom(pt++, other, order != 1) == null) {
+          if (!isParent && addAtom(pt++, other, order != 1 && elemNo < 10, 
false) == null) {
             isTerminal = true;
             return false;
           }
@@ -843,7 +907,7 @@
 
     private void fillNull(int pt) {
       for (; pt < atoms.length; pt++)
-        atoms[pt] = new CIPAtom(null, this, true);
+        atoms[pt] = new CIPAtom(null, this, true, false);
     }
 
     /**
@@ -852,9 +916,10 @@
      * @param i
      * @param other
      * @param isDuplicate
+     * @param isAlkene 
      * @return new atom or null
      */
-    private CIPAtom addAtom(int i, Node other, boolean isDuplicate) {
+    private CIPAtom addAtom(int i, Node other, boolean isDuplicate, boolean 
isAlkene) {
       if (i >= atoms.length) {
         if (Logger.debugging)
           Logger.info(" too many bonds on " + atom);
@@ -871,7 +936,7 @@
           }
         }
       }
-      atoms[i] = new CIPAtom(other, this, isDuplicate);
+      atoms[i] = new CIPAtom(other, this, isDuplicate, isAlkene);
       if (currentRule > RULE_2)
         prevPriorities[i] = getBasePriority(atoms[i]);
       //      if (Logger.debugging)
@@ -986,6 +1051,8 @@
             break;
           }
           if (doCheckPseudo) {
+            // Rule 4 has found enantiomeric ligands. We need to make sure 
+            // there are not two such sets. 
             doCheckPseudo = false;
             if (ties == null)
               ties = new BS();
@@ -1007,15 +1074,6 @@
         CIPAtom a = newAtoms[pt] = atoms[i];
         int p = priorities[i];
         newPriorities[pt] = p;
-        // can't do this, because of tie breaking
-        //        switch (currentRule) {
-        //        case 0:
-        //          p = 127 - (a.atom == null ? 0 : a.elemNo);
-        //          break;
-        //        case 2:
-        //          p = 255 - (a.atom == null ? 0 : a.massNo);
-        //          break;
-        //        }
         newPrevPriorities[pt] = prevPriorities[i] | (p << shift);
         if (a.atom != null)
           bs.set(priorities[i]);
@@ -1029,9 +1087,9 @@
 
       if (ties != null) {
         if (ties.cardinality() == 2) {
-          if (sphere != 0 || useAuxiliaries) {
+          //if (sphere != 0 || useAuxiliaries) {
             checkPseudoHandedness(ties, indices);
-          }
+          //}
         } else if (sphere == 0) {
           aChiral = true;
         }
@@ -1305,7 +1363,7 @@
       for (int i = 0, n = path.size(); i < n; i++) {
         CIPAtom p = path.get(i);
         if (p == null)
-          p = new CIPAtom(null, this, true);
+          p = new CIPAtom(null, this, true, isAlkene);
         else
           p = (CIPAtom) p.clone();
         thisAtom.replaceParentSubstituent(last, p);
@@ -1330,18 +1388,18 @@
       // critical here that we do NOT include the tied branches
       CIPAtom tie1 = atoms[Math.min(indices[ia], indices[ib])];
       CIPAtom tie2 = atoms[Math.max(indices[ia], indices[ib])];
-      atom1.atoms[indices[ia]] = new CIPAtom(null, atom1, false);
-      atom1.atoms[indices[ib]] = new CIPAtom(null, atom1, false);
+      atom1.atoms[indices[ia]] = new CIPAtom(null, atom1, false, isAlkene);
+      atom1.atoms[indices[ib]] = new CIPAtom(null, atom1, false, isAlkene);
       atom1.addReturnPath(null, path);
       int thisRule = currentRule;
       currentRule = RULE_1;
       atom1.sortSubstituents();
       // 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[2] = tie1;
-      atom1.atoms[3] = tie2;
+      // go as long as they are together and in order.
+      atom1.atoms[bondCount - 2] = tie1;
+      atom1.atoms[bondCount - 1] = tie2;
       currentRule = thisRule;
-      int rs = checkHandedness(atom1);
+      int rs = atom1.checkHandedness();
       if (Logger.debugging) {
         for (int i = 0; i < 4; i++)
           Logger.info("pseudo " +  rs + " " + priorities[i] + " " + 
atoms[i].myPath);
@@ -1366,6 +1424,7 @@
     
     /**
      * @param base
+     * @param isRoot 
      * @return collective string, with setting of rule4List
      */
     String createAuxiliaryRSCenters(String base, boolean isRoot) {
@@ -1388,8 +1447,9 @@
             }
           }
         }
-        if (!isRoot && bondCount == 4 && nPriorities >= 3) {
-          if (true || knownAtomChirality.equals("~")) {
+        if (!isRoot && (bondCount == 4 && nPriorities >= 3 || bondCount == 3 
&& !isAlkene && nPriorities >= 2)) {
+//          if (true || knownAtomChirality.equals("~")) {
+//  actually we need this to be auxiliary only
             CIPAtom atom1 = (CIPAtom) clone();
             if (atom1.set()) {
               Lst<CIPAtom> path = getReturnPath(this);
@@ -1398,12 +1458,12 @@
               currentRule = RULE_1;
               atom1.sortSubstituents();
               currentRule = thisRule;
-              rs = checkHandedness(atom1);
+              rs = atom1.checkHandedness();
               s = (rs == STEREO_R ? "R" : rs == STEREO_S ? "S" : "~");
             }
-          } else {
-            s = knownAtomChirality;
-          }
+//          } else {
+//            s = knownAtomChirality;
+//          }
         }
         System.out.println("createAux " + this + " " + nPriorities + " " + rs
             + " " + nRS + " " + subRS);
@@ -1523,20 +1583,20 @@
           atoms[i].setChirality(atoms[i].knownAtomChirality);
     }
 
-    /**
-     * Update the chirality path for this atom. Needs to also run through all 
decendents.
-     * @param rs
-     */
-    private void setAuxiliaryChirality(String rs) {
-      System.out.println("set auxchirality " + this + " " + rs + " " + 
knownChiralityPathFull);
-      auxAtomChirality = rs;
-      knownChiralityPathFull = (parent == null ? "" : 
parent.knownChiralityPathFull) + rs;
-      knownChiralityPathAbbr = PT.rep(knownChiralityPathFull, "~", "");
-      System.out.println("set chirality " + this + " " + rs + " " + 
knownChiralityPathFull);
-      for (int i = 0; i < 4; i++)
-        if (atoms[i] != null && atoms[i].atom != null)
-          atoms[i].setAuxiliaryChirality(atoms[i].knownAtomChirality);
-    }
+//    /**
+//     * Update the chirality path for this atom. Needs to also run through 
all decendents.
+//     * @param rs
+//     */
+//    private void setAuxiliaryChirality(String rs) {
+//      System.out.println("set auxchirality " + this + " " + rs + " " + 
knownChiralityPathFull);
+//      auxAtomChirality = rs;
+//      knownChiralityPathFull = (parent == null ? "" : 
parent.knownChiralityPathFull) + rs;
+//      knownChiralityPathAbbr = PT.rep(knownChiralityPathFull, "~", "");
+//      System.out.println("set chirality " + this + " " + rs + " " + 
knownChiralityPathFull);
+//      for (int i = 0; i < 4; i++)
+//        if (atoms[i] != null && atoms[i].atom != null)
+//          atoms[i].setAuxiliaryChirality(atoms[i].knownAtomChirality);
+//    }
     
     void resetAuxiliaryChirality() {
       auxAtomChirality = null;
@@ -1570,6 +1630,21 @@
       return (isRa == isRb ? TIED : isRa > isRb ? A_WINS : B_WINS);
     }
 
+    /**
+     * Determine the ordered CIP winding of this atom.
+     * 
+     * @return 1 for "R", 2 for "S"
+     */
+    int checkHandedness() {
+      P3 p1 = atoms[0].atom.getXYZ(); // highest priority
+      P3 p2 = atoms[1].atom.getXYZ();
+      P3 p3 = atoms[2].atom.getXYZ();
+      P3 p4 = (lonePair == null ? atoms[3].atom.getXYZ() : lonePair); // 
lowest priority
+      float d = Measure.getNormalThroughPoints(p1, p2, p3, vNorm, vTemp);
+      return (Measure.distanceToPlaneV(vNorm, d, p4) > 0 ? STEREO_R : 
STEREO_S);
+    }
+
+
     @Override
     public Object clone() {
       CIPAtom a = null;

Modified: trunk/Jmol/src/org/jmol/util/Node.java
===================================================================
--- trunk/Jmol/src/org/jmol/util/Node.java      2017-04-21 23:05:05 UTC (rev 
21532)
+++ trunk/Jmol/src/org/jmol/util/Node.java      2017-04-22 12:47:41 UTC (rev 
21533)
@@ -16,7 +16,7 @@
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  *  Lesser General Public License for more details.
- *
+ *3
  *  You should have received a copy of the GNU Lesser General Public
  *  License along with this library; if not, write to the Free Software
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
@@ -25,6 +25,7 @@
 package org.jmol.util;
 
 import javajs.util.Lst;
+import javajs.util.P3;
 
 import org.jmol.java.BS;
 
@@ -98,5 +99,6 @@
   char getBioSmilesType();
   String getCIPChirality(boolean doCalculate);
   void setCIPChirality(int c);
+  public P3 getXYZ();
 
 }

Modified: trunk/Jmol/src/org/jmol/viewer/JC.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/JC.java      2017-04-21 23:05:05 UTC (rev 
21532)
+++ trunk/Jmol/src/org/jmol/viewer/JC.java      2017-04-22 12:47:41 UTC (rev 
21533)
@@ -44,6 +44,60 @@
 @J2SRequireImport({javajs.util.SB.class})
 public final class JC {
 
+  public final static int CIP_CHIRALITY_R_FLAG = 1;
+  public final static int CIP_CHIRALITY_S_FLAG = 2; // 3 is "no chirality"
+  public final static int CIP_CHIRALITY_PSEUDO_FLAG = 4;
+  public final static int CIP_CHIRALITY_r_FLAG = 5;
+  public final static int CIP_CHIRALITY_s_FLAG = 6;
+  public final static int CIP_CHIRALITY_UNDETERMINED = 7;
+  public final static int CIP_CHIRALITY_Z_FLAG = 8;
+  public final static int CIP_CHIRALITY_E_FLAG = 0x10; // Z|E is "no chirality"
+
+  public static String getCIPChiralityName(int flags) {
+    switch (flags) {
+    case CIP_CHIRALITY_Z_FLAG:
+      return "Z";
+    case CIP_CHIRALITY_E_FLAG:
+      return "E";
+    case CIP_CHIRALITY_R_FLAG:
+      return "R";
+    case CIP_CHIRALITY_S_FLAG:
+      return "S";
+    case CIP_CHIRALITY_r_FLAG:
+      return "r";
+    case CIP_CHIRALITY_s_FLAG:
+      return "s";
+    case CIP_CHIRALITY_UNDETERMINED:
+      return "?";
+    default:
+      return "";
+    }
+  }
+
+  public static int getCIPChiralityCode(String rs) {
+    char c = (rs.length() == 0 ? 'x' : rs.charAt(0));
+    switch (c) {
+    case 'Z':
+      return CIP_CHIRALITY_Z_FLAG;
+    case 'E':
+      return CIP_CHIRALITY_E_FLAG;
+    case 'R':
+      return CIP_CHIRALITY_R_FLAG;
+    case 'S':
+      return CIP_CHIRALITY_S_FLAG;
+    case 'r':
+      return CIP_CHIRALITY_r_FLAG;
+    case 's':
+      return CIP_CHIRALITY_s_FLAG;
+    case '?':
+      return CIP_CHIRALITY_UNDETERMINED;
+    default:
+      return 0;
+    }
+  }
+
+
+
   // axes mode constants --> org.jmol.constant.EnumAxesMode
   // callback constants --> org.jmol.constant.EnumCallback
   // draw constants --> org.jmol.shapespecial.draw.EnumCallback
@@ -1249,4 +1303,5 @@
   }
 
 
+
 }

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2017-04-21 23:05:05 UTC 
(rev 21532)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2017-04-22 12:47:41 UTC 
(rev 21533)
@@ -49,8 +49,18 @@
 # 10. Run jmol/tools build-release.xml
 #
 
-Jmol.___JmolVersion="14.14.1"
+Jmol.___JmolVersion="14.15.1" // 4/22/17
 
+new feature: x.split(true)
+ -- does a white-space token split of the string value of x
+
+new feature: CIP chirality adds P, S, As, Se, Sb, Te, Bi, Po trigonal 
pyramidal and tetrahedral
+ 
+bug fix: CIP chirality broken for carbonyl groups
+
+
+JmolVersion="14.14.1" // 4/19/17
+
 new feature: CALCULATE CHIRALITY {atom set}
   -- starts with basic CIP Rule 1-2 determination of R/S and E/Z.
   -- continues with Rules 3-5, which require full-molecule analysis.

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

Reply via email to