Revision: 21647
          http://sourceforge.net/p/jmol/code/21647
Author:   hansonr
Date:     2017-07-03 15:12:15 +0000 (Mon, 03 Jul 2017)
Log Message:
-----------
 * 7/3/17 Jmol 14.20.1 major rewrite to correct and simplify logic; full 
validation
 *  for 433 structures (many duplicates) in AY236, BH64, MV64, MV116, JM, and L 
(949 lines)

Modified Paths:
--------------
    trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java

Modified: trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java
===================================================================
--- trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java  2017-07-03 13:12:40 UTC 
(rev 21646)
+++ trunk/Jmol/src/org/jmol/symmetry/CIPChirality.java  2017-07-03 15:12:15 UTC 
(rev 21647)
@@ -116,7 +116,7 @@
  * code history:
  * 
  * 7/3/17 Jmol 14.20.1 major rewrite to correct and simplify logic; full 
validation
- *  for 433 structures (many duplicates) in AY236, BH64, MV64, MV116, JM, and 
L (974 lines)
+ *  for 433 structures (many duplicates) in AY236, BH64, MV64, MV116, JM, and 
L (949 lines)
  * 
  * 6/30/17 Jmol 14.20.1 major rewrite of Rule 4b (999 lines)
  * 
@@ -412,14 +412,15 @@
 
   static final int RULE_1a = 1;
   static final int RULE_1b = 2;
-  static final int RULE_2 = 3;
-  static final int RULE_3 = 4;
+  static final int RULE_2  = 3;
+  static final int RULE_3  = 4;
   static final int RULE_4a = 5;
   static final int RULE_4b = 6;
   static final int RULE_4c = 7;
-  static final int RULE_5 = 8;
+  static final int RULE_5  = 8;
 
   static String prefixString = "..........";
+  
   static Integer zero = Integer.valueOf(0);
 
   public String getRuleName() {
@@ -685,7 +686,7 @@
     boolean mustBePlanar = false;
     switch (a.getCovalentBondCount()) {
     default:
-      System.out.println("???? too many bonds! " + a);
+      System.out.println("?? too many bonds! " + a);
       return false;
     case 0:
       return false;
@@ -1022,34 +1023,34 @@
    * Determine R/S or one half of E/Z determination
    * 
    * @param atom
-   *        ignored if a is not null
+   *        ignored if a is not null (just checking ene end top priority)
    * @param cipAtom
    *        ignored if atom is not null
    * @param parent
    *        null for tetrahedral, other alkene carbon for E/Z
    * 
-   * @return if parent != null: [0:none, 1:R, 2:S] otherwise [0:none, 1:
-   *         atoms[0] is higher, 2: atoms[1] is higher]
+   * @return if and E/Z test, [0:none, 1: atoms[0] is higher, 2: atoms[1] is 
higher]
+   *         otherwise [0:none, 1:R, 2:S] 
    */
   private int getAtomChiralityLimited(SimpleNode atom, CIPAtom cipAtom,
                                       CIPAtom parent) {
     int rs = NO_CHIRALITY;
-    boolean isAlkene = false;
+    boolean isAlkeneEndCheck = (atom == null);
     try {
-      if (cipAtom == null) {
-        cipAtom = new CIPAtom().create(atom, null, isAlkene, false, false);
+      if (isAlkeneEndCheck) {
+        atom = cipAtom.atom;
+      } else {
+        // If this is a root-atom call (not an alkene end determination)
+        // then this is a call to root; we do not know at this point if it 
+        // is an atom we can process or not
+        cipAtom = new CIPAtom().create(atom, null, false, false, false);
         int nSubs = atom.getCovalentBondCount(), elemNo = atom
             .getElementNumber();
-        isAlkene = (nSubs == 3 && elemNo <= 10 && 
!cipAtom.isTrigonalPyramidal); // (IUPAC 2013.P-93.2.4)
-        if (nSubs != (parent == null ? 4 : 3)
-            - (nSubs == 3 && !isAlkene ? 1 : 0))
-          return rs;
-      } else {
-        atom = cipAtom.atom;
-        isAlkene = cipAtom.isAlkene;
+        boolean isSP2 = (nSubs == 3 && elemNo <= 10 && 
!cipAtom.isTrigonalPyramidal); // (IUPAC 2013.P-93.2.4)
+        if (nSubs != (parent == null ? 4 : 3) - (nSubs == 3 && !isSP2 ? 1 : 0))
+          return NO_CHIRALITY;
       }
-      root = cipAtom;
-      cipAtom.parent = parent;
+      (root = cipAtom).parent = parent;
       if (parent != null)
         cipAtom.htPathPoints = parent.htPathPoints;
       currentRule = RULE_1a;
@@ -1079,13 +1080,14 @@
               }
             }
 
-            if (isAlkene) {
-              rs = (cipAtom.atoms[0].isDuplicate ? STEREO_S : STEREO_R);
-            } else {
-              rs = cipAtom.checkHandedness()
-                  | (currentRule == RULE_5 && cipAtom.canBePseudo ? 
JC.CIP_CHIRALITY_PSEUDO_FLAG
-                      : 0);
-            }
+            // If this is an alkene end check, we just use STERE_S and 
STEREO_R as markers
+            
+            if (isAlkeneEndCheck)
+              return (cipAtom.atoms[0].isDuplicate ? 2 : 1);
+            
+            rs = cipAtom.checkHandedness()
+                | (currentRule == RULE_5 && cipAtom.canBePseudo ? 
JC.CIP_CHIRALITY_PSEUDO_FLAG
+                    : 0);
             if (Logger.debugging)
               Logger.info(atom + " " + JC.getCIPChiralityName(rs) + " by Rule "
                   + getRuleName() + "\n----------------------------------"); 
// Logger
@@ -1157,6 +1159,27 @@
       if (isAxial && ((ruleA == RULE_5) != (ruleB == RULE_5))) {
         // only one of the ends may be enantiomeric to make this r or s 
         // see AY236.70 and AY236.170
+        //
+        // Now we must check maxRules. If [5,5], then we have
+        // 
+        //    R      R'
+        //     \    /
+        //       ==
+        //     /    \
+        //    S      S'
+        //
+        // planar flip is unchanged, and this is c/t (ignored here)
+        // 
+        // 
+        //    R      R
+        //     \    /
+        //       ==
+        //     /    \
+        //    S      S
+        //
+        // planar flip is unchanged; also c/t (ignored here)
+        // 
+
         c |= JC.CIP_CHIRALITY_PSEUDO_FLAG;
       }
       a.setCIPChirality(c | ((ruleA - 1) << JC.CIP_CHIRALITY_NAME_OFFSET));
@@ -1199,7 +1222,7 @@
    */
   private int getAlkeneEndTopPriority(CIPAtom a, SimpleNode pa, boolean 
isAxial) {
     a.canBePseudo = isAxial;
-    return getAtomChiralityLimited(a.atom, a,
+    return getAtomChiralityLimited(null, a,
         new CIPAtom().create(pa, null, true, false, false)) - 1;
   }
 
@@ -1486,15 +1509,15 @@
     /**
      * a list of string buffers that tracks full-length stereochemical paths 
for
      * the branch's root atom only for Mata analysis in the form of
-     * p1XXXXXp2YYYYp3ZZZZZ where pn is 0-3, the priority up through Rule 4a;
+     * p1p2p3XXXXXYYYYZZZZZ where pn is 1-4, the priority up through Rule 4a;
      * used for the final flattening of the ligand path for like/unlike 
analysis
      * 
      */
     
-    private Lst<String[]> rule4Paths;
+    private Lst<String[]> rootRule4Paths;
 
     /**
-     * a list of priorities from the root leading this branch
+     * a list of priorities from the root leading this branch; used to build 
rootRule4Paths
      * 
      */
     private String priorityPath;
@@ -1501,7 +1524,7 @@
 
     /**
      * for the root atom, the number of auxiiary centers; for other atoms, the 
auxiiary
-     * chirality type: 0: ~, 1: R, 2: S
+     * chirality type: 0: ~, 1: R, 2: S; normalized to R/S even if M/P or C/T
      */
     int rule4Type;
     
@@ -2255,7 +2278,7 @@
           || !parent.isAlkeneAtom2 || !b.parent.isAlkeneAtom2
           || !parent.alkeneParent.isEvenEne || 
!b.parent.alkeneParent.isEvenEne ? IGNORE
           : parent == b.parent ? sign(breakTie(b, 0))
-              : (za = parent.getEZaux()) < (zb = b.parent.getEZaux()) ? A_WINS
+              : (za = parent.getRule3auxEZ()) < (zb = 
b.parent.getRule3auxEZ()) ? A_WINS
                   : za > zb ? B_WINS : TIED;
     }
 
@@ -2272,44 +2295,33 @@
      * 
      * @return one of [STEREO_Z, STEREO_E, STEREO_BOTH_EZ]
      */
-    private int getEZaux() {
-      // this is the second atom of the alkene, checked as the parent of the 
next atom
-      // (because there is no need to do this test until we are on the branch 
that includes
-      //  the atom after the alkene).
-      if (auxEZ == STEREO_UNDETERMINED
-          && (auxEZ = alkeneParent.auxEZ) == STEREO_UNDETERMINED) {
-        int[] maxRules = new int[] {RULE_3, RULE_3};
-        auxEZ = getEneWinnerChirality(alkeneParent, this, false, maxRules);
-        if (auxEZ == NO_CHIRALITY)
-          auxEZ = STEREO_BOTH_EZ;
-      }
-      alkeneParent.auxEZ = auxEZ;
-      if (Logger.debuggingHigh)
-        Logger.info("getZaux " + alkeneParent + " " + auxEZ);
-      return auxEZ;
+    private int getRule3auxEZ() {
+
+      // "this" is the second atom of the alkene, checked as the parent of one 
of its ligands, 
+      // as there is no need to do this test until we are on the branch that 
includes
+      // the atom after the alkene.
+
+      return alkeneParent.auxEZ = (auxEZ != STEREO_UNDETERMINED ? auxEZ
+          : (auxEZ = getAuxEneWinnerChirality(alkeneParent, this, false, 
RULE_3)) == NO_CHIRALITY ? (auxEZ = STEREO_BOTH_EZ)
+              : auxEZ);
     }
 
     /**
-     * Determine the winner on one end of an alkene or cumulene.
+     * Determine the winner on one end of an alkene or cumulene,
+     * accepting a max rule of RULE_3 or RULE_5, depending upon the application
      * 
      * @param end1
      * @param end2
      * @param isAxial
-     * @param maxRuleRet [max,max] returns  [max1, max2]
+     * @param maxRule RULE_3 or RULE_5
      * @return one of: {NO_CHIRALITY | STEREO_Z | STEREO_E | STEREO_M |
      *         STEREO_P}
      */
-    private int getEneWinnerChirality(CIPAtom end1, CIPAtom end2,
-                                      boolean isAxial, int[] maxRuleRet) {
-      // [0] returns max rule for determination 1
-      CIPAtom winner1 = getEneEndWinner(end1, end1.nextSP2, maxRuleRet);
-      int max1 = maxRuleRet[0];
-      maxRuleRet[0] = maxRuleRet[1];
+    private int getAuxEneWinnerChirality(CIPAtom end1, CIPAtom end2,
+                                      boolean isAxial, int maxRule) {
+      CIPAtom winner1 = getAuxEneEndWinner(end1, end1.nextSP2, maxRule);
       CIPAtom winner2 = (winner1 == null || winner1.atom == null ? null
-          : getEneEndWinner(end2, end2.nextSP2, maxRuleRet));
-      maxRuleRet[1] = maxRuleRet[0];
-      maxRuleRet[0] = max1;
-      // returns [max1, max2]
+          : getAuxEneEndWinner(end2, end2.nextSP2, maxRule));
       return getEneChirality(winner1, end1, end2, winner2, isAxial, false);
     }
 
@@ -2320,28 +2332,69 @@
      * 
      * @param end
      * @param prevSP2
-     * @param ruleMaxRet
+     * @param maxRule
      * @return higher-priority atom, or null if they are equivalent
      */
-    private CIPAtom getEneEndWinner(CIPAtom end, CIPAtom prevSP2, int[] 
ruleMaxRet) {
+    private CIPAtom getAuxEneEndWinner(CIPAtom end, CIPAtom prevSP2, int 
maxRule) {
       CIPAtom atom1 = (CIPAtom) end.clone();
-      int ruleMax = ruleMaxRet[0];
       if (atom1.parent != prevSP2)        
         atom1.addReturnPath(prevSP2, end);
-      else if (ruleMax > RULE_3)
+      else if (maxRule == RULE_5)
         atom1.rule4List = end.rule4List;
-      CIPAtom a = null;
-      ruleMaxRet[0] = -1;
-      for (int i = RULE_1a; i <= ruleMax; i++)
-        if ((a = atom1.getTopSorted(i)) != null) {
-          ruleMaxRet[0] = i;
-          break;
-        }     
-      return (a == null || a.atom == null ? null : a);
+      CIPAtom a;
+      for (int i = RULE_1a; i <= maxRule; i++)
+        if ((a = atom1.getTopSorted(i)) != null) 
+          return (a.atom == null  ? null : a);
+      return null;
     }
 
     /**
+     * Return top-priority non-sp2-duplicated atom.
      * 
+     * @param rule
+     * 
+     * @return highest-priority non-duplicated atom
+     */
+    private CIPAtom getTopSorted(int rule) {
+      if (sortByRule(rule))
+        for (int i = 0; i < 4; i++) {
+          CIPAtom a = atoms[i];
+          if (!a.sp2Duplicate)
+            return priorities[i] == priorities[i + 1] ? null : atoms[i];
+        }
+      return null;
+    }
+
+    /**
+     * Sort for auxiliary chirality determination
+     * 
+     * @param maxRule
+     * @return TIED or deciding rule RULE_1a - RULE_5
+     */
+    private int sortToRule(int maxRule) {
+      for (int i = RULE_1a; i <= maxRule; i++)
+        if (sortByRule(i))
+          return i;
+      return TIED;
+    }
+    
+    /**
+     * Sort by a given rule, preserving currentRule.
+     * 
+     * @param rule
+     * @return true if a decision has been made
+     */
+    private boolean sortByRule(int rule) {
+      int current = currentRule;
+      currentRule = rule;
+      boolean isChiral = sortSubstituents(0);
+      currentRule = current;
+      return isChiral;
+    }
+
+
+    /**
+     * 
      * @param newParent
      * @param fromAtom
      */
@@ -2528,19 +2581,16 @@
      */
     void generateRule4Paths() {
       
-      getRule4Paths("");
-
-      
-      rule4Paths = new Lst<String[]>();
+      getRule4PriorityPaths("");
+      rootRule4Paths = new Lst<String[]>();
       appendRule4Paths(this, new String[3]);
-
       getRule4Counts(rule4Count = new Object[] { null, zero, zero, 
Integer.valueOf(10000)});
       
       if (Logger.debugging) {
         Logger.info("Rule 4b paths for " + this + "=\n");
-      for (int i = 0; i < rule4Paths.size(); i++) { // Logger
-        String s = rule4Paths.get(i)[0].toString(); // Logger
-        int prefixLen = rule4Paths.get(i)[1].length(); // Logger
+      for (int i = 0; i < rootRule4Paths.size(); i++) { // Logger
+        String s = rootRule4Paths.get(i)[0].toString(); // Logger
+        int prefixLen = rootRule4Paths.get(i)[1].length(); // Logger
         while (prefixString.length() < prefixLen) // Logger
           prefixString += prefixString;  // Logger
         Logger.info(prefixString.substring(0,  prefixLen) + 
s.substring(prefixLen) + " " + priorityPath);
@@ -2549,30 +2599,51 @@
       }
     }
     
+    /**
+     * Recursively build paths to stereocenters to estabish the path priority 
lexicographically.
+     *  
+     * @param path
+     */
+    private void getRule4PriorityPaths(String path) {
+      priorityPath = path + (priority + 1);
+      for (int i = 0; i < 4; i++)
+        if (rule4List[i] != null)
+          atoms[i].getRule4PriorityPaths(priorityPath);
+    }
+    
     private void getRule4Counts(Object[] counts) {
       if (sphere > ((Integer) counts[3]).intValue())
         return;
-      if (setAuxiliary && auxChirality != "~") {
+      if (setAuxiliary && auxChirality != "~")
         atom.setCIPChirality(JC.getCIPChiralityCode(auxChirality));
+      if (rule4Type > 0) {
+        // Accumlate the number of R and S centers of a given cumlative 
priority
+        int val = sign(priorityPath.length() - (counts[0] == null ? 10000 : 
((String) counts[0]).length()));
+        if (val == 0)
+          val = sign(priorityPath.compareTo(counts[0].toString()));
+        switch (val) {
+        case -1:
+          counts[0] = priorityPath;
+          counts[STEREO_R] = counts[STEREO_S] = zero;
+          counts[3] = Integer.valueOf(sphere);
+          //$FALL-THROUGH$
+        case 0:
+          counts[rule4Type] = Integer.valueOf(((Integer) 
counts[rule4Type]).intValue() + 1);
+          break;
+        }
+        if (Logger.debugging)
+          Logger.info(this + " addRule4Ref " + sphere + " " + priority + " " + 
rule4Type
+              + " " + PT.toJSON("rule4Count", counts));  // Logger
       }
-      if (rule4Type > 0)
-        addMataRef(counts);
       for (int i = 0; i < 4; i++)
         if (rule4List[i] != null)
           atoms[i].getRule4Counts(counts);
     }
     
-    private void getRule4Paths(String path) {
-      priorityPath = path + (priority + 1);
-      for (int i = 0; i < 4; i++)
-        if (rule4List[i] != null)
-          atoms[i].getRule4Paths(priorityPath);
-    }
-    
     private void appendRule4Paths(CIPAtom rootsub, String[] pathInfo) {
       String s0 = (pathInfo[0] == null ? auxChirality : pathInfo[0]);
       if (pathInfo[2] == null)
-        rootsub.rule4Paths.addLast(pathInfo = new String[] {s0, "", 
priorityPath});
+        rootsub.rootRule4Paths.addLast(pathInfo = new String[] {s0, "", 
priorityPath});
       boolean isFirst = true;
       for (int i = 0; i < 4; i++)
         if (rule4List[i] != null) {
@@ -2579,7 +2650,7 @@
           if (isFirst)
               pathInfo[2] = priorityPath; 
           else
-            rootsub.rule4Paths.addLast(pathInfo = new String[] {s0, s0, 
priorityPath});
+            rootsub.rootRule4Paths.addLast(pathInfo = new String[] {s0, s0, 
priorityPath});
           isFirst = false;
           pathInfo[0] += rule4List[i];
           if (atoms[i].nextChiralBranch != null)
@@ -2615,13 +2686,13 @@
      * @return a string that can be compared with another using like/unlike
      */ 
     private String flattenRule4Paths(char ref, boolean isRule5) {
-      int nPaths = rule4Paths.size();
+      int nPaths = rootRule4Paths.size();
       String[] paths = new String[nPaths];      
       int nMax = 0;
       for (int i = 0; i < nPaths; i++) {
         // remove all enantiomorphic descriptors
-        String path = rule4Paths.get(i)[0];
-        String priorityPath = rule4Paths.get(i)[2];
+        String path = rootRule4Paths.get(i)[0];
+        String priorityPath = rootRule4Paths.get(i)[2];
         String s = PT.replaceAllCharacters(path, "srctmp", "~");
         // remove all 
         paths[i] = s = priorityPath + s.replace(ref, 'A');
@@ -2851,30 +2922,10 @@
               //
               if (!isEvenEne || (auxEZ == STEREO_BOTH_EZ || auxEZ == 
STEREO_UNDETERMINED)
                   && alkeneChild.bondCount >= 2 && !isKekuleAmbiguous) {
-                int[] maxRules = new int[] { RULE_5, RULE_5 };
-                rs = getEneWinnerChirality(this, alkeneChild, !isEvenEne, 
maxRules);
+                rs = getAuxEneWinnerChirality(this, alkeneChild, !isEvenEne, 
RULE_5);
                 //
-                // Now we must check maxRules. If [5,5], then we have
+                // Note that we can have C/T (rule4Type = R/S):
                 // 
-                //    R      R'
-                //     \    /
-                //       ==
-                //     /    \
-                //    S      S'
-                //
-                // planar flip is unchanged, and this is c/t (ignored here)
-                // 
-                // 
-                //    R      R
-                //     \    /
-                //       ==
-                //     /    \
-                //    S      S
-                //
-                // planar flip is unchanged; also c/t (ignored here)
-                // 
-                // But note that we can have C/T (rule4Type = R/S)
-                // 
                 //    R      x
                 //     \    /
                 //       ==
@@ -2883,29 +2934,22 @@
                 //
                 // flips sense upon planar inversion; determination was Rule 5.
                 //
-                boolean ignoreCT = (isEvenEne && maxRules[0] == RULE_5 && 
maxRules[1] == RULE_5);
+                // Normalize M/P and E/Z to R/S
                 switch (rs) {
                 case STEREO_M:
+                case STEREO_Z:
                   rs = STEREO_R;
                   s = "R";
                   break;
                 case STEREO_P:
+                case STEREO_E:
                   rs = STEREO_S;
                   s = "S";
                   break;
-                case STEREO_Z:
-                  rs = STEREO_R;
-                  s = (ignoreCT ? "r" : "R");
-                  break;
-                case STEREO_E:
-                  rs = STEREO_S;
-                  s = (ignoreCT ? "s" : "S");
-                  break;
                 }
                 if (rs != NO_CHIRALITY) {
                   auxChirality = s;
-                  if (!ignoreCT)
-                    rule4Type = rs;
+                  rule4Type = rs;
                   subRS = "";
                   if (isSeqCT) {
                     nextChiralBranch = alkeneChild;
@@ -2924,7 +2968,7 @@
             if (isBranch && adj != NOT_RELEVANT) {
               // if here, adj is A_WINS (-1), or B_WINS (1) 
               // we check based on A winning, but then reverse it if B 
actually won
-              switch (checkPseudoHandedness(mataList)) {
+              switch (rule4CheckPseudoHandedness(mataList)) {
               case STEREO_R:
                 s = (adj == A_WINS ? "r" : "s");
                 break;
@@ -2970,56 +3014,35 @@
     }
 
     /**
-     * Sort by a given rule, preserving root.canBePseudo and currentRule.
+     * Reverse the path to the parent and check r/s chirality
      * 
-     * @param rule
-     * @return true if a decision has been made
-     */
-    private boolean sortByRule(int rule) {
-      boolean rootPseudo = root.canBePseudo;
-      int current = currentRule;
-      currentRule = rule;
-      boolean isChiral = sortSubstituents(0);
-      currentRule = current;
-      root.canBePseudo = rootPseudo;
-      return isChiral;
-    }
-
-    /**
-     * Sort for auxiliary chirality determination
+     * @param iab
+     * @return STEREO_R or STEREO_S
      * 
-     * @param maxRule
-     * @return TIED or deciding rule RULE_1a - RULE_5
      */
-    private int sortToRule(int maxRule) {
-      for (int i = RULE_1a; i <= maxRule; i++)
-        if (sortByRule(i))
-          return i;
-      return TIED;
-    }
-
-    /**
-     * Accumlate the number of R and S centers of a given cumlative priority
-     * 
-     * @param rule4Counts 
-     */
-    private void addMataRef(Object[] rule4Counts) {
-      int val = sign(priorityPath.length() - (rule4Counts[0] == null ? 10000 : 
((String) rule4Counts[0]).length()));
-      if (val == 0)
-        val = sign(priorityPath.compareTo(rule4Counts[0].toString()));
-      switch (val) {
-      case -1:
-        rule4Counts[0] = priorityPath;
-        rule4Counts[STEREO_R] = rule4Counts[STEREO_S] = zero;
-        rule4Counts[3] = Integer.valueOf(sphere);
-        //$FALL-THROUGH$
-      case 0:
-        rule4Counts[rule4Type] = Integer.valueOf(((Integer) 
rule4Counts[rule4Type]).intValue() + 1);
-        break;
+    private int rule4CheckPseudoHandedness(int[] iab) {
+      int ia = iab[0];
+      int ib = iab[1];
+      CIPAtom atom1;
+      // critical here that we do NOT include the tied branches
+      atom1 = (CIPAtom) clone();
+      atom1.atoms[ia] = new CIPAtom().create(null, atom1, false, false, false);
+      atom1.atoms[ib] = new CIPAtom().create(null, atom1, false, false, false);
+      atom1.addReturnPath(null, this);
+      // We are guaranteed that only RULE_1a is necessary, because one of our
+      // paths goes all the way back to the root, without a duplicate atom, 
and any
+      // other path reaching that will terminate with a duplicate atom instead.
+      atom1.sortByRule(RULE_1a);
+      // 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[bondCount - 2] = atoms[Math.min(ia, ib)];
+      atom1.atoms[bondCount - 1] = atoms[Math.max(ia, ib)];
+      int rs = atom1.checkHandedness();
+      if (Logger.debugging) {
+        for (int i = 0; i < 4; i++) // Logger
+          Logger.info("pseudo " + rs + " " + priorities[i] + " " + 
atoms[i].myPath);
       }
-      if (Logger.debugging)
-        Logger.info(this + " addMata " + sphere + " " + priority + " " + 
rule4Type
-            + " " + PT.toJSON("rule4Count", rule4Counts));  // Logger
+      return rs;
     }
 
     /**
@@ -3102,55 +3125,6 @@
     }
 
     /**
-     * Reverse the path to the parent and check r/s chirality
-     * 
-     * @param iab
-     * @return STEREO_R or STEREO_S
-     * 
-     */
-    private int checkPseudoHandedness(int[] iab) {
-      int ia = iab[0];
-      int ib = iab[1];
-      CIPAtom atom1;
-      // critical here that we do NOT include the tied branches
-      atom1 = (CIPAtom) clone();
-      atom1.atoms[ia] = new CIPAtom().create(null, atom1, false, false, false);
-      atom1.atoms[ib] = new CIPAtom().create(null, atom1, false, false, false);
-      atom1.addReturnPath(null, this);
-      // We are guaranteed that only RULE_1a is necessary, because one of our
-      // paths goes all the way back to the root, without a duplicate atom, 
and any
-      // other path reaching that will terminate with a duplicate atom instead.
-      atom1.sortByRule(RULE_1a);
-      // 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[bondCount - 2] = atoms[Math.min(ia, ib)];
-      atom1.atoms[bondCount - 1] = atoms[Math.max(ia, ib)];
-      int rs = atom1.checkHandedness();
-      if (Logger.debugging) {
-        for (int i = 0; i < 4; i++) // Logger
-          Logger.info("pseudo " + rs + " " + priorities[i] + " " + 
atoms[i].myPath);
-      }
-      return rs;
-    }
-
-    /**
-     * Return top-priority non-sp2-duplicated atom.
-     * 
-     * @param rule
-     * 
-     * @return highest-priority non-duplicated atom
-     */
-    private CIPAtom getTopSorted(int rule) {
-      if (sortByRule(rule))
-        for (int i = 0; i < 4; i++) {
-          CIPAtom a = atoms[i];
-          if (!a.sp2Duplicate)
-            return priorities[i] == priorities[i + 1] ? null : atoms[i];
-        }
-      return null;
-    }
-
-    /**
      * Chapter 9 Rules 4a and 4c. This method allows for "RS" to be checked as
      * "either R or S". See AY236.66, AY236.67,
      * AY236.147,148,156,170,171,201,202, etc. (4a)
@@ -3211,7 +3185,7 @@
       a.alkeneParent = null;
       a.rule4Count = null;
       a.rule4List = null;
-      a.rule4Paths = null;
+      a.rootRule4Paths = null;
       a.priority = a.rule4Type = 0;
       a.auxChirality = "~";
       a.auxEZ = STEREO_UNDETERMINED;

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