Revision: 21609
          http://sourceforge.net/p/jmol/code/21609
Author:   hansonr
Date:     2017-05-19 17:09:25 +0000 (Fri, 19 May 2017)
Log Message:
-----------
Jmol.___JmolVersion="14.16.1" // 2017.05.19

new feature: load =chebi/nnnnnn    chEBI 2D molecule load, with minimal 
100-step minimization

bug fix: CML reader does not read 2D wedge/hash information

bug fix: CIP fix for missing branch descriptors; 984 lines 

bug fix: CIP adds helicene M/P chirality  
  - validated using CCDC structures HEXHEL02 HEXHEL03 HEXHEL04 ODAGOS ODAHAF
  - http://pubs.rsc.org/en/content/articlehtml/2017/CP/C6CP07552E
  
code: CIP: additional simplification;   
code: CIP status: implementation complete, including:
         All subrules implemented fully: 1a, 1b, 2, 3, 4a, 4b, 4c, 5
         R/S, E/Z, M/P (odd-cumulene and helicene), r/s, seqCis/seqTrans (as 
Z/E)
         fused benzenoid aromatic Mancude ring "Kekule weighted" atom number 
adjustments

 * Added logic to Rule 1b: The root distance for a Kekule-ambiguous duplicate
 * atom is its own sphere, not the sphere of its duplicated atom.
 * 
 * Stated more precisely:
 * 
 * Proposed amended Sequence Rule 1:
 * 
 * (1a) higher atomic number precedes lower;
 * 
 * (1b) in comparing two duplicate nodes, lower root distance precedes higher
 * root distance, where "root distance" is defined:
 * 
 * (i) in the case of a duplicate atom for which the atomic number is averaged
 * over two or more atoms in applying Rule 1a, the distance from the duplicate
 * node itself to the root node; and
 * 
 * (ii) in all other cases, the distance of its corresponding nonduplicated atom
 * node to the root node.
 * 

IUPAC Blue Book 2013 errors of note:

,"147":"r,,,R,,,,r,,,S" // chiral phosphine ignored in BB P-93.5.1.1.2 for S vs 
R
{
  "id"  :  "148"
  "name_pname_pin"  :  "bis[(1r,4r)-4-methylcyclohexyl]phosphane"
  "ref_pname_pin"  :  "P-93.5.1.1.2"
  "stereo"  :  ",r,,,R,,,,r,,,R,,,"
 }

,"148":"r,,,S,,,,r,,,R,,,,s,,,s" // r,,,S,,,,r,,,S,,,,s,,,S  Jmol disagrees 
with BB P-93.5.1.1.2 or R and S p. 1243
{
  "id"  :  "149"
  "name_pname_pin"  :  
"bis[(1r,4r)-4-methylcyclohexyl]-(1s,4s)-4-methylcyclohexylphosphane"
  "ref_pname_pin"  :  "P-93.5.1.1.2"
  "stereo"  :  ",r,,,S,,,,r,,,S,,,,s,,,S,,,"
 }

,"202":"RR" // // p. 1265 disagrees with BB P-93.5.3.5 for RR vs. SS
{
  "id"  :  "203"
  "name_pname_pin"  :  
"(5S,8R,11S)-1,12-dioxatrispiro[4.2.2.4^{11}.2^{8}.2^{5}]nonadecane"
  "ref_pname_pin"  :  "P-93 5.3.5"
 }

,"227":"SrSEErS" // disagrees with BB P-93.5.7.2 for S vs. r
{
  "id"  :  "228"
  "name_pname_pin"  :  
"(1E)-1-{(1'S,1r,4s)-[1,1'-bi(cyclohexan)]-3'-en-4-yl}-N-[(1r,4r)-4-phenylcyclohexyl]methan-1-imine"
  "ref_pname_pin"  :  "P-93.5.7.2"
  "stereo"  :  "S,,,,,,,r,S,,,,,,,E,,r,r,,,,,,,,,,,,"
 }

,"230":"@3D RrRsR" // p 1282  disagrees with BB P-93.6
{
  "id"  :  "231"
  "name_pname_pin"  :  
"(2R)-1-[(1r,4R)-4-methylcyclohexyl]-3-[(1s,4S)-4-methylcyclohexyl]propan-2-ol"
  "ref_pname_pin"  :  "P-93.6"
  "stereo"  :  ",,,,r,,,R,,,,s,,,R,,,"
 }

Modified Paths:
--------------
    trunk/Jmol/src/org/jmol/adapter/readers/xml/XmlCmlReader.java
    trunk/Jmol/src/org/jmol/adapter/readers/xml/XmlReader.java
    trunk/Jmol/src/org/jmol/modelset/ModelSet.java
    trunk/Jmol/src/org/jmol/scriptext/CmdExt.java
    trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java
    trunk/Jmol/src/org/jmol/util/CommandHistory.java
    trunk/Jmol/src/org/jmol/viewer/FileManager.java
    trunk/Jmol/src/org/jmol/viewer/JC.java
    trunk/Jmol/src/org/jmol/viewer/Jmol.properties
    trunk/Jmol/src/org/jmol/viewer/Viewer.java

Modified: trunk/Jmol/src/org/jmol/adapter/readers/xml/XmlCmlReader.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/xml/XmlCmlReader.java       
2017-05-18 04:50:52 UTC (rev 21608)
+++ trunk/Jmol/src/org/jmol/adapter/readers/xml/XmlCmlReader.java       
2017-05-19 17:09:25 UTC (rev 21609)
@@ -125,7 +125,7 @@
   protected String moleculeID;
   
   protected Map<String, Object> htModelAtomMap;
-  private boolean is2d;
+  private boolean optimize2d;
 
   /**
    * state constants
@@ -142,14 +142,14 @@
     MOLECULE_ATOM_SCALAR = 9,
     MOLECULE_BOND_ARRAY = 10, 
     MOLECULE_BOND = 11, 
-    MOLECULE_FORMULA = 12,
-    MOLECULE_ATOM_BUILTIN = 13, 
-    MOLECULE_BOND_BUILTIN = 14,
-    MODULE = 15,
+    MOLECULE_BOND_STEREO = 12, 
+    MOLECULE_FORMULA = 13,
+    MOLECULE_ATOM_BUILTIN = 14, 
+    MOLECULE_BOND_BUILTIN = 15,
+    MODULE = 16,
     SYMMETRY = 17,
     LATTICE_VECTOR = 18,
     ASSOCIATION = 19;
-
   /**
    * the current state
    */
@@ -169,8 +169,10 @@
   @Override
   protected void processXml(XmlReader parent,
                             Object saxReader) throws Exception {
-    is2d = parent.checkFilterKey("2D");
+    optimize2d = parent.checkFilterKey("2D");
     processXml2(parent, saxReader);
+    if (optimize2d)
+      set2D();
   }
 
   @Override
@@ -306,7 +308,7 @@
           for (int i = tokenCount; --i >= 0;)
             atomArray[i].atomName = tokens[i];
         }
-        boolean is3d = (!is2d && (val = atts.get("x3")) != null);
+        boolean is3d = (!optimize2d && (val = atts.get("x3")) != null);
         if (is3d) {
           is3d = true;
           coords3D = true;
@@ -418,8 +420,14 @@
         setKeepChars(true);
         state = MOLECULE_BOND_BUILTIN;
         scalarDictValue = val;
+      } else if (name.equals("bondstereo")) {
+        state = MOLECULE_BOND_STEREO;
       }
       break;
+    case MOLECULE_BOND_STEREO:
+      setKeepChars(true);
+      state = MOLECULE_BOND_STEREO;
+      break;
     case MOLECULE_ATOM:
       if (name.equals("scalar")) {
         state = MOLECULE_ATOM_SCALAR;
@@ -622,6 +630,13 @@
         atom.elementSymbol = chars.toString();
       setKeepChars(false);
       break;
+    case MOLECULE_BOND_STEREO:
+      String stereo = chars.toString();
+      if (bond.order == 1)
+        bond.order = (stereo.equals("H") ? JmolAdapter.ORDER_STEREO_FAR : 
JmolAdapter.ORDER_STEREO_NEAR);
+      setKeepChars(false);
+      state = MOLECULE_BOND;
+      break;
     case MOLECULE_BOND_BUILTIN: // ACD Labs
       state = MOLECULE_BOND;
       if (scalarDictValue.equals("atomRef")) {
@@ -690,8 +705,10 @@
     parent.applySymmetryToBonds = true;
     a1 = fixSerialName(a1);
     a2 = fixSerialName(a2);
-    if (joinList == null || !checkBondToR(a1, a2))
+    if (joinList == null || !checkBondToR(a1, a2)) {
       asc.addNewBondFromNames(a1, a2, order);
+      bond = asc.bonds[asc.bondCount - 1];
+    }
   }
 
   private String fixSerialName(String a) {

Modified: trunk/Jmol/src/org/jmol/adapter/readers/xml/XmlReader.java
===================================================================
--- trunk/Jmol/src/org/jmol/adapter/readers/xml/XmlReader.java  2017-05-18 
04:50:52 UTC (rev 21608)
+++ trunk/Jmol/src/org/jmol/adapter/readers/xml/XmlReader.java  2017-05-19 
17:09:25 UTC (rev 21609)
@@ -33,6 +33,7 @@
 import org.jmol.adapter.smarter.Atom;
 import org.jmol.adapter.smarter.AtomSetCollection;
 import org.jmol.adapter.smarter.AtomSetCollectionReader;
+import org.jmol.adapter.smarter.Bond;
 import org.jmol.adapter.smarter.Resolver;
 import org.jmol.api.Interface;
 import org.jmol.util.Logger;
@@ -92,6 +93,7 @@
 public class XmlReader extends AtomSetCollectionReader {
 
   protected Atom atom;
+  protected Bond bond;
   //protected String[] domAttributes;
   protected XmlReader parent; // XmlReader itself; to be assigned by the 
subReader
   public Map<String, String> atts;

Modified: trunk/Jmol/src/org/jmol/modelset/ModelSet.java
===================================================================
--- trunk/Jmol/src/org/jmol/modelset/ModelSet.java      2017-05-18 04:50:52 UTC 
(rev 21608)
+++ trunk/Jmol/src/org/jmol/modelset/ModelSet.java      2017-05-19 17:09:25 UTC 
(rev 21609)
@@ -2964,6 +2964,8 @@
       vwr.shm.setShapeSizeBs(JC.SHAPE_BALLS, 0, vwr.rd,
           BSUtil.newAndSetBit(atomIndex));
       setAtomName(atomIndex, type + atom.getAtomNumber(), false);
+      if (vwr.getBoolean(T.modelkitmode))
+        am[atom.mi].isModelKit = true;
       if (!am[atom.mi].isModelKit)
         taintAtom(atomIndex, TAINT_ATOMNAME);
     } else if (type.equals("Pl")) {

Modified: trunk/Jmol/src/org/jmol/scriptext/CmdExt.java
===================================================================
--- trunk/Jmol/src/org/jmol/scriptext/CmdExt.java       2017-05-18 04:50:52 UTC 
(rev 21608)
+++ trunk/Jmol/src/org/jmol/scriptext/CmdExt.java       2017-05-19 17:09:25 UTC 
(rev 21609)
@@ -5108,6 +5108,7 @@
     P3 pt = (++e.iToken < slen ? centerParameter(e.iToken) : null);
     if (chk)
       return;
+    vwr.pushState();
     switch (atomsOrBonds) {
     case T.atoms:
       e.clearDefinedVariableAtomSets();

Modified: trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java
===================================================================
--- trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java  2017-05-18 04:50:52 UTC 
(rev 21608)
+++ trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java  2017-05-19 17:09:25 UTC 
(rev 21609)
@@ -197,7 +197,14 @@
   // 4. Rule 3  requires the concept of "auxiliary" (temporary, 
digraph-specific) descriptors.
   //            This concept of auxiliary descriptors is the key to not having 
an analysis
   //            blow up or somehow require complex, impossible iteration.
-  // 5. Rule 4a needs to be addressed exhaustively prior to Rules 4b and 4c. 
+  // 5. Rule 4a needs to be addressed exhaustively prior to Rules 4b and 4c. 
This involves the
+  //            the initial generation of all auxiliary descriptors, including 
r/s and R/S at
+  //            branching points. In the course of doing this, all rules, 1-5, 
must be employed
+  //            at these auxiliary centers using the already-created digraph. 
This rule serves to
+  //            avoid the need for Rule 4b for all except the most unusual 
cases, where, for example,
+  //            there are two otherwise identical branches, but one can be 
identified as S and the
+  //            other only r or no-stereo, but not R. Thus, only branches that 
end up as R/R, R/S, S/S,
+  //            r/r, r/s, s/s, or nst/nst need be investigated by Rule 4b.  
   // 6. Rule 4b Somehow missed in the discussion is that the reference 
descriptor is determined
   //            once and only once for each branch from the center under 
scrutiny. All Rules 
   //            preceding Rule 4 can be applied to iterated subsections of a 
digraph. Not this one,
@@ -204,7 +211,7 @@
   //            nor Rule 5, though. The key is to determine one single "Mata 
sequence" of R and S descriptors
   //            for each pair of branches being considered. This same 
reference carries through all  
   //            future iterations of the algorithm for that branch.
-  // 7. Rule 4c Again, this rule must be invoked only after Rule 4b is 
completely set, and again
+  // 7. Rule 4c Again, this subrule must be invoked only after Rule 4b is 
completed, and again
   //            it is only for the root branches, not anywhere else.
   // 8. Rule 5  Final setting pseudoasymmetry (r/s, m/p) can be done along the 
same line as Rule 4b,
   //            but with slightly different sorting criteria.
@@ -217,6 +224,7 @@
   //    prefilterAtoms()
   //    checkForAlkenes()
   //    checkForSmallRings()
+  //    checkForHelicenes()
   //    checkForBridgeheadNitrogens()
   //    checkForKekuleIssues()
   //    checkForAtropisomerism()
@@ -224,6 +232,7 @@
   //    if (haveAlkenes) {
   //      for(all double bonds) getBondChirality(a1, a2)
   //      removeUnnecessaryEZDesignations()
+  //      indicateHeliceneChirality()
   //    }
   //  }
   //
@@ -307,10 +316,11 @@
   static final int RULE_2  = 3;
   static final int RULE_3  = 4;
   static final int RULE_4a = 5;
-  static final int RULE_4bc = 6; // can be done together; no need for a 
separate loop
-  static final int RULE_5  = 7;
+  static final int RULE_4b = 6; 
+  static final int RULE_4c = 7; 
+  static final int RULE_5  = 8;
   
-  static final String[] ruleNames = {"","1a", "1b", "2", "3", "4a", "4bc", 
"5"}; 
+  static final String[] ruleNames = {"","1a", "1b", "2", "3", "4a", "4b", 
"4c", "5"}; 
 
   public String getRuleName() {
     return ruleNames[currentRule];
@@ -325,7 +335,7 @@
   /**
    * maximum path to display for debugging only
    */
-  public static final int MAX_PATH = 30;
+  public static final int MAX_PATH = 50;
   
   /**
    * maximum ring size that can have a double bond with no E/Z designation;
@@ -436,32 +446,33 @@
       int c = getAtomChiralityLimited(a, null, null, RULE_5);
       a.setCIPChirality(c == 0 ? JC.CIP_CHIRALITY_NONE : c);
     }
+    if (haveAlkenes) {
 
-    // set bond chiralities
-    
-    if (haveAlkenes) {
+      // set bond chiralities E/Z and M/P
+      
       Lst<int[]> lstEZ = new Lst<int[]>();
       for (int i = bsToDo.nextSetBit(0); i >= 0; i = bsToDo.nextSetBit(i + 1))
         getAtomBondChirality(atoms[i], lstEZ, bsToDo);
       if (lstSmallRings.size() > 0 && lstEZ.size() > 0)
         clearSmallRingEZ(atoms, lstEZ);
-    }
-    
-    // add helical chiralities
+      
+      // Add helicene chiralities -- predetermined using a Jmol SMARTS 
conformational search.
+      //
+      // M: A{a}(.t:-10,-40)a(.t:-10,-40)aaa
+      // P: A{a}(.t:10,40)a(.t:10,40)aaa
+      //
+      // Note that indicators are on the first and last aromatic atoms {a}. 
 
-    if (bsHelixM != null) 
-      for (int i = bsHelixM.nextSetBit(0); i >= 0; i = bsHelixM.nextSetBit(i + 
1))
-        atoms[i].setCIPChirality(STEREO_M);
+      if (bsHelixM != null) 
+        for (int i = bsHelixM.nextSetBit(0); i >= 0; i = bsHelixM.nextSetBit(i 
+ 1))
+          atoms[i].setCIPChirality(STEREO_M);
 
 
-    if (bsHelixM != null) 
-      for (int i = bsHelixM.nextSetBit(0); i >= 0; i = bsHelixM.nextSetBit(i + 
1))
-        atoms[i].setCIPChirality(STEREO_M);
+      if (bsHelixP != null) 
+        for (int i = bsHelixP.nextSetBit(0); i >= 0; i = bsHelixP.nextSetBit(i 
+ 1))
+          atoms[i].setCIPChirality(STEREO_P);
+    }
 
-    if (bsHelixP != null) 
-      for (int i = bsHelixP.nextSetBit(0); i >= 0; i = bsHelixP.nextSetBit(i + 
1))
-        atoms[i].setCIPChirality(STEREO_P);
-
     if (Logger.debugging) {
       Logger.info("sp2-aromatic = " + bsKekuleAmbiguous);
       Logger.info("smallRings = " + PT.toJSON(null,lstSmallRings));
@@ -1391,13 +1402,6 @@
       isTrigonalPyramidal = (bondCount == 3 && !isAlkene && (elemNo > 10 || 
bsAzacyclic != null
           && bsAzacyclic.get(atomIndex)));
       canBePseudo = (bondCount == 4 || isTrigonalPyramidal);
-      //String c = atom.getCIPChirality(false);
-      // What we are doing here is creating a lexigraphically sortable string
-      // R < S < r < s < ~ and C < T < ~ // actually, C and T are not used
-      // we ignore r and s here. 
-      //if (c.equals("") || c.equals("r") || c.equals("s"))
-        //c = "~"; // none
-      //knownAtomChirality = c;
       if (parent != null)
         sphere = parent.sphere + 1;
       if (sphere == 1) {
@@ -1577,10 +1581,6 @@
 
       Arrays.sort(atoms);
       return true;
-      // pretty sure this next test cannot be true
-//      if (isTerminal)
-//        System.out.println("????");
-//      return !isTerminal;
     }
 
     /**
@@ -1638,7 +1638,7 @@
       }
 
       // if this is Rule 4 or 5, then we do a check of the forward-based 
stereochemical path
-      boolean checkRule4List = (rule4List != null && (currentRule == RULE_4bc 
|| currentRule == RULE_5));
+      boolean checkRule4List = (rule4List != null && currentRule > RULE_4a);
       for (int i = 0; i < 4; i++) {
         CIPAtom a = atoms[i];
         for (int j = i + 1; j < 4; j++) {
@@ -1989,7 +1989,8 @@
         return checkRule3(b); // can be IGNORE
       case RULE_4a:
         return checkRules4a(b, " sr SR PM");
-      case RULE_4bc:
+      case RULE_4b:
+      case RULE_4c:
       case RULE_5:
         return TIED; // not carried out here because these need access to a 
full list of ligands 
 //      case RULE_4c:  // taken care of by RULE_4bc
@@ -2217,7 +2218,6 @@
      *         (IGNORE)
      */
     private int compareMataPair(int ia, int ib) {
-      boolean isRule5 = (currentRule == RULE_5);
       // note that opposites will need to generate "R" or "S" keys, which will 
be 
       // resolved as "r" or "s" 
       // but generally we will want to process this as "R" and "S"
@@ -2224,54 +2224,60 @@
       // note that this analysis cannot be done ahead of time
       String aStr = rule4List[ia].substring(1);
       String bStr = rule4List[ib].substring(1);
-      boolean haveRS = false;
-      if (atoms[ia].nextChiralBranch != null) {
-        String s = atoms[ia].getMataList(getFirstRef(aStr), isRule5);
-        haveRS = (s.indexOf("|") >= 0); 
-        aStr = (haveRS ? s :  aStr + s);
-      }
-      if (atoms[ib].nextChiralBranch != null) {
-        String s = atoms[ib].getMataList(getFirstRef(bStr), isRule5);
-        haveRS |= (s.indexOf("|") >= 0); 
-        bStr = (s.indexOf("|") < 0 ? bStr + s : s);
-      }
-      if (Logger.debugging)
-        Logger.info(dots() + this + " comparing " + atoms[ia] + " " + aStr + " 
to "
-            + atoms[ib] + " " + bStr);
-      if (isRule5 || !haveRS && aStr.length() != bStr.length()) {
-        // note that these two strings can be different lengths
-        // if we have sXX and ~
-        return sign(aStr.compareTo(bStr));
-      }
-      if (haveRS) {
-        // Mata(2005) Figure 9
-        // We are trying to ascertain that
-        // R lull                  R luuu
-        // S luuu   is the same as S lull
-        // 
-        // Solution is to SUM all winners. If that is 0, then they are the same
-        String[] aList = PT.split(aStr, "|");
-        String[] bList = PT.split(bStr, "|");
-        int minScore = Integer.MAX_VALUE;
-        int sumScore = 0;
-        aStr = aList[0];
-        bStr = bList[0];
-        for (int i = aList.length; --i >= 0;) {
-          for (int j = bList.length; --j >= 0;) {
-            int score = compareRule4PairStr(aList[i], bList[j], true);
-            sumScore += score;
-            if (score != TIED && Math.abs(score) <= minScore) {
-              minScore = Math.abs(score);
-              aStr = aList[i];
-              bStr = bList[j];
+      if (currentRule == RULE_4c) {
+        aStr = PT.rep(aStr,  "~",  "");
+        bStr = PT.rep(bStr,  "~",  "");
+      } else {
+        boolean haveRS = false;
+        boolean isRule5 = (currentRule == RULE_5);
+        if (atoms[ia].nextChiralBranch != null) {
+          String s = atoms[ia].getMataList(getFirstRef(aStr), isRule5);
+          haveRS = (s.indexOf("|") >= 0);
+          aStr = (haveRS ? s : aStr + s);
+        }
+        if (atoms[ib].nextChiralBranch != null) {
+          String s = atoms[ib].getMataList(getFirstRef(bStr), isRule5);
+          haveRS |= (s.indexOf("|") >= 0);
+          bStr = (s.indexOf("|") < 0 ? bStr + s : s);
+        }
+        if (Logger.debugging)
+          Logger.info(dots() + this + " comparing " + atoms[ia] + " " + aStr
+              + " to " + atoms[ib] + " " + bStr);
+        if (isRule5 || !haveRS && aStr.length() != bStr.length()) {
+          // note that these two strings can be different lengths
+          // if we have sXX and ~
+          return sign(aStr.compareTo(bStr));
+        }
+        aStr = cleanRule4Str(aStr);
+        bStr = cleanRule4Str(bStr);
+        if (haveRS) {
+          // Mata(2005) Figure 9
+          // We are trying to ascertain that
+          // R lull                  R luuu
+          // S luuu   is the same as S lull
+          // 
+          // Solution is to SUM all winners. If that is 0, then they are the 
same
+          String[] aList = PT.split(aStr, "|");
+          String[] bList = PT.split(bStr, "|");
+          int minScore = Integer.MAX_VALUE;
+          int sumScore = 0;
+          aStr = aList[0];
+          bStr = bList[0];
+          for (int i = aList.length; --i >= 0;) {
+            for (int j = bList.length; --j >= 0;) {
+              int score = compareRule4PairStr(aList[i], bList[j], true);
+              sumScore += score;
+              if (score != TIED && Math.abs(score) <= minScore) {
+                minScore = Math.abs(score);
+                aStr = aList[i];
+                bStr = bList[j];
+              }
             }
           }
+          if (sumScore == TIED)
+            return TIED;
         }
-        if (sumScore == TIED)
-          return TIED;
       }
-      aStr = PT.rep(aStr, "~", "");
-      bStr = PT.rep(bStr, "~", "");
       if (aStr.length() == 1 && "RS".indexOf(aStr) < 0) {
         int score = checkEnantiomer(aStr, bStr, 0, aStr.length(), " rs");
         switch (score) {
@@ -2285,6 +2291,11 @@
       return compareRule4PairStr(aStr, bStr, false);
     }
 
+    private String cleanRule4Str(String aStr) {
+      return (aStr.length() > 1 ?
+          PT.replaceAllCharacters(aStr, "sr~", "") : aStr);
+    }
+
     /**
      * Just get the first R- or S-equivalent in "~~~~xxxxx"
      * @param aStr
@@ -2412,7 +2423,7 @@
      */
     private int compareRule4PairStr(String aStr, String bStr, boolean 
isRSTest) {
       if (Logger.debugging)
-        Logger.info(dots() + this + " Rule 4b comparing " + aStr + " " + bStr);
+        Logger.info(dots() + this.myPath + " Rule 4b comparing " + aStr + " " 
+ bStr);
       doCheckPseudo = false;
       int n = aStr.length();
       if (n == 0 ||  n != bStr.length())
@@ -2655,17 +2666,18 @@
                 s = s.toUpperCase(); // Rule 4c or diasteriomers // AY-236.148
               auxChirality = s;
               subRS = "";
-              if (ret != null)
-                ret[0] = null;
+              //if (ret != null)
+                //ret[0] = null;
             } else {
               // if here, adj is TIED (0) 
               CIPAtom atom1 = (CIPAtom) clone();
               if (atom1.set()) {
                 atom1.addReturnPath(null, this);
+                //System.out.println("determining " + s + " for " + 
atom1.myPath);
                 atom1.sortByRule(RULE_1a);
                 rs = atom1.checkHandedness();
                 s = (rs == STEREO_R ? "R" : rs == STEREO_S ? "S" : "~");
-                System.out.println("determining " + s + " for " + root + "->" 
+ atom1);
+                //System.out.println("determining " + s + " for " + 
atom1.myPath);
                 node1.addMataRef(sphere, priority, rs);
               }
             }
@@ -2738,8 +2750,13 @@
       if (n != rs2.length())
         return NOT_RELEVANT; // TODO: ?? this may not be true -- paths with 
and without O, N, C for example, that still have stereochemistry
       if (rs1.equals(rs2))
-        return TIED;      
-      String rs = (rs1.indexOf("R") < 0 && rs1.indexOf("S") < 0 ? "~rs" : 
"~RS");
+        return TIED;
+      boolean haveRS = (rs1.indexOf("R") >= 0 || rs1.indexOf("S") >= 0);
+      String rs = (haveRS ? "~RS" : "~rs");
+      if (haveRS) {
+        rs1 = PT.replaceAllCharacters(rs1, "rs", "~");
+        rs2 = PT.replaceAllCharacters(rs2, "rs", "~");
+      }
       int score = checkEnantiomer(rs1, rs2, 1, n, rs);
       if (score == DIASTEREOMERIC) {
         switch (compareMataPair(i1, i2)) {
@@ -2910,6 +2927,7 @@
       a.atoms = new CIPAtom[4];
       a.priorities = new int[4];
       a.htPathPoints = htPathPoints;
+      a.doCheckPseudo = false;
       for (int i = 0; i < 4; i++) {
 //        a.priorities[i] = priorities[i];
         if (atoms[i] != null) {
@@ -2916,6 +2934,7 @@
           a.atoms[i] = atoms[i];
         }
       }
+      a.ties = null;
       if (Logger.debugging)
         Logger.info("cloning " + this + " as " + a);
       return a;

Modified: trunk/Jmol/src/org/jmol/util/CommandHistory.java
===================================================================
--- trunk/Jmol/src/org/jmol/util/CommandHistory.java    2017-05-18 04:50:52 UTC 
(rev 21608)
+++ trunk/Jmol/src/org/jmol/util/CommandHistory.java    2017-05-19 17:09:25 UTC 
(rev 21609)
@@ -255,4 +255,19 @@
     //System.out.println("HISTORY:" + i+" "+commandList.get(i));
   }
 
+  private Lst<String> lstStates;
+  
+  public void pushState(String stateInfo) {
+    if (lstStates == null)
+      lstStates = new Lst<String>();
+    lstStates.addLast(stateInfo);    
+  }
+
+  public String popState() {
+    if (lstStates == null || lstStates.size() == 0)
+      return null;
+    String s = lstStates.removeItemAt(lstStates.size() - 1);
+    return s;
+  }
+
 }

Modified: trunk/Jmol/src/org/jmol/viewer/FileManager.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/FileManager.java     2017-05-18 04:50:52 UTC 
(rev 21608)
+++ trunk/Jmol/src/org/jmol/viewer/FileManager.java     2017-05-19 17:09:25 UTC 
(rev 21609)
@@ -210,6 +210,12 @@
         && Viewer.hasDatabasePrefix(name0)) {
       htParams.put("dbName", name0);
     }
+    if (name.endsWith("%2D%")) {
+      String filter = (String) htParams.get("filter");
+      htParams.put("filter", (filter == null ? "" : filter) + "2D");
+      name = name.substring(0, name.length() - 4);
+    }
+      
     int pt = name.indexOf("::");
     String nameAsGiven = (pt >= 0 ? name.substring(pt + 2) : name);
     String fileType = (pt >= 0 ? name.substring(0, pt) : null);

Modified: trunk/Jmol/src/org/jmol/viewer/JC.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/JC.java      2017-05-18 04:50:52 UTC (rev 
21608)
+++ trunk/Jmol/src/org/jmol/viewer/JC.java      2017-05-19 17:09:25 UTC (rev 
21609)
@@ -129,6 +129,7 @@
   // note list of RCSB access points: 
http://www.rcsb.org/pdb/static.do?p=download/http/index.html
   
   public static String[] databases = { 
+    "chebi", 
"http://www.ebi.ac.uk/chebi/saveStructure.do?defaultImage=true&chebiId=%file%2D%";,
     "aflowbin", 
"http://aflowlib.mems.duke.edu/users/jmolers/binary_new/%FILE.aflow_binary";,
     "aflow", 
"http://aflowlib.mems.duke.edu/users/jmolers/binary_new/%FILE.aflow_binary";,
     // _#DOCACHE_ flag indicates that the loaded file should be saved in any 
state in full

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2017-05-18 04:50:52 UTC 
(rev 21608)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2017-05-19 17:09:25 UTC 
(rev 21609)
@@ -54,9 +54,12 @@
 # command, and then write a PDB file, all the occupancies are listed as 1.00 
 # instead of the occupancies I tried to assign in jmol.
 
+# TODO: fix UNDO
 
-Jmol.___JmolVersion="14.15.5"
+Jmol.___JmolVersion="14.16.1" // 2017.05.19
 
+new feature: load =chebi/nnnnnn    chEBI 2D molecule load, with minimal 
100-step minimization
+
 bug fix: CML reader does not read 2D wedge/hash information
 
 bug fix: CIP fix for missing branch descriptors; 984 lines 
@@ -69,7 +72,7 @@
 code: CIP status: implementation complete, including:
          All subrules implemented fully: 1a, 1b, 2, 3, 4a, 4b, 4c, 5
          R/S, E/Z, M/P (odd-cumulene and helicene), r/s, seqCis/seqTrans (as 
Z/E)
-         benzenoid (including fused benzenoid heteroaromatic) Mancude ring 
"Kekule weighted" atom number adjustments 
+         fused benzenoid aromatic Mancude ring "Kekule weighted" atom number 
adjustments
 
  * Added logic to Rule 1b: The root distance for a Kekule-ambiguous duplicate
  * atom is its own sphere, not the sphere of its duplicated atom.
@@ -93,7 +96,7 @@
 
 IUPAC Blue Book 2013 errors of note:
 
-,"147":"r,,,R,,,,r,,,S" // chiral phosphine -- disagrees with BB P-93.5.1.1.2 
for S vs R
+,"147":"r,,,R,,,,r,,,S" // chiral phosphine ignored in BB P-93.5.1.1.2 for S 
vs R
 {
   "id"  :  "148"
   "name_pname_pin"  :  "bis[(1r,4r)-4-methylcyclohexyl]phosphane"

Modified: trunk/Jmol/src/org/jmol/viewer/Viewer.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Viewer.java  2017-05-18 04:50:52 UTC (rev 
21608)
+++ trunk/Jmol/src/org/jmol/viewer/Viewer.java  2017-05-19 17:09:25 UTC (rev 
21609)
@@ -7944,6 +7944,20 @@
     commandHistory.addCommand(PT.replaceAllCharacters(command, "\r\n\t", " "));
   }
 
+  public void pushState() {
+    if (autoExit || !haveDisplay || !getPreserveState())
+      return;
+    commandHistory.pushState(getStateInfo());
+  }
+  
+  public void popState() {
+    if (autoExit || !haveDisplay || !getPreserveState())
+      return;
+    String state = commandHistory.popState();
+    if (state != null)
+      evalStringQuiet(state);
+  }
+  
   /**
    * Removes one command from the command history
    * 

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