Revision: 20982
          http://sourceforge.net/p/jmol/code/20982
Author:   hansonr
Date:     2016-03-07 04:22:42 +0000 (Mon, 07 Mar 2016)
Log Message:
-----------
Jmol.___JmolVersion="14.5.3_2016.03.06"

new feature: optional processing of OpenSMILES [CH2:002] ":<n>" atom class.
 -- positive integer value only
 -- checks the atom property property_osclass
 -- for SMARTS, [:0] means "without an osclass"
 -- for SMARTS, [!:0] means "any non-zero osclass"
 -- for SMARTS, same as [$(select property_osclass=n)]
 -- only enabled with Jmol SMILES directive "/opensmiles/"; otherwise ignored

new feature: {*}.find("OPENSMILES")
 -- adds atom class if property_osclass is nonzero
    
bug fix: Inconsistent use of "DIASTEREOMERS" (preferred) and "DIASTERIOMERS" 
(incorrect)

Modified Paths:
--------------
    branches/v14_4/Jmol/src/org/jmol/api/SmilesMatcherInterface.java
    branches/v14_4/Jmol/src/org/jmol/minimize/forcefield/ForceFieldMMFF.java
    branches/v14_4/Jmol/src/org/jmol/modelset/Atom.java
    branches/v14_4/Jmol/src/org/jmol/scriptext/MathExt.java
    branches/v14_4/Jmol/src/org/jmol/smiles/SmilesAtom.java
    branches/v14_4/Jmol/src/org/jmol/smiles/SmilesGenerator.java
    branches/v14_4/Jmol/src/org/jmol/smiles/SmilesMatcher.java
    branches/v14_4/Jmol/src/org/jmol/smiles/SmilesParser.java
    branches/v14_4/Jmol/src/org/jmol/smiles/SmilesSearch.java
    branches/v14_4/Jmol/src/org/jmol/util/Edge.java
    branches/v14_4/Jmol/src/org/jmol/util/Node.java
    branches/v14_4/Jmol/src/org/jmol/viewer/JC.java
    trunk/Jmol/src/org/jmol/api/SmilesMatcherInterface.java
    trunk/Jmol/src/org/jmol/minimize/forcefield/ForceFieldMMFF.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/smiles/SmilesGenerator.java
    trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java
    trunk/Jmol/src/org/jmol/smiles/SmilesParser.java
    trunk/Jmol/src/org/jmol/smiles/SmilesSearch.java
    trunk/Jmol/src/org/jmol/util/Edge.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: branches/v14_4/Jmol/src/org/jmol/api/SmilesMatcherInterface.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/api/SmilesMatcherInterface.java    
2016-03-06 18:23:15 UTC (rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/api/SmilesMatcherInterface.java    
2016-03-07 04:22:42 UTC (rev 20982)
@@ -45,9 +45,8 @@
                                              int ac, BS bsSelected,
                                              int flags) throws Exception;
 
-  public abstract void getSubstructureSets(String[] smarts, Node[] atoms, int 
ac,
-                                           int flags,
-                         BS bsSelected, Lst<BS> bitSets, Lst<BS>[] vRings) 
throws Exception;
+  public abstract void getMMFF94AtomTypes(String[] smarts, Node[] atoms, int 
ac,
+                                           BS bsSelected, Lst<BS> bitSets, 
Lst<BS>[] vRings) throws Exception;
 
   public abstract String getSmiles(Node[] atoms, int ac, BS bsSelected,
                                       String bioComment, int flags) throws 
Exception;

Modified: 
branches/v14_4/Jmol/src/org/jmol/minimize/forcefield/ForceFieldMMFF.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/minimize/forcefield/ForceFieldMMFF.java    
2016-03-06 18:23:15 UTC (rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/minimize/forcefield/ForceFieldMMFF.java    
2016-03-07 04:22:42 UTC (rev 20982)
@@ -870,8 +870,7 @@
     // identifies that atom's MMFF94 type.
 
     try {
-      smartsMatcher.getSubstructureSets(smarts, atoms, atoms.length,
-          Edge.FLAG_AROMATIC_STRICT | Edge.FLAG_AROMATIC_DOUBLE,
+      smartsMatcher.getMMFF94AtomTypes(smarts, atoms, atoms.length,
           bsConnected, bitSets, vRings);
     } catch (Exception e) {
       Logger.error(e.toString());

Modified: branches/v14_4/Jmol/src/org/jmol/modelset/Atom.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/modelset/Atom.java 2016-03-06 18:23:15 UTC 
(rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/modelset/Atom.java 2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -33,6 +33,7 @@
 import javajs.util.T3;
 import javajs.util.V3;
 
+import org.jmol.api.JmolDataManager;
 import org.jmol.api.JmolModulationSet;
 import org.jmol.api.SymmetryInterface;
 import org.jmol.atomdata.RadiusData;
@@ -1420,4 +1421,18 @@
     return (m.isBioModel ? ((BioModel) m).getUnitID(this, flags) : "");
   }
 
+  @Override
+  public float getFloatProperty(String property) {
+    Object data = group.chain.model.ms.vwr.getDataObj(property, null,
+        JmolDataManager.DATA_TYPE_AF);
+    float f = 0;
+    if (data != null) {
+      try {
+        f = ((float[]) data)[i];
+      } catch (Exception e) {
+      }
+    }
+    return f;
+  }
+
 }

Modified: branches/v14_4/Jmol/src/org/jmol/scriptext/MathExt.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/scriptext/MathExt.java     2016-03-06 
18:23:15 UTC (rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/scriptext/MathExt.java     2016-03-07 
04:22:42 UTC (rev 20982)
@@ -1272,7 +1272,8 @@
         && args[1].tok != T.off ? SV.sValue(args[1]) : "");
     boolean isSequence = !isList && sFind.equalsIgnoreCase("SEQUENCE");
     boolean isSeq = !isList && sFind.equalsIgnoreCase("SEQ");
-    boolean isSmiles = !isList && sFind.equalsIgnoreCase("SMILES");
+    boolean isOpenSmiles = !isList && sFind.equalsIgnoreCase("OPENSMILES");
+    boolean isSmiles = isOpenSmiles || !isList && 
sFind.equalsIgnoreCase("SMILES");
     boolean isSMARTS = !isList && sFind.equalsIgnoreCase("SMARTS");
     boolean isChemical = !isList && sFind.equalsIgnoreCase("CHEMICAL");
     boolean isMF = !isList && sFind.equalsIgnoreCase("MF");
@@ -1365,7 +1366,8 @@
                     | JC.SMILES_RETURN_FIRST);
             ret = (map.length > 0 ? vwr.ms.getDihedralMap(map[0]) : new 
int[0]);
           } else {
-            int smilesFlags = (isSmiles ? JC.SMILES_TYPE_SMILES
+            int smilesFlags = (isOpenSmiles ? JC.SMILES_TYPE_OPENSMILES 
+                : isSmiles ? JC.SMILES_TYPE_SMILES
                 : JC.SMILES_TYPE_SMARTS)
                 | (isON && sFind.length() == 0 ? JC.SMILES_BIO_COV_CROSSLINK
                     | JC.SMILES_BIO_COMMENT : 0);

Modified: branches/v14_4/Jmol/src/org/jmol/smiles/SmilesAtom.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/smiles/SmilesAtom.java     2016-03-06 
18:23:15 UTC (rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/smiles/SmilesAtom.java     2016-03-07 
04:22:42 UTC (rev 20982)
@@ -180,6 +180,7 @@
   private Node matchingNode;
   public boolean hasSubpattern;
   public int mapIndex = -1; // in  CCC we have atoms 0, 1, and 2
+  public float osClass = Float.NaN; // OpenSMILES atom class is an integer
 
   public SmilesAtom setAll(int iComponent, int ptAtom, int atomicNumber,
       int charge) {
@@ -716,18 +717,21 @@
   }
 
   /**
+   *
+   * called from SmilesGenerator
    * 
    * @param atomicNumber
    * @param isotopeNumber
    * @param valence set -1 to force brackets
    * @param charge
+   * @param osclass OpenSMILES value
    * @param nH
    * @param isAromatic
    * @param stereo
    * @return label
    */
   static String getAtomLabel(int atomicNumber, int isotopeNumber, int valence,
-                             int charge, int nH, boolean isAromatic,
+                             int charge, float osclass, int nH, boolean 
isAromatic,
                              String stereo) {
     String sym = Elements.elementSymbolFromNumber(atomicNumber);
     if (isAromatic) {
@@ -735,15 +739,20 @@
       if (atomicNumber != 6)
         valence = Integer.MAX_VALUE; // force [n]
     }
-    int count = (stereo == null || stereo.length() > 0 || isotopeNumber != 0 
|| charge != 0 ? -1
+    int count = (isotopeNumber != 0 
+        || stereo != null && stereo.length() > 0 
+        || charge != 0 || osclass != 0 ? -1
         : getDefaultCount(atomicNumber, false));
     return (count == valence ? sym : 
+      // rearranged 14.5.3_2016.03.06 to 
       "["
-        + (isotopeNumber <= 0 ? "" : "" + isotopeNumber) + sym
+        + (isotopeNumber <= 0 ? "" : "" + isotopeNumber) 
+        + sym
+        + (stereo == null ? "" : stereo)
+        + (nH > 1 ? "H" + nH : nH == 1 ? "H" : "")
         + (charge < 0 && charge != Integer.MIN_VALUE ? "" + charge 
             : charge > 0 ? "+" + charge : "") 
-        + (stereo == null ? "" : stereo)
-        + (nH > 1 ? "H" + nH : nH == 1 ? "H" : "") 
+        + (osclass == 0 ? "" : ":" + (int) osclass)
         + "]");
   }
 
@@ -807,4 +816,11 @@
         + "]";
   }
 
+  @Override
+  public float getFloatProperty(String property) {
+    if (property == "property_osclass") // == is OK here.  
+      return osClass;
+    return Float.NaN;
+  }
+
 }

Modified: branches/v14_4/Jmol/src/org/jmol/smiles/SmilesGenerator.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/smiles/SmilesGenerator.java        
2016-03-06 18:23:15 UTC (rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/smiles/SmilesGenerator.java        
2016-03-07 04:22:42 UTC (rev 20982)
@@ -86,6 +86,7 @@
   private boolean addAtomComment;
   private boolean noBioComment;
   private boolean noStereo;
+  private boolean openSMILES;
   public P3 stereoReference;
   private SmilesStereo smilesStereo;
   private boolean isPolyhedral;
@@ -99,13 +100,15 @@
       return "";
     this.atoms = atoms;
     this.ac = ac;
-    addAtomComment = ((flags & JC.SMILES_ATOM_COMMENT) == 
JC.SMILES_ATOM_COMMENT);
     bsSelected = BSUtil.copy(bsSelected);    
-    
+
+    // note -- some of these are 2-bit flags, so we need to use (flags & X) == 
X 
     if ((flags & JC.SMILES_BIO) == JC.SMILES_BIO)
       return getBioSmiles(bsSelected, comment, flags);
     
     this.bsSelected = bsSelected;
+    openSMILES = ((flags & JC.SMILES_TYPE_OPENSMILES) == 
JC.SMILES_TYPE_OPENSMILES);
+    addAtomComment = ((flags & JC.SMILES_ATOM_COMMENT) == 
JC.SMILES_ATOM_COMMENT);
     explicitH = ((flags & JC.SMILES_EXPLICIT_H) == JC.SMILES_EXPLICIT_H);
     topologyOnly = ((flags & JC.SMILES_TOPOLOGY) == JC.SMILES_TOPOLOGY);
     getAromatic = !((flags & JC.SMILES_NOAROMATIC) == JC.SMILES_NOAROMATIC);
@@ -704,6 +707,7 @@
     int charge = atom.getFormalCharge();
     int isotope = atom.getIsotopeNumber();
     int valence = atom.getValence();
+    float osclass = (openSMILES ? atom.getFloatProperty("property_osclass") : 
0); 
     String atomName = atom.getAtomName();
     String groupType = (atom instanceof BNode ? 
((BNode)atom).getBioStructureTypeName() : "");
     // for bioSMARTS we provide the connecting atom if 
@@ -717,7 +721,7 @@
       addBracketedBioName(sb, atom, "." + atomName, false);
     else
       sb.append(SmilesAtom
-          .getAtomLabel(atomicNumber, isotope, (forceBrackets ? -1 : valence), 
charge, nH, isAromatic,
+          .getAtomLabel(atomicNumber, isotope, (forceBrackets ? -1 : valence), 
charge, osclass, nH, isAromatic,
               atat != null ? atat : noStereo ? null : checkStereoPairs(atom, 
atomIndex, stereo, stereoFlag)));
     sb.appendSB(sMore);
 

Modified: branches/v14_4/Jmol/src/org/jmol/smiles/SmilesMatcher.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/smiles/SmilesMatcher.java  2016-03-06 
18:23:15 UTC (rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/smiles/SmilesMatcher.java  2016-03-07 
04:22:42 UTC (rev 20982)
@@ -285,16 +285,17 @@
   }
 
   /**
-   * called by ForceFieldMMFF.setAtomTypes
+   * called by ForceFieldMMFF.setAtomTypes only
    * 
    */
   @Override
-  public void getSubstructureSets(String[] smarts, Node[] atoms, int ac,
-                                  int flags, BS bsSelected, Lst<BS> ret,
+  public void getMMFF94AtomTypes(String[] smarts, Node[] atoms, int ac,
+                                  BS bsSelected, Lst<BS> ret,
                                   Lst<BS>[] vRings) throws Exception {
     InvalidSmilesException.clear();
     SmilesParser sp = new SmilesParser(true);
     SmilesSearch search = null;
+    int flags = (SmilesSearch.FLAG_AROMATIC_STRICT | 
SmilesSearch.FLAG_AROMATIC_DOUBLE);
     search = sp.parse("");
     search.firstMatchOnly = false;
     search.matchAllAtoms = false;

Modified: branches/v14_4/Jmol/src/org/jmol/smiles/SmilesParser.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/smiles/SmilesParser.java   2016-03-06 
18:23:15 UTC (rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/smiles/SmilesParser.java   2016-03-07 
04:22:42 UTC (rev 20982)
@@ -25,16 +25,16 @@
 package org.jmol.smiles;
 
 
+import java.util.Hashtable;
+import java.util.Map;
+
 import javajs.util.Lst;
 import javajs.util.PT;
 import javajs.util.SB;
 
-import java.util.Hashtable;
-import java.util.Map;
-
 import org.jmol.util.Elements;
-import org.jmol.util.Edge;
 import org.jmol.util.Logger;
+import org.jmol.viewer.JC;
 
 /**
  * Parses a SMILES String to create a <code>SmilesMolecule</code>.
@@ -121,6 +121,7 @@
   private int braceCount;
   private int branchLevel;
   private boolean ignoreStereochemistry;
+  private boolean openSMILES;
 
   public static SmilesSearch getMolecule(String pattern, boolean isSmarts)
       throws InvalidSmilesException {
@@ -160,23 +161,27 @@
       String strFlags = getSubPattern(pattern, 0, '/').toUpperCase();
       pattern = pattern.substring(strFlags.length() + 2);
       if (strFlags.indexOf("NONCANONICAL") >= 0)
-        flags |= Edge.FLAG_AROMATIC_NONCANONICAL;
+        flags |= SmilesSearch.FLAG_AROMATIC_NONCANONICAL;
+      if (strFlags.indexOf("OPENSMILES") >= 0) {
+        flags |= JC.SMILES_TYPE_OPENSMILES;
+        openSMILES = true;
+      }
       if (strFlags.indexOf("NOAROMATIC") >= 0)
-        flags |= Edge.FLAG_NO_AROMATIC;
+        flags |= SmilesSearch.FLAG_NO_AROMATIC;
       if (strFlags.indexOf("AROMATICSTRICT") >= 0)
-        flags |= Edge.FLAG_AROMATIC_STRICT;
+        flags |= SmilesSearch.FLAG_AROMATIC_STRICT;
       if (strFlags.indexOf("AROMATICDEFINED") >= 0)
-        flags |= Edge.FLAG_AROMATIC_DEFINED;
+        flags |= SmilesSearch.FLAG_AROMATIC_DEFINED;
       if (strFlags.indexOf("AROMATICDOUBLE") >= 0)
-        flags |= Edge.FLAG_AROMATIC_DOUBLE;
+        flags |= SmilesSearch.FLAG_AROMATIC_DOUBLE;
       if (strFlags.indexOf("NOSTEREO") >= 0) {
-        flags |= Edge.FLAG_IGNORE_STEREOCHEMISTRY;
+        flags |= SmilesSearch.FLAG_IGNORE_STEREOCHEMISTRY;
         ignoreStereochemistry = true;
       } else if (strFlags.indexOf("INVERTSTEREO") >= 0) {
-        if ((flags & Edge.FLAG_INVERT_STEREOCHEMISTRY) != 0)
-          flags &= ~Edge.FLAG_INVERT_STEREOCHEMISTRY;
+        if ((flags & SmilesSearch.FLAG_INVERT_STEREOCHEMISTRY) != 0)
+          flags &= ~SmilesSearch.FLAG_INVERT_STEREOCHEMISTRY;
         else
-          flags |= Edge.FLAG_INVERT_STEREOCHEMISTRY;
+          flags |= SmilesSearch.FLAG_INVERT_STEREOCHEMISTRY;
       }
     }
     if (pattern.indexOf("$") >= 0)
@@ -920,6 +925,11 @@
             index = SmilesStereo.checkChirality(pattern, index,
                 molecule.patternAtoms[newAtom.index]);
             break;
+          case ':': //openSmiles application-dependent atom class
+            index = getDigits(pattern, index + 1, ret);
+            if (openSMILES)
+              newAtom.osClass = ret[0];
+            break;
           default:
             // SMARTS has ambiguities in terms of chaining without &.
             // H alone is "one H atom"

Modified: branches/v14_4/Jmol/src/org/jmol/smiles/SmilesSearch.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/smiles/SmilesSearch.java   2016-03-06 
18:23:15 UTC (rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/smiles/SmilesSearch.java   2016-03-07 
04:22:42 UTC (rev 20982)
@@ -40,6 +40,7 @@
 import org.jmol.util.JmolMolecule;
 import org.jmol.util.Logger;
 import org.jmol.util.Node;
+import org.jmol.viewer.JC;
 
 /**
  *  -- was SmilesMolecule, 
@@ -58,7 +59,16 @@
     sb.append("\nmolecular formula: " + getMolecularFormula(true, null, 
false)); 
     return sb.toString();    
   }
+
   
+  final static int FLAG_AROMATIC_NONCANONICAL    = 0x400;
+  final static int FLAG_AROMATIC_DOUBLE          = 0x200;
+  final static int FLAG_AROMATIC_DEFINED         = 0x100;
+  final static int FLAG_AROMATIC_STRICT          = 0x080;
+  final static int FLAG_INVERT_STEREOCHEMISTRY   = 0x040;
+  final static int FLAG_IGNORE_STEREOCHEMISTRY   = 0x020;
+  final static int FLAG_NO_AROMATIC              = 0x010;
+
   private final static int INITIAL_ATOMS = 16;
   SmilesAtom[] patternAtoms = new SmilesAtom[INITIAL_ATOMS];
 
@@ -131,6 +141,7 @@
   private boolean noAromatic;
   private boolean aromaticDouble;
   private boolean noncanonical;
+  private boolean openSMILES;
     
 
   void setAtomArray() {
@@ -186,7 +197,7 @@
       needAromatic = false;
     if (needAromatic)
       needRingData = true;
-    boolean noAromatic = ((flags & Edge.FLAG_NO_AROMATIC) != 0);
+    boolean noAromatic = ((flags & FLAG_NO_AROMATIC) != 0);
     needAromatic &= (bsA == null) & !noAromatic;
     // when using "xxx".find("search","....")
     // or $(...), the aromatic set has already been determined
@@ -203,8 +214,8 @@
   @SuppressWarnings("unchecked")
   void getRingData(boolean needRingData, int flags, Lst<BS>[] vRings)
       throws InvalidSmilesException {
-    boolean aromaticStrict = ((flags & Edge.FLAG_AROMATIC_STRICT) != 0);
-    boolean aromaticDefined = ((flags & Edge.FLAG_AROMATIC_DEFINED) != 0);
+    boolean aromaticStrict = ((flags & FLAG_AROMATIC_STRICT) != 0);
+    boolean aromaticDefined = ((flags & FLAG_AROMATIC_DEFINED) != 0);
     if (aromaticStrict && vRings == null)
       vRings = AU.createArrayOfArrayList(4);
     if (aromaticDefined && needAromatic) {
@@ -406,11 +417,13 @@
      *    
      */
 
-    ignoreStereochemistry = ((flags & Edge.FLAG_IGNORE_STEREOCHEMISTRY) != 0);
-    invertStereochemistry = ((flags & Edge.FLAG_INVERT_STEREOCHEMISTRY) != 0);
-    noAromatic = ((flags & Edge.FLAG_NO_AROMATIC) != 0);
-    noncanonical = ((flags & Edge.FLAG_AROMATIC_NONCANONICAL) != 0);
-      aromaticDouble = ((flags & Edge.FLAG_AROMATIC_DOUBLE) != 0);
+    // flags are passed on from SmilesParser
+    aromaticDouble = ((flags & FLAG_AROMATIC_DOUBLE) != 0);
+    ignoreStereochemistry = ((flags & FLAG_IGNORE_STEREOCHEMISTRY) != 0);
+    invertStereochemistry = ((flags & FLAG_INVERT_STEREOCHEMISTRY) != 0);
+    noAromatic = ((flags & FLAG_NO_AROMATIC) != 0);
+    noncanonical = ((flags & FLAG_AROMATIC_NONCANONICAL) != 0);
+    openSMILES = ((flags & JC.SMILES_TYPE_OPENSMILES) == 
JC.SMILES_TYPE_OPENSMILES);
     
     if (Logger.debugging && !isSilent)
       Logger.debug("SmilesSearch processing " + pattern);
@@ -928,8 +941,8 @@
         if (!noAromatic && !patternAtom.aromaticAmbiguous
             && isAromatic != bsAromatic.get(iAtom)) {
           if (!noncanonical
-              || patternAtom.getExplicitHydrogenCount() != 
-                        atom.getCovalentHydrogenCount())
+              || patternAtom.getExplicitHydrogenCount() != atom
+                  .getCovalentHydrogenCount())
             break;
         }
 
@@ -985,33 +998,41 @@
                 + atom.getImplicitHydrogenCount())
           break;
 
-        // r <n> ring of a given size
-        if (ringData != null && patternAtom.ringSize >= -1) {
-          if (patternAtom.ringSize <= 0) {
-            if ((ringCounts[iAtom] == 0) != (patternAtom.ringSize == 0))
-              break;
-          } else {
-            BS rd = ringData[patternAtom.ringSize == 500 ? 5
-                : patternAtom.ringSize == 600 ? 6 : patternAtom.ringSize];
-            if (rd == null || !rd.get(iAtom))
-              break;
-            if (!noAromatic)
-              if (patternAtom.ringSize == 500) {
-                if (!bsAromatic5.get(iAtom))
-                  break;
-              } else if (patternAtom.ringSize == 600) {
-                if (!bsAromatic6.get(iAtom))
-                  break;
-              }
+        if (openSMILES) {
+          if (!Float.isNaN(patternAtom.osClass)
+              && patternAtom.osClass != 
atom.getFloatProperty("property_osclass"))
+            break;
+        }
+
+        if (ringData != null) {
+          // r <n> ring of a given size
+          if (patternAtom.ringSize >= -1) {
+            if (patternAtom.ringSize <= 0) {
+              if ((ringCounts[iAtom] == 0) != (patternAtom.ringSize == 0))
+                break;
+            } else {
+              BS rd = ringData[patternAtom.ringSize == 500 ? 5
+                  : patternAtom.ringSize == 600 ? 6 : patternAtom.ringSize];
+              if (rd == null || !rd.get(iAtom))
+                break;
+              if (!noAromatic)
+                if (patternAtom.ringSize == 500) {
+                  if (!bsAromatic5.get(iAtom))
+                    break;
+                } else if (patternAtom.ringSize == 600) {
+                  if (!bsAromatic6.get(iAtom))
+                    break;
+                }
+            }
+            // R <n> a certain number of rings
+            if (patternAtom.ringMembership >= -1) {
+              //  R --> -1 implies "!R0"
+              if (patternAtom.ringMembership == -1 ? ringCounts[iAtom] == 0
+                  : ringCounts[iAtom] != patternAtom.ringMembership)
+                break;
+            }
           }
         }
-        // R <n> a certain number of rings
-        if (ringData != null && patternAtom.ringMembership >= -1) {
-          //  R --> -1 implies "!R0"
-          if (patternAtom.ringMembership == -1 ? ringCounts[iAtom] == 0
-              : ringCounts[iAtom] != patternAtom.ringMembership)
-            break;
-        }
         // x <n>
         if (patternAtom.ringConnectivity >= 0) {
           // default > 0

Modified: branches/v14_4/Jmol/src/org/jmol/util/Edge.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/util/Edge.java     2016-03-06 18:23:15 UTC 
(rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/util/Edge.java     2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -104,13 +104,6 @@
 
   public int index = -1;
   public int order;
-  final public static int FLAG_AROMATIC_NONCANONICAL = 64;
-  final public static int FLAG_AROMATIC_DOUBLE = 32;
-  final public static int FLAG_AROMATIC_DEFINED = 16;
-  final public static int FLAG_AROMATIC_STRICT = 8;
-  final public static int FLAG_INVERT_STEREOCHEMISTRY = 4;
-  final public static int FLAG_IGNORE_STEREOCHEMISTRY = 2;
-  public final static int FLAG_NO_AROMATIC = 1;
 
   abstract public int getAtomIndex1();
 

Modified: branches/v14_4/Jmol/src/org/jmol/util/Node.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/util/Node.java     2016-03-06 18:23:15 UTC 
(rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/util/Node.java     2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -43,7 +43,14 @@
   public int getIsotopeNumber();
   public int getValence();
   public void set(float x, float y, float z);
+  
+  /**
+   * @param property  "property_xxxx"
+   * @return value or Float.NaN
+   */
 
+  public float getFloatProperty(String property);
+
   // abstracts out the essential pieces for SMARTS processing
   
   public BS findAtomsLike(String substring);

Modified: branches/v14_4/Jmol/src/org/jmol/viewer/JC.java
===================================================================
--- branches/v14_4/Jmol/src/org/jmol/viewer/JC.java     2016-03-06 18:23:15 UTC 
(rev 20981)
+++ branches/v14_4/Jmol/src/org/jmol/viewer/JC.java     2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -1067,6 +1067,7 @@
   
   public static final int SMILES_TYPE_SMILES       = 0x1;
   public static final int SMILES_TYPE_SMARTS       = 0x2;
+  public static final int SMILES_TYPE_OPENSMILES   = 0x5; 
   
   public static final int SMILES_MATCH_ALL         = 0x10;
   public static final int SMILES_MATCH_ONE         = 0x20;

Modified: trunk/Jmol/src/org/jmol/api/SmilesMatcherInterface.java
===================================================================
--- trunk/Jmol/src/org/jmol/api/SmilesMatcherInterface.java     2016-03-06 
18:23:15 UTC (rev 20981)
+++ trunk/Jmol/src/org/jmol/api/SmilesMatcherInterface.java     2016-03-07 
04:22:42 UTC (rev 20982)
@@ -45,9 +45,8 @@
                                              int ac, BS bsSelected,
                                              int flags) throws Exception;
 
-  public abstract void getSubstructureSets(String[] smarts, Node[] atoms, int 
ac,
-                                           int flags,
-                         BS bsSelected, Lst<BS> bitSets, Lst<BS>[] vRings) 
throws Exception;
+  public abstract void getMMFF94AtomTypes(String[] smarts, Node[] atoms, int 
ac,
+                                           BS bsSelected, Lst<BS> bitSets, 
Lst<BS>[] vRings) throws Exception;
 
   public abstract String getSmiles(Node[] atoms, int ac, BS bsSelected,
                                       String bioComment, int flags) throws 
Exception;

Modified: trunk/Jmol/src/org/jmol/minimize/forcefield/ForceFieldMMFF.java
===================================================================
--- trunk/Jmol/src/org/jmol/minimize/forcefield/ForceFieldMMFF.java     
2016-03-06 18:23:15 UTC (rev 20981)
+++ trunk/Jmol/src/org/jmol/minimize/forcefield/ForceFieldMMFF.java     
2016-03-07 04:22:42 UTC (rev 20982)
@@ -25,15 +25,13 @@
 package org.jmol.minimize.forcefield;
 
 import java.io.BufferedReader;
+import java.util.Hashtable;
+import java.util.Map;
 
 import javajs.util.AU;
 import javajs.util.Lst;
 import javajs.util.PT;
 
-import java.util.Hashtable;
-
-import java.util.Map;
-
 import org.jmol.api.SmilesMatcherInterface;
 import org.jmol.java.BS;
 import org.jmol.minimize.MinAngle;
@@ -47,7 +45,6 @@
 import org.jmol.util.BSUtil;
 import org.jmol.util.Elements;
 import org.jmol.util.Escape;
-import org.jmol.util.Edge;
 import org.jmol.util.Logger;
 import org.jmol.viewer.JmolAsyncException;
 
@@ -870,8 +867,7 @@
     // identifies that atom's MMFF94 type.
 
     try {
-      smartsMatcher.getSubstructureSets(smarts, atoms, atoms.length,
-          Edge.FLAG_AROMATIC_STRICT | Edge.FLAG_AROMATIC_DOUBLE,
+      smartsMatcher.getMMFF94AtomTypes(smarts, atoms, atoms.length,
           bsConnected, bitSets, vRings);
     } catch (Exception e) {
       Logger.error(e.toString());

Modified: trunk/Jmol/src/org/jmol/modelset/Atom.java
===================================================================
--- trunk/Jmol/src/org/jmol/modelset/Atom.java  2016-03-06 18:23:15 UTC (rev 
20981)
+++ trunk/Jmol/src/org/jmol/modelset/Atom.java  2016-03-07 04:22:42 UTC (rev 
20982)
@@ -33,6 +33,7 @@
 import javajs.util.T3;
 import javajs.util.V3;
 
+import org.jmol.api.JmolDataManager;
 import org.jmol.api.JmolModulationSet;
 import org.jmol.api.SymmetryInterface;
 import org.jmol.atomdata.RadiusData;
@@ -1420,4 +1421,18 @@
     return (m.isBioModel ? ((BioModel) m).getUnitID(this, flags) : "");
   }
 
+  @Override
+  public float getFloatProperty(String property) {
+    Object data = group.chain.model.ms.vwr.getDataObj(property, null,
+        JmolDataManager.DATA_TYPE_AF);
+    float f = 0;
+    if (data != null) {
+      try {
+        f = ((float[]) data)[i];
+      } catch (Exception e) {
+      }
+    }
+    return f;
+  }
+
 }

Modified: trunk/Jmol/src/org/jmol/scriptext/MathExt.java
===================================================================
--- trunk/Jmol/src/org/jmol/scriptext/MathExt.java      2016-03-06 18:23:15 UTC 
(rev 20981)
+++ trunk/Jmol/src/org/jmol/scriptext/MathExt.java      2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -1272,7 +1272,8 @@
         && args[1].tok != T.off ? SV.sValue(args[1]) : "");
     boolean isSequence = !isList && sFind.equalsIgnoreCase("SEQUENCE");
     boolean isSeq = !isList && sFind.equalsIgnoreCase("SEQ");
-    boolean isSmiles = !isList && sFind.equalsIgnoreCase("SMILES");
+    boolean isOpenSmiles = !isList && sFind.equalsIgnoreCase("OPENSMILES");
+    boolean isSmiles = isOpenSmiles || !isList && 
sFind.equalsIgnoreCase("SMILES");
     boolean isSMARTS = !isList && sFind.equalsIgnoreCase("SMARTS");
     boolean isChemical = !isList && sFind.equalsIgnoreCase("CHEMICAL");
     boolean isMF = !isList && sFind.equalsIgnoreCase("MF");
@@ -1365,7 +1366,8 @@
                     | JC.SMILES_RETURN_FIRST);
             ret = (map.length > 0 ? vwr.ms.getDihedralMap(map[0]) : new 
int[0]);
           } else {
-            int smilesFlags = (isSmiles ? JC.SMILES_TYPE_SMILES
+            int smilesFlags = (isOpenSmiles ? JC.SMILES_TYPE_OPENSMILES 
+                : isSmiles ? JC.SMILES_TYPE_SMILES
                 : JC.SMILES_TYPE_SMARTS)
                 | (isON && sFind.length() == 0 ? JC.SMILES_BIO_COV_CROSSLINK
                     | JC.SMILES_BIO_COMMENT : 0);

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java      2016-03-06 18:23:15 UTC 
(rev 20981)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesAtom.java      2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -180,6 +180,7 @@
   private Node matchingNode;
   public boolean hasSubpattern;
   public int mapIndex = -1; // in  CCC we have atoms 0, 1, and 2
+  public float osClass = Float.NaN; // OpenSMILES atom class is an integer
 
   public SmilesAtom setAll(int iComponent, int ptAtom, int atomicNumber,
       int charge) {
@@ -716,18 +717,21 @@
   }
 
   /**
+   *
+   * called from SmilesGenerator
    * 
    * @param atomicNumber
    * @param isotopeNumber
    * @param valence set -1 to force brackets
    * @param charge
+   * @param osclass OpenSMILES value
    * @param nH
    * @param isAromatic
    * @param stereo
    * @return label
    */
   static String getAtomLabel(int atomicNumber, int isotopeNumber, int valence,
-                             int charge, int nH, boolean isAromatic,
+                             int charge, float osclass, int nH, boolean 
isAromatic,
                              String stereo) {
     String sym = Elements.elementSymbolFromNumber(atomicNumber);
     if (isAromatic) {
@@ -735,15 +739,20 @@
       if (atomicNumber != 6)
         valence = Integer.MAX_VALUE; // force [n]
     }
-    int count = (stereo == null || stereo.length() > 0 || isotopeNumber != 0 
|| charge != 0 ? -1
+    int count = (isotopeNumber != 0 
+        || stereo != null && stereo.length() > 0 
+        || charge != 0 || osclass != 0 ? -1
         : getDefaultCount(atomicNumber, false));
     return (count == valence ? sym : 
+      // rearranged 14.5.3_2016.03.06 to 
       "["
-        + (isotopeNumber <= 0 ? "" : "" + isotopeNumber) + sym
+        + (isotopeNumber <= 0 ? "" : "" + isotopeNumber) 
+        + sym
+        + (stereo == null ? "" : stereo)
+        + (nH > 1 ? "H" + nH : nH == 1 ? "H" : "")
         + (charge < 0 && charge != Integer.MIN_VALUE ? "" + charge 
             : charge > 0 ? "+" + charge : "") 
-        + (stereo == null ? "" : stereo)
-        + (nH > 1 ? "H" + nH : nH == 1 ? "H" : "") 
+        + (osclass == 0 ? "" : ":" + (int) osclass)
         + "]");
   }
 
@@ -807,4 +816,11 @@
         + "]";
   }
 
+  @Override
+  public float getFloatProperty(String property) {
+    if (property == "property_osclass") // == is OK here.  
+      return osClass;
+    return Float.NaN;
+  }
+
 }

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesGenerator.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesGenerator.java 2016-03-06 18:23:15 UTC 
(rev 20981)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesGenerator.java 2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -86,6 +86,7 @@
   private boolean addAtomComment;
   private boolean noBioComment;
   private boolean noStereo;
+  private boolean openSMILES;
   public P3 stereoReference;
   private SmilesStereo smilesStereo;
   private boolean isPolyhedral;
@@ -99,13 +100,15 @@
       return "";
     this.atoms = atoms;
     this.ac = ac;
-    addAtomComment = ((flags & JC.SMILES_ATOM_COMMENT) == 
JC.SMILES_ATOM_COMMENT);
     bsSelected = BSUtil.copy(bsSelected);    
-    
+
+    // note -- some of these are 2-bit flags, so we need to use (flags & X) == 
X 
     if ((flags & JC.SMILES_BIO) == JC.SMILES_BIO)
       return getBioSmiles(bsSelected, comment, flags);
     
     this.bsSelected = bsSelected;
+    openSMILES = ((flags & JC.SMILES_TYPE_OPENSMILES) == 
JC.SMILES_TYPE_OPENSMILES);
+    addAtomComment = ((flags & JC.SMILES_ATOM_COMMENT) == 
JC.SMILES_ATOM_COMMENT);
     explicitH = ((flags & JC.SMILES_EXPLICIT_H) == JC.SMILES_EXPLICIT_H);
     topologyOnly = ((flags & JC.SMILES_TOPOLOGY) == JC.SMILES_TOPOLOGY);
     getAromatic = !((flags & JC.SMILES_NOAROMATIC) == JC.SMILES_NOAROMATIC);
@@ -704,6 +707,7 @@
     int charge = atom.getFormalCharge();
     int isotope = atom.getIsotopeNumber();
     int valence = atom.getValence();
+    float osclass = (openSMILES ? atom.getFloatProperty("property_osclass") : 
0);
     String atomName = atom.getAtomName();
     String groupType = (atom instanceof BNode ? 
((BNode)atom).getBioStructureTypeName() : "");
     // for bioSMARTS we provide the connecting atom if 
@@ -717,7 +721,7 @@
       addBracketedBioName(sb, atom, "." + atomName, false);
     else
       sb.append(SmilesAtom
-          .getAtomLabel(atomicNumber, isotope, (forceBrackets ? -1 : valence), 
charge, nH, isAromatic,
+          .getAtomLabel(atomicNumber, isotope, (forceBrackets ? -1 : valence), 
charge, osclass, nH, isAromatic,
               atat != null ? atat : noStereo ? null : checkStereoPairs(atom, 
atomIndex, stereo, stereoFlag)));
     sb.appendSB(sMore);
 

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java   2016-03-06 18:23:15 UTC 
(rev 20981)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java   2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -285,16 +285,17 @@
   }
 
   /**
-   * called by ForceFieldMMFF.setAtomTypes
+   * called by ForceFieldMMFF.setAtomTypes only
    * 
    */
   @Override
-  public void getSubstructureSets(String[] smarts, Node[] atoms, int ac,
-                                  int flags, BS bsSelected, Lst<BS> ret,
+  public void getMMFF94AtomTypes(String[] smarts, Node[] atoms, int ac,
+                                  BS bsSelected, Lst<BS> ret,
                                   Lst<BS>[] vRings) throws Exception {
     InvalidSmilesException.clear();
     SmilesParser sp = new SmilesParser(true);
     SmilesSearch search = null;
+    int flags = (SmilesSearch.FLAG_AROMATIC_STRICT | 
SmilesSearch.FLAG_AROMATIC_DOUBLE);
     search = sp.parse("");
     search.firstMatchOnly = false;
     search.matchAllAtoms = false;

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesParser.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesParser.java    2016-03-06 18:23:15 UTC 
(rev 20981)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesParser.java    2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -25,16 +25,16 @@
 package org.jmol.smiles;
 
 
+import java.util.Hashtable;
+import java.util.Map;
+
 import javajs.util.Lst;
 import javajs.util.PT;
 import javajs.util.SB;
 
-import java.util.Hashtable;
-import java.util.Map;
-
 import org.jmol.util.Elements;
-import org.jmol.util.Edge;
 import org.jmol.util.Logger;
+import org.jmol.viewer.JC;
 
 /**
  * Parses a SMILES String to create a <code>SmilesMolecule</code>.
@@ -121,6 +121,7 @@
   private int braceCount;
   private int branchLevel;
   private boolean ignoreStereochemistry;
+  private boolean openSMILES;
 
   public static SmilesSearch getMolecule(String pattern, boolean isSmarts)
       throws InvalidSmilesException {
@@ -160,23 +161,27 @@
       String strFlags = getSubPattern(pattern, 0, '/').toUpperCase();
       pattern = pattern.substring(strFlags.length() + 2);
       if (strFlags.indexOf("NONCANONICAL") >= 0)
-        flags |= Edge.FLAG_AROMATIC_NONCANONICAL;
+        flags |= SmilesSearch.FLAG_AROMATIC_NONCANONICAL;
+      if (strFlags.indexOf("OPENSMILES") >= 0) {
+        flags |= JC.SMILES_TYPE_OPENSMILES;
+        openSMILES = true;
+      }
       if (strFlags.indexOf("NOAROMATIC") >= 0)
-        flags |= Edge.FLAG_NO_AROMATIC;
+        flags |= SmilesSearch.FLAG_NO_AROMATIC;
       if (strFlags.indexOf("AROMATICSTRICT") >= 0)
-        flags |= Edge.FLAG_AROMATIC_STRICT;
+        flags |= SmilesSearch.FLAG_AROMATIC_STRICT;
       if (strFlags.indexOf("AROMATICDEFINED") >= 0)
-        flags |= Edge.FLAG_AROMATIC_DEFINED;
+        flags |= SmilesSearch.FLAG_AROMATIC_DEFINED;
       if (strFlags.indexOf("AROMATICDOUBLE") >= 0)
-        flags |= Edge.FLAG_AROMATIC_DOUBLE;
+        flags |= SmilesSearch.FLAG_AROMATIC_DOUBLE;
       if (strFlags.indexOf("NOSTEREO") >= 0) {
-        flags |= Edge.FLAG_IGNORE_STEREOCHEMISTRY;
+        flags |= SmilesSearch.FLAG_IGNORE_STEREOCHEMISTRY;
         ignoreStereochemistry = true;
       } else if (strFlags.indexOf("INVERTSTEREO") >= 0) {
-        if ((flags & Edge.FLAG_INVERT_STEREOCHEMISTRY) != 0)
-          flags &= ~Edge.FLAG_INVERT_STEREOCHEMISTRY;
+        if ((flags & SmilesSearch.FLAG_INVERT_STEREOCHEMISTRY) != 0)
+          flags &= ~SmilesSearch.FLAG_INVERT_STEREOCHEMISTRY;
         else
-          flags |= Edge.FLAG_INVERT_STEREOCHEMISTRY;
+          flags |= SmilesSearch.FLAG_INVERT_STEREOCHEMISTRY;
       }
     }
     if (pattern.indexOf("$") >= 0)
@@ -920,6 +925,11 @@
             index = SmilesStereo.checkChirality(pattern, index,
                 molecule.patternAtoms[newAtom.index]);
             break;
+          case ':': //openSmiles application-dependent atom class
+            index = getDigits(pattern, index + 1, ret);
+            if (openSMILES)
+              newAtom.osClass = ret[0];
+            break;
           default:
             // SMARTS has ambiguities in terms of chaining without &.
             // H alone is "one H atom"

Modified: trunk/Jmol/src/org/jmol/smiles/SmilesSearch.java
===================================================================
--- trunk/Jmol/src/org/jmol/smiles/SmilesSearch.java    2016-03-06 18:23:15 UTC 
(rev 20981)
+++ trunk/Jmol/src/org/jmol/smiles/SmilesSearch.java    2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -40,6 +40,7 @@
 import org.jmol.util.JmolMolecule;
 import org.jmol.util.Logger;
 import org.jmol.util.Node;
+import org.jmol.viewer.JC;
 
 /**
  *  -- was SmilesMolecule, 
@@ -58,7 +59,16 @@
     sb.append("\nmolecular formula: " + getMolecularFormula(true, null, 
false)); 
     return sb.toString();    
   }
+
   
+  final static int FLAG_AROMATIC_NONCANONICAL    = 0x400;
+  final static int FLAG_AROMATIC_DOUBLE          = 0x200;
+  final static int FLAG_AROMATIC_DEFINED         = 0x100;
+  final static int FLAG_AROMATIC_STRICT          = 0x080;
+  final static int FLAG_INVERT_STEREOCHEMISTRY   = 0x040;
+  final static int FLAG_IGNORE_STEREOCHEMISTRY   = 0x020;
+  final static int FLAG_NO_AROMATIC              = 0x010;
+
   private final static int INITIAL_ATOMS = 16;
   SmilesAtom[] patternAtoms = new SmilesAtom[INITIAL_ATOMS];
 
@@ -131,6 +141,7 @@
   private boolean noAromatic;
   private boolean aromaticDouble;
   private boolean noncanonical;
+  private boolean openSMILES;
     
 
   void setAtomArray() {
@@ -186,7 +197,7 @@
       needAromatic = false;
     if (needAromatic)
       needRingData = true;
-    boolean noAromatic = ((flags & Edge.FLAG_NO_AROMATIC) != 0);
+    boolean noAromatic = ((flags & FLAG_NO_AROMATIC) != 0);
     needAromatic &= (bsA == null) & !noAromatic;
     // when using "xxx".find("search","....")
     // or $(...), the aromatic set has already been determined
@@ -203,8 +214,8 @@
   @SuppressWarnings("unchecked")
   void getRingData(boolean needRingData, int flags, Lst<BS>[] vRings)
       throws InvalidSmilesException {
-    boolean aromaticStrict = ((flags & Edge.FLAG_AROMATIC_STRICT) != 0);
-    boolean aromaticDefined = ((flags & Edge.FLAG_AROMATIC_DEFINED) != 0);
+    boolean aromaticStrict = ((flags & FLAG_AROMATIC_STRICT) != 0);
+    boolean aromaticDefined = ((flags & FLAG_AROMATIC_DEFINED) != 0);
     if (aromaticStrict && vRings == null)
       vRings = AU.createArrayOfArrayList(4);
     if (aromaticDefined && needAromatic) {
@@ -406,11 +417,13 @@
      *    
      */
 
-    ignoreStereochemistry = ((flags & Edge.FLAG_IGNORE_STEREOCHEMISTRY) != 0);
-    invertStereochemistry = ((flags & Edge.FLAG_INVERT_STEREOCHEMISTRY) != 0);
-    noAromatic = ((flags & Edge.FLAG_NO_AROMATIC) != 0);
-    noncanonical = ((flags & Edge.FLAG_AROMATIC_NONCANONICAL) != 0);
-      aromaticDouble = ((flags & Edge.FLAG_AROMATIC_DOUBLE) != 0);
+    // flags are passed on from SmilesParser
+    aromaticDouble = ((flags & FLAG_AROMATIC_DOUBLE) != 0);
+    ignoreStereochemistry = ((flags & FLAG_IGNORE_STEREOCHEMISTRY) != 0);
+    invertStereochemistry = ((flags & FLAG_INVERT_STEREOCHEMISTRY) != 0);
+    noAromatic = ((flags & FLAG_NO_AROMATIC) != 0);
+    noncanonical = ((flags & FLAG_AROMATIC_NONCANONICAL) != 0);
+    openSMILES = ((flags & JC.SMILES_TYPE_OPENSMILES) == 
JC.SMILES_TYPE_OPENSMILES);
     
     if (Logger.debugging && !isSilent)
       Logger.debug("SmilesSearch processing " + pattern);
@@ -928,8 +941,8 @@
         if (!noAromatic && !patternAtom.aromaticAmbiguous
             && isAromatic != bsAromatic.get(iAtom)) {
           if (!noncanonical
-              || patternAtom.getExplicitHydrogenCount() != 
-                        atom.getCovalentHydrogenCount())
+              || patternAtom.getExplicitHydrogenCount() != atom
+                  .getCovalentHydrogenCount())
             break;
         }
 
@@ -985,33 +998,41 @@
                 + atom.getImplicitHydrogenCount())
           break;
 
-        // r <n> ring of a given size
-        if (ringData != null && patternAtom.ringSize >= -1) {
-          if (patternAtom.ringSize <= 0) {
-            if ((ringCounts[iAtom] == 0) != (patternAtom.ringSize == 0))
-              break;
-          } else {
-            BS rd = ringData[patternAtom.ringSize == 500 ? 5
-                : patternAtom.ringSize == 600 ? 6 : patternAtom.ringSize];
-            if (rd == null || !rd.get(iAtom))
-              break;
-            if (!noAromatic)
-              if (patternAtom.ringSize == 500) {
-                if (!bsAromatic5.get(iAtom))
-                  break;
-              } else if (patternAtom.ringSize == 600) {
-                if (!bsAromatic6.get(iAtom))
-                  break;
-              }
+        if (openSMILES) {
+          if (!Float.isNaN(patternAtom.osClass)
+              && patternAtom.osClass != 
atom.getFloatProperty("property_osclass"))
+            break;
+        }
+
+        if (ringData != null) {
+          // r <n> ring of a given size
+          if (patternAtom.ringSize >= -1) {
+            if (patternAtom.ringSize <= 0) {
+              if ((ringCounts[iAtom] == 0) != (patternAtom.ringSize == 0))
+                break;
+            } else {
+              BS rd = ringData[patternAtom.ringSize == 500 ? 5
+                  : patternAtom.ringSize == 600 ? 6 : patternAtom.ringSize];
+              if (rd == null || !rd.get(iAtom))
+                break;
+              if (!noAromatic)
+                if (patternAtom.ringSize == 500) {
+                  if (!bsAromatic5.get(iAtom))
+                    break;
+                } else if (patternAtom.ringSize == 600) {
+                  if (!bsAromatic6.get(iAtom))
+                    break;
+                }
+            }
+            // R <n> a certain number of rings
+            if (patternAtom.ringMembership >= -1) {
+              //  R --> -1 implies "!R0"
+              if (patternAtom.ringMembership == -1 ? ringCounts[iAtom] == 0
+                  : ringCounts[iAtom] != patternAtom.ringMembership)
+                break;
+            }
           }
         }
-        // R <n> a certain number of rings
-        if (ringData != null && patternAtom.ringMembership >= -1) {
-          //  R --> -1 implies "!R0"
-          if (patternAtom.ringMembership == -1 ? ringCounts[iAtom] == 0
-              : ringCounts[iAtom] != patternAtom.ringMembership)
-            break;
-        }
         // x <n>
         if (patternAtom.ringConnectivity >= 0) {
           // default > 0

Modified: trunk/Jmol/src/org/jmol/util/Edge.java
===================================================================
--- trunk/Jmol/src/org/jmol/util/Edge.java      2016-03-06 18:23:15 UTC (rev 
20981)
+++ trunk/Jmol/src/org/jmol/util/Edge.java      2016-03-07 04:22:42 UTC (rev 
20982)
@@ -104,13 +104,6 @@
 
   public int index = -1;
   public int order;
-  final public static int FLAG_AROMATIC_NONCANONICAL = 64;
-  final public static int FLAG_AROMATIC_DOUBLE = 32;
-  final public static int FLAG_AROMATIC_DEFINED = 16;
-  final public static int FLAG_AROMATIC_STRICT = 8;
-  final public static int FLAG_INVERT_STEREOCHEMISTRY = 4;
-  final public static int FLAG_IGNORE_STEREOCHEMISTRY = 2;
-  public final static int FLAG_NO_AROMATIC = 1;
 
   abstract public int getAtomIndex1();
 

Modified: trunk/Jmol/src/org/jmol/util/Node.java
===================================================================
--- trunk/Jmol/src/org/jmol/util/Node.java      2016-03-06 18:23:15 UTC (rev 
20981)
+++ trunk/Jmol/src/org/jmol/util/Node.java      2016-03-07 04:22:42 UTC (rev 
20982)
@@ -43,7 +43,14 @@
   public int getIsotopeNumber();
   public int getValence();
   public void set(float x, float y, float z);
+  
+  /**
+   * @param property  "property_xxxx"
+   * @return value or Float.NaN
+   */
 
+  public float getFloatProperty(String property);
+
   // abstracts out the essential pieces for SMARTS processing
   
   public BS findAtomsLike(String substring);

Modified: trunk/Jmol/src/org/jmol/viewer/JC.java
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/JC.java      2016-03-06 18:23:15 UTC (rev 
20981)
+++ trunk/Jmol/src/org/jmol/viewer/JC.java      2016-03-07 04:22:42 UTC (rev 
20982)
@@ -1067,23 +1067,24 @@
   
   public static final int SMILES_TYPE_SMILES       = 0x1;
   public static final int SMILES_TYPE_SMARTS       = 0x2;
+  public static final int SMILES_TYPE_OPENSMILES   = 0x5; 
   
   public static final int SMILES_MATCH_ALL         = 0x10;
   public static final int SMILES_MATCH_ONE         = 0x20;
   public static final int SMILES_RETURN_FIRST      = 0x40;
 
-  public static final int SMILES_EXPLICIT_H                = 0x00100;
-  public static final int SMILES_TOPOLOGY                  = 0x00200;
-  public static final int SMILES_NOAROMATIC                = 0x00400;
-  public static final int SMILES_NOSTEREO                  = 0x00800;
-  public static final int SMILES_POLYHEDRAL                = 0x01000;
-  public static final int SMILES_BIO                       = 0x10000;
-  public static final int SMILES_BIO_ALLOW_UNMATCHED_RINGS = 0x11000;
-  public static final int SMILES_BIO_COV_CROSSLINK         = 0x12000;
-  public static final int SMILES_BIO_HH_CROSSLINK          = 0x16000;
-  public static final int SMILES_BIO_COMMENT               = 0x30000;
-  public static final int SMILES_BIO_NOCOMMENTS            = 0x50000;
-  public static final int SMILES_ATOM_COMMENT              = 0x80000;
+  public static final int SMILES_EXPLICIT_H                = 0x000100;
+  public static final int SMILES_TOPOLOGY                  = 0x000200;
+  public static final int SMILES_NOAROMATIC                = 0x000400;
+  public static final int SMILES_NOSTEREO                  = 0x000800;
+  public static final int SMILES_POLYHEDRAL                = 0x001000;
+  public static final int SMILES_ATOM_COMMENT              = 0x002000;
+  public static final int SMILES_BIO                       = 0x010000;
+  public static final int SMILES_BIO_ALLOW_UNMATCHED_RINGS = 0x030000;
+  public static final int SMILES_BIO_COV_CROSSLINK         = 0x050000;
+  public static final int SMILES_BIO_HH_CROSSLINK          = 0x090000;
+  public static final int SMILES_BIO_COMMENT               = 0x110000;
+  public static final int SMILES_BIO_NOCOMMENTS            = 0x210000;
 
  
   public static final int JSV_NOT = -1;

Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties
===================================================================
--- trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2016-03-06 18:23:15 UTC 
(rev 20981)
+++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties      2016-03-07 04:22:42 UTC 
(rev 20982)
@@ -67,6 +67,17 @@
 
 Jmol.___JmolVersion="14.5.3_2016.03.06"
 
+new feature: optional processing of OpenSMILES [CH2:002] ":<n>" atom class.
+ -- positive integer value only
+ -- checks the atom property property_osclass
+ -- for SMARTS, [:0] means "without an osclass"
+ -- for SMARTS, [!:0] means "any non-zero osclass"
+ -- for SMARTS, same as [$(select property_osclass=n)]
+ -- only enabled with Jmol SMILES directive "/opensmiles/"; otherwise ignored
+
+new feature: {*}.find("OPENSMILES")
+ -- adds atom class if property_osclass is nonzero
+    
 bug fix: Inconsistent use of "DIASTEREOMERS" (preferred) and "DIASTERIOMERS" 
(incorrect)
 
 JmolVersion="14.5.3_2016.03.05"

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://makebettercode.com/inteldaal-eval
_______________________________________________
Jmol-commits mailing list
Jmol-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jmol-commits

Reply via email to