Revision: 21640
          http://sourceforge.net/p/jmol/code/21640
Author:   hansonr
Date:     2017-06-25 20:37:45 +0000 (Sun, 25 Jun 2017)
Log Message:
-----------
Jmol.___JmolVersion="14.19.1"

bug fix: CIPChirality: minor fixes for Rule 4b and 5 for BH64_012-015; better 
atropisomer check
bug fix; SPIN QUATERNION 
bug fix: CENTERAT ABSOLUTE broken (since forever?)
bug fix: SPIN QUATERNION {0 0 -1 0} still does a positive, not negative, 
rotation
 (solution is to apply a miniscule rotation of 1e-10 degrees)
 
bug fix: script array context [3 -0] becomes [3], as in [3 - 0]

new feature: WRITE "SDF" implements atom value V  nnn ... information
 -- requires assigning the data property name "atom_values" in the model's 
molData property
 -- for example:
 
  $ load $2,3-dichlorobutane
  $ molData = {"atom_values":"chirality"}
  $ model properties "molData" molData
  $ write diol.sdf

 -- note that if the model already has a molData property, then use the 
following to append to it:
 
  $ molData = (_M.molData ? _M.molData : {})
  $ molData.atom_values = "chirality"
  $ model properties "molData" molData
   
   
   
new feature: x = load("filename","JSON")
 -- loads JSON data into variable
 
bug fix: SET ANTIALIASDISPLAY requires click [via resizeImage()]
bug fix: CIP gives wrong alkene root distance for cyclopropene
bug fix: WRITE of structure file does not report number of atoms and warn if 
selected is different from this molecule
bug fix: WRITE MOL using format 10f.5 instead of 10f.4 for x, y, z coordinates
bug fix: MOL/SDF files should truncate lines at 80 characters.

Modified Paths:
--------------
    trunk/Jmol/src/org/jmol/script/ScriptEval.java
    trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java
    trunk/Jmol/src/org/jmol/symmetry/Symmetry.java
    trunk/Jmol/src/org/jmol/viewer/Jmol.properties

Modified: trunk/Jmol/src/org/jmol/script/ScriptEval.java
===================================================================
--- trunk/Jmol/src/org/jmol/script/ScriptEval.java      2017-06-22 16:44:35 UTC 
(rev 21639)
+++ trunk/Jmol/src/org/jmol/script/ScriptEval.java      2017-06-25 20:37:45 UTC 
(rev 21640)
@@ -5819,7 +5819,10 @@
     int direction = 1;
     int tok;
     Quat q = null;
+    boolean qGT180 = false;
     boolean helicalPath = false;
+    boolean isDegreesPerSecond = false;
+    boolean isSeconds = false;
     Lst<P3> ptsB = null;
     BS bsCompare = null;
     P3 invPoint = null;
@@ -5876,11 +5879,11 @@
           // rotate spin BRANCH <DihedralList> [seconds]
           if (degreesPerSecond == PT.FLOAT_MIN_SAFE) {
             degreesPerSecond = floatParameter(i);
-            continue;
           } else if (endDegrees == Float.MAX_VALUE) {
             endDegrees = degreesPerSecond;
             degreesPerSecond = floatParameter(i);
-            continue;
+          } else {
+            invArg();
           }
         } else {
           // rotate ... [endDegrees]
@@ -5887,14 +5890,21 @@
           // rotate ... [endDegrees] [degreesPerSecond]
           if (endDegrees == Float.MAX_VALUE) {
             endDegrees = floatParameter(i);
-            continue;
           } else if (degreesPerSecond == PT.FLOAT_MIN_SAFE) {
             degreesPerSecond = floatParameter(i);
             isSpin = true;
-            continue;
+          } else {
+            invArg();
           }
         }
-        invArg();
+        if (i == slen - 2 && (tokAt(i + 1) == T.misc || tokAt(i + 1) == 
T.string)) {
+          String s = paramAsStr(++i).toLowerCase();
+          if (s.equals("dps")) {
+            isDegreesPerSecond = true;
+          } else if (s.equals("sec")) {
+            isSeconds = true;
+          }
+        }
         break;
       case T.minus:
         direction = -1;
@@ -5925,8 +5935,9 @@
         if (q != null) {
           if (tok == T.best && !(isMolecular = isSelected)) // yes, setting 
isMolecular here.
             q = q.div(vwr.tm.getRotationQ());
-          if (q.q0 == 0 && isSpin)
+          if (q.q0 == 0)
             q.q0 = 1e-10f;
+          qGT180 = (q.q0 < 0);
           rotAxis.setT(q.getNormal());
           endDegrees = q.getTheta();
         }
@@ -5945,7 +5956,8 @@
             return;
           pts = new P3[3];
           for (int j = 0; j < 3; j++)
-            pts[j] = vwr.ms.getAtomSetCenter(SV.getBitSet(lst.get(n - 3 + j), 
false));
+            pts[j] = vwr.ms.getAtomSetCenter(SV.getBitSet(lst.get(n - 3 + j),
+                false));
         } else if (isArrayParameter(i + 1)) {
           pts = getPointArray(++i, -1, false);
           i = iToken;
@@ -5960,7 +5972,7 @@
         if (n < 3)
           return;
         q = Quat.getQuaternionFrame(pts[n - 3], pts[n - 2], pts[n - 1]);
-        q = Quat.new4(1,0,0,0).mulQ(q.inv().div(vwr.tm.getRotationQ()));
+        q = Quat.new4(1, 0, 0, 0).mulQ(q.inv().div(vwr.tm.getRotationQ()));
         rotAxis.setT(q.getNormal());
         endDegrees = q.getTheta();
         break;
@@ -6008,8 +6020,8 @@
         int symop = intParameter(++i);
         if (chk)
           continue;
-        Map<String, Object> info = vwr.getSymTemp().getSpaceGroupInfo(
-            vwr.ms, null, -1);
+        Map<String, Object> info = vwr.getSymTemp().getSpaceGroupInfo(vwr.ms,
+            null, -1);
         Object[] op = (info == null ? null : (Object[]) 
info.get("operations"));
         if (symop == 0 || op == null || op.length < Math.abs(symop))
           invArg();
@@ -6104,12 +6116,23 @@
       if (bsAtoms == null)
         bsAtoms = bsCompare;
     }
+    if (isSpin && qGT180) {
+      endDegrees = (endDegrees >= 0 ? 360 : -360) - endDegrees;
+      rotAxis.scale(-1);
+    }
+    if (q != null && !isSeconds && !isDegreesPerSecond) {
+      isDegreesPerSecond = (degreesPerSecond > 0);
+      isSeconds = !isDegreesPerSecond;
+    }
     float rate = (degreesPerSecond == PT.FLOAT_MIN_SAFE ? 10
         : endDegrees == Float.MAX_VALUE ? degreesPerSecond
-            : (degreesPerSecond < 0) == (endDegrees > 0) ?
-            // -n means number of seconds, not degreesPerSecond
-            -endDegrees / degreesPerSecond
-                : degreesPerSecond);
+            : isDegreesPerSecond ? degreesPerSecond
+                : isSeconds ? (endDegrees < 0 ? -1 : 1) * Math.abs(endDegrees 
/ degreesPerSecond)
+                    : (degreesPerSecond < 0) == (q == null ? endDegrees > 0
+                        : true) ?
+                    // -n means number of seconds, not degreesPerSecond
+                    -endDegrees / degreesPerSecond
+                        : degreesPerSecond);
 
     if (dihedralList != null) {
       if (!isSpin) {

Modified: trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java
===================================================================
--- trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java  2017-06-22 16:44:35 UTC 
(rev 21639)
+++ trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java  2017-06-25 20:37:45 UTC 
(rev 21640)
@@ -108,8 +108,10 @@
  * 
  * code history:
  * 
- * 6/12/2017 Jmo 14.18.2 tested for Rule 1b sphere (AY236.53, 163, 173, 192); 
957 lines
+ * 6/25/17 Jmol 14.19.1 minor fixes for Rule 4b and 5 for BH64_012-015; better 
atropisomer check
  * 
+ * 6/12/2017 Jmol 14.18.2 tested for Rule 1b sphere (AY236.53, 163, 173, 192); 
957 lines
+ * 
  * 6/8/2017 Jmol 14.18.2 removed unnecessary presort for Rule 1b
  * 
  * 5/27/17 Jmol 14.17.2 fully interfaced using SimpleNode and SimpleEdge
@@ -437,7 +439,6 @@
     // for reflection
     //System.out.println("TESTING ALLOWRULE1B");
     //allowRule1bAlkenes = false;
-    System.out.println("TESTING SPHERE+1");
   }
 
   /**
@@ -1696,7 +1697,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_4a);
+      boolean checkRule4List = (rule4List != null && (currentRule == RULE_4b 
|| currentRule == RULE_5));
       for (int i = 0; i < 4; i++) {
         CIPAtom a = atoms[i];
         for (int j = i + 1; j < 4; j++) {
@@ -1781,6 +1782,7 @@
 
       CIPAtom[] newAtoms = new CIPAtom[4];
       int[] newPriorities = new int[4];
+      String[] newRule4List = (rule4List == null ? null : new String[4]);
 
       BS bs = new BS();
       for (int i = 0; i < 4; i++) {
@@ -1787,11 +1789,14 @@
         int pt = indices[i];
         CIPAtom a = newAtoms[pt] = atoms[i];
         newPriorities[pt] = priorities[i];
+        if (rule4List != null)
+          newRule4List[pt] = rule4List[i];
         if (a.atom != null)
           bs.set(priorities[i]);
       }
       atoms = newAtoms;
       priorities = newPriorities;
+      rule4List = newRule4List;
       nPriorities = bs.cardinality();
 
       // Check for pseudochirality
@@ -2050,13 +2055,12 @@
       case RULE_3:
         return checkRule3(b); // can be IGNORE
       case RULE_4a:
-        return checkRules4a(b, " sr SR PM");
+        return checkRules4ac(b, " sr SR PM");
+      case RULE_4c:
+        return checkRules4ac(b, " s r p m");
       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
-        //        return checkRules4a4c(b, " s r");
       }
     }
 
@@ -2265,7 +2269,7 @@
     }
 
     /**
-     * Chapter 9 Rules 4 and 5: like vs. unlike
+     * Chapter 9 Rules 4b and 5: like vs. unlike
      * 
      * Compare two strings such as RSSSR and SRSRR for like and unlike and find
      * a winner. Return IGNORE if they are identical; return A_WINS or B_WINS 
if
@@ -2282,57 +2286,60 @@
       // resolved as "r" or "s" 
       // but generally we will want to process this as "R" and "S"
       // note that this analysis cannot be done ahead of time
-      String aStr = rule4List[ia].substring(1), bStr = 
rule4List[ib].substring(1);
-      if (currentRule == RULE_4c) {
-        aStr = PT.rep(aStr, "~", "");
-        bStr = PT.rep(bStr, "~", "");
+      String aStr = rule4List[ia].substring(1), bStr = rule4List[ib]
+          .substring(1);
+      boolean haveRSOptions = false, isRule5 = (currentRule == RULE_5);
+      String sa = "", sb = "";
+      if (atoms[ia].nextChiralBranch != null) {
+        sa = atoms[ia].nextChiralBranch.getMataList(getFirstRef(aStr), 
isRule5);
+      }
+      if (atoms[ib].nextChiralBranch != null) {
+        sb = atoms[ib].nextChiralBranch.getMataList(getFirstRef(bStr), 
isRule5);
+      }
+      haveRSOptions = (sa.indexOf("|") >= 0 || sb.indexOf("|") >= 0);
+      if (haveRSOptions) {
+        aStr += "|" + sa;
+        bStr += "|" + sb;
       } else {
-        boolean haveRS = false, 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); // Logger
-        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, "|"), bList = PT.split(bStr, "|");
-          int minScore = Integer.MAX_VALUE, 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];
-              }
+        aStr += sa;
+        bStr += sb;
+      }
+
+      if (true || Logger.debugging)
+        Logger.info(dots() + this + " comparing " + atoms[ia] + " " + aStr
+            + " to " + atoms[ib] + " " + bStr); // Logger
+      if (isRule5 || !haveRSOptions && 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 (haveRSOptions) {
+        // 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, "|"), bList = PT.split(bStr, "|");
+        int minScore = Integer.MAX_VALUE, sumScore = 0;
+        aStr = aList[0] + aList[1];
+        bStr = bList[0] + bList[1];
+        for (int i = aList.length; --i >= 1;) {
+          for (int j = bList.length; --j >= 1;) {
+            int score = compareRule4PairStr(aList[0] + aList[i], bList[0]
+                + bList[j], true);
+            sumScore += score;
+            if (score != TIED && Math.abs(score) <= minScore) {
+              minScore = Math.abs(score);
+              aStr = aList[0] + aList[i];
+              bStr = bList[0] + bList[j];
             }
           }
-          if (sumScore == TIED)
-            return TIED;
         }
+        if (sumScore == TIED)
+          return TIED;
       }
       if (aStr.length() == 1 && "RS".indexOf(aStr) < 0) {
         int score = checkEnantiomer(aStr, bStr, 0, aStr.length(), " rs");
@@ -2360,7 +2367,7 @@
      */
     private String getFirstRef(String aStr) {
       int r = aStr.indexOf("R"), s = aStr.indexOf("S");
-      return (r < 0 && s < 0 ? null : r < 0 ? "S" : "R");
+      return (r < 0 && s < 0 ? null : s > 0 && (r < 0 || r > s) ? "S" : "R");
     }
 
     /**
@@ -2407,7 +2414,7 @@
 
     /**
      * This is the key Mata method -- getting the correct sequence of R and S
-     * from a set of diasteromorphic paths. Given a specific reference
+     * from a set of diastereomorphic paths. Given a specific reference
      * designation, the task is to sort the paths based on priority (we can't
      * change the base priority already determined using Rules 1-3) and
      * reference.
@@ -2596,7 +2603,7 @@
             case A_WINS:
             case B_WINS:
               isBranch = true;
-              noPseudo = subRS.indexOf("r") >= 0;
+              noPseudo = (subRS.indexOf("r") >= 0);
               // enantiomers -- we have an r/s situation
               // process to determine chirality, but then set ret[0] to be null
               subRS = "";
@@ -2713,7 +2720,6 @@
               }
               if (noPseudo)
                 s = s.toUpperCase(); // Rule 4c or diasteriomers // AY-236.148
-              auxChirality = s;
               subRS = "";
               //if (ret != null)
               //ret[0] = null;
@@ -2730,6 +2736,7 @@
                 parent.addMataRef(sphere, priority, rs);
               }
             }
+            auxChirality = s;
           }
         }
       }
@@ -2812,8 +2819,17 @@
         return NOT_RELEVANT;
       if (rs1.equals(rs2))
         return TIED;
-      boolean haveRS = (rs1.indexOf("R") >= 0 || rs1.indexOf("S") >= 0);
-      String rs = (haveRS ? "~RS" : "~rs");
+      String rs = rs1 + rs2;
+      //System.out.println("compareRule4aIsomers:" + rs1 + " vs. " + rs2);
+      boolean haveRS = (rs.indexOf("R") >= 0 || rs.indexOf("S") >= 0);
+      if ((rs.indexOf("r") >= 0 || rs.indexOf("s") >= 0)) {
+        // consider Rule 4a here -- Sr beats R~ BH64_014
+          if (rs1.endsWith("~"))
+            return (DIASTEREOMERIC_B_WINS);
+          if (rs2.endsWith("~"))
+            return (DIASTEREOMERIC_A_WINS);
+      }
+      rs = (haveRS ? "~RS" : "~rs");
       if (haveRS) {
         rs1 = PT.replaceAllCharacters(rs1, "rs", "~");
         rs2 = PT.replaceAllCharacters(rs2, "rs", "~");
@@ -2840,7 +2856,7 @@
      * @param m
      * @param n
      * @param rs
-     * @return DIASTEROMERIC, A_WINS, or B_WINS
+     * @return DIASTEREOMERIC, A_WINS, or B_WINS
      */
     private int checkEnantiomer(String rs1, String rs2, int m, int n, String 
rs) {
       int finalScore = TIED; // not a possible return
@@ -2921,11 +2937,15 @@
      *        String to test against; depends upon subrule being checked
      * @return 0 (TIED), -1 (A_WINS), or 1 (B_WINS)
      */
-    private int checkRules4a(CIPAtom b, String test) {
+    private int checkRules4ac(CIPAtom b, String test) {
       if (isTerminal || isDuplicate)
         return TIED;
       int isRa = test.indexOf(auxChirality), isRb = 
test.indexOf(b.auxChirality);
-      return (isRa > isRb + 1 ? A_WINS : isRb > isRa + 1 ? B_WINS : TIED);
+      return (isRa > isRb + 1 ? 
+          A_WINS 
+          : isRb > isRa + 1 ? 
+              B_WINS 
+              : TIED);
     }
 
     /**
@@ -2967,6 +2987,7 @@
       a.htPathPoints = htPathPoints;
       a.doCheckPseudo = false;
       a.alkeneParent = null;
+      a.auxChirality = "~";
       for (int i = 0; i < 4; i++)
         if (atoms[i] != null)
           a.atoms[i] = atoms[i];
@@ -2978,7 +2999,9 @@
     public String toString() {
       return (atom == null ? "<null>" : "[" + currentRule + "." + sphere + ","
           + id + "." + atom.getAtomName()
-          + (isDuplicate ? "*(" + rootDistance + ")": "") + "]");
+          + (isDuplicate ? "*(" + rootDistance + ")": "")
+          + (auxChirality == null ? "" : auxChirality)
+          + "]");
     }
 
   }

Modified: trunk/Jmol/src/org/jmol/symmetry/Symmetry.java
===================================================================
--- trunk/Jmol/src/org/jmol/symmetry/Symmetry.java      2017-06-22 16:44:35 UTC 
(rev 21639)
+++ trunk/Jmol/src/org/jmol/symmetry/Symmetry.java      2017-06-25 20:37:45 UTC 
(rev 21640)
@@ -768,7 +768,10 @@
     CIPChirality cip = getCIPChirality(vwr);
     BS bsAtropisomer = null, bsHelixM = null, bsHelixP = null;
     try {
-      bsAtropisomer = vwr.getSmartsMatch("a-a", bsAtoms);
+// four ortho groups required:      bsAtropisomer = 
vwr.getSmartsMatch("[!H](.t3:-20,20)a1(.t3).[!H](.t1:-20,20)a(.t1)a1(.t1)(.t2:-20,20)(.t3)(.t4:-20,20)-{a}2(.t1)(.t2)(.t3)(.t4)a(.t2)[!H](.t2).a2(.t4)[!H](.t4)",
 bsAtoms);
+// three ortho groups required:     bsAtropisomer = 
vwr.getSmartsMatch("[!H](.t3:-20,20)a1(.t3).[!H](.t1:-20,20)a(.t1){a}1(.t1)(.t2:-20,20)(.t3)-{a}(.t1)(.t2)(.t3)a(.t2)[!H](.t2)",
 bsAtoms);
+// one ortho group on each ring required:
+      bsAtropisomer = 
vwr.getSmartsMatch("[!H](.t1:-20,20)a{a(.t2:-20,20)-a}a[!H]", bsAtoms);
       bsHelixM = vwr.getSmartsMatch("A{a}(.t:-10,-40)a(.t:-10,-40)aaa", 
bsAtoms);
       bsHelixP = vwr.getSmartsMatch("A{a}(.t:10,40)a(.t:10,40)aaa", bsAtoms);
     } catch (Exception e) {

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2017-06-22 16:44:35 UTC 
(rev 21639)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2017-06-25 20:37:45 UTC 
(rev 21640)
@@ -58,11 +58,13 @@
 
 Jmol.___JmolVersion="14.19.1"
 
+bug fix: CIPChirality: minor fixes for Rule 4b and 5 for BH64_012-015; better 
atropisomer check
+bug fix; SPIN QUATERNION 
 bug fix: CENTERAT ABSOLUTE broken (since forever?)
-bug fix: SPIN quaternion {0 0 -1 0} still does a positive, not negative, 
rotation
+bug fix: SPIN QUATERNION {0 0 -1 0} still does a positive, not negative, 
rotation
  (solution is to apply a miniscule rotation of 1e-10 degrees)
  
-bug fix: scirpt array context [3 -0] becomes [3], as in [3 - 0]
+bug fix: script array context [3 -0] becomes [3], as in [3 - 0]
 
 new feature: WRITE "SDF" implements atom value V  nnn ... information
  -- requires assigning the data property name "atom_values" in the model's 
molData property

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