Revision: 21629 http://sourceforge.net/p/jmol/code/21629 Author: hansonr Date: 2017-06-05 03:25:50 +0000 (Mon, 05 Jun 2017) Log Message: ----------- Jmol.___JmolVersion="14.18.1"
bug fix: WRITE MOL should not generate > <JMOL_PARTIAL_CHARGES> because it is not SDF format bug fix: WRITE SDF should generate > <JMOL_PARTIAL_CHARGES> with a trailing space bug fix: (SMILES) targetString.find("SMILES",patternString) will fail for .[C@H]2 (new group and attached to a connection number) bug fix: SHOW CHEMICAL SMILES fails when logLevel is set > 4 new feature: WRITE SDF writes > <.... user data -- can be set using MODEL PROPERTY "molData" x where x is an associative array new feature: associativeArray.pop() -- clears associativeArray new feature: assArray1.push(assArray2) -- adds all key/value entries in assArray2 to assArray1. new feature: assArray1 + assArray2 -- adds all key/value entries into a new associative array. (Complements a1 - a2) Modified Paths: -------------- trunk/Jmol/src/org/jmol/adapter/readers/molxyz/MolReader.java trunk/Jmol/src/org/jmol/modelset/ModelSet.java trunk/Jmol/src/org/jmol/script/SV.java trunk/Jmol/src/org/jmol/script/ScriptEval.java trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java trunk/Jmol/src/org/jmol/scriptext/CmdExt.java trunk/Jmol/src/org/jmol/scriptext/MathExt.java trunk/Jmol/src/org/jmol/smiles/SmilesSearch.java trunk/Jmol/src/org/jmol/smiles/SmilesStereo.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties trunk/Jmol/src/org/jmol/viewer/PropertyManager.java trunk/Jmol/src/org/jmol/viewer/Viewer.java Modified: trunk/Jmol/src/org/jmol/adapter/readers/molxyz/MolReader.java =================================================================== --- trunk/Jmol/src/org/jmol/adapter/readers/molxyz/MolReader.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/adapter/readers/molxyz/MolReader.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -29,10 +29,9 @@ import javajs.util.PT; +import org.jmol.adapter.smarter.Atom; import org.jmol.adapter.smarter.AtomSetCollectionReader; -import org.jmol.adapter.smarter.Atom; import org.jmol.api.JmolAdapter; -import org.jmol.util.Elements; import org.jmol.util.Logger; /** @@ -131,37 +130,30 @@ } private void processMolSdHeader() throws Exception { - /* - * obviously we aren't being this strict, but for the record: - * - * from ctfile.pdf (October 2003): - * - * Line 1: Molecule name. This line is unformatted, but like all - * other lines in a molfile may not extend beyond column 80. - * If no name is available, a blank line must be present. - * Caution: This line must not contain any of the reserved - * tags that identify any of the other CTAB file types - * such as $MDL (RGfile), $$$$ (SDfile record separator), - * $RXN (rxnfile), or $RDFILE (RDfile headers). - * - * Line 2: This line has the format: - * IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR - * (FORTRAN: A2<--A8--><---A10-->A2I2<--F10.5-><---F12.5--><-I6-> ) - * User's first and last initials (l), program name (P), - * date/time (M/D/Y,H:m), dimensional codes (d), scaling factors (S, s), - * energy (E) if modeling program input, internal - * registry number (R) if input through MDL form. A blank line can be - * substituted for line 2. If the internal registry number is more than - * 6 digits long, it is stored in an M REG line (described in Chapter 3). - * - * Line 3: A line for comments. If no comment is entered, a blank line - * must be present. - */ - + // We aren't being this strict. Line definitions are from ctfile.pdf (October 2003) String header = ""; + // Line 1: Molecule name. This line is unformatted, but like all + // other lines in a molfile may not extend beyond column 80. + // If no name is available, a blank line must be present. + // Caution: This line must not contain any of the reserved + // tags that identify any of the other CTAB file types + // such as $MDL (RGfile), $$$$ (SDfile record separator), + // $RXN (rxnfile), or $RDFILE (RDfile headers). + // String thisDataSetName = line.trim(); + asc.setCollectionName(thisDataSetName); + header += line + "\n"; - asc.setCollectionName(thisDataSetName); + + // Line 2: This line has the format: + // IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR + // (FORTRAN: A2<--A8--><---A10-->A2I2<--F10.5-><---F12.5--><-I6-> ) + // User's first and last initials (l), program name (P), + // date/time (M/D/Y,H:m), dimensional codes (d), scaling factors (S, s), + // energy (E) if modeling program input, internal + // registry number (R) if input through MDL form. A blank line can be + // substituted for line 2. If the internal registry number is more than + // 6 digits long, it is stored in an M REG line (described in Chapter 3). rd(); if (line == null) return; @@ -173,15 +165,14 @@ appendLoadNote("This model is 2D. Its 3D structure has not been generated."); } asc.setInfo("dimension", dimension); - //line 3: comment + + // Line 3: A line for comments. If no comment is entered, a blank line + // must be present. rd(); if (line == null) return; line = line.trim(); header += line + "\n"; - if (line.length() != 0) { - thisDataSetName += ": " + line; - } Logger.info(header); checkCurrentLineForScript(); asc.setInfo("fileHeader", header); @@ -277,7 +268,6 @@ // read V2000 user data - Atom[] atoms = asc.atoms; Map<String, String> molData = new Hashtable<String, String>(); rd(); while (line != null && line.indexOf("$$$$") != 0) { @@ -312,18 +302,26 @@ rd(); } + /** + * Read the SDF data with name in lower case + * + * @param molData + * @throws Exception + */ private void readMolData(Map<String, String> molData) throws Exception { Atom[] atoms = asc.atoms; + // "> <xxx>" becomes "xxx" + // "> yyy <xxx> zzz" becomes "yyy <xxx> zzz" String dataName = PT.trim(line, "> <").toLowerCase(); String data = ""; float[] fdata = null; - while (rd() != null && line.indexOf("$$$$") != 0 - && line.indexOf(">") != 0) { + // officially, we need a terminating blank line, and $$$$ could be data, + // but here we do not allow $$$$ due to Jmol legacy writing of JMOL_PARTIAL_CHARGES + while (rd() != null && !line.equals("$$$$") + && line.length() > 0) data += line + "\n"; - continue; - } data = PT.trim(data, "\n"); - Logger.info(dataName + ":" + data.replace('\n', '|')); + Logger.info(dataName + ":" + PT.esc(data)); molData.put(dataName, data); if (dataName.toUpperCase().contains("_PARTIAL_CHARGES")) { try { Modified: trunk/Jmol/src/org/jmol/modelset/ModelSet.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/ModelSet.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/modelset/ModelSet.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -1477,7 +1477,8 @@ } public void setInfo(int modelIndex, Object key, Object value) { - am[modelIndex].auxiliaryInfo.put((String) key, value); + if (modelIndex >= 0 && modelIndex < mc) + am[modelIndex].auxiliaryInfo.put((String) key, value); } public Object getInfo(int modelIndex, String key) { Modified: trunk/Jmol/src/org/jmol/script/SV.java =================================================================== --- trunk/Jmol/src/org/jmol/script/SV.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/script/SV.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -1520,42 +1520,62 @@ /** * - * Script variables are pushed after cloning, because - * the name comes with them when we do otherwise - * they are not mutable anyway. We do want to have actual + * Script variables are pushed after cloning, because the name comes with them + * when we do otherwise they are not mutable anyway. We do want to have actual * references to points, lists, and associative arrays - * + * @param mapKey * @param value * null to pop - * @param mapKey + * * @return array */ - public SV pushPop(SV value, SV mapKey) { - if (mapKey != null) { + public SV pushPop(SV mapKey, SV value) { + if (mapKey == null) { Map<String, SV> m = getMap(); + if (m == null) { + Lst<SV> x = getList(); + if (value == null || x == null) { + // array.pop() + return (x == null || x.size() == 0 ? newS("") : x.removeItemAt(x + .size() - 1)); + } + // array.push(value) + x.addLast(newI(0).setv(value)); + } else { + if (value == null) { + // assocArray.pop() + m.clear(); // new Jmol 14.18 + } else { + Map<String, SV> m1 = value.getMap(); + if (m1 != null) + m.putAll(m1); // new Jmol 14.18 + // assocArray.push(value) + } + } + } else { + Map<String, SV> m = getMap(); if (value == null) { SV v = null; if (m == null) { + // array.pop(i) Lst<SV> lst = getList(); int len = lst.size(); int i = iValue(mapKey) - 1; if (i < 0) - i += len; + i += len; if (i >= 0 && i < len) { v = lst.removeItemAt(i); } } else { + // assocArray.pop(key) v = m.remove(mapKey.asString()); } return (v == null ? newS("") : v); } - if (m != null) + if (m != null) { + //assocArray.push(key,value) m.put(mapKey.asString(), newI(0).setv(value)); - } else { - Lst<SV> x = getList(); - if (value == null || x == null) - return (x == null || x.size() == 0 ? newS("") : x.removeItemAt(x.size() - 1)); - x.addLast(newI(0).setv(value)); + } } return this; } Modified: trunk/Jmol/src/org/jmol/script/ScriptEval.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptEval.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/script/ScriptEval.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -5176,6 +5176,8 @@ isRange = true; break; case T.property: + if (modelIndex < 0 && (modelIndex = vwr.am.cmi) < 0) + return; propName = paramAsStr(++i); SV sv = setVariable(++i, -1, "", false); if (sv != null && !chk) { @@ -5185,8 +5187,9 @@ } prop = SV.oValue(sv); } - i = slen; - break; + if (!chk) + vwr.ms.setInfo(modelIndex, propName, prop); + return; default: frameControl(offset); return; @@ -5256,11 +5259,6 @@ } } - if (propName != null) { - if (modelIndex >= 0) - vwr.ms.setInfo(modelIndex, propName, prop); - return; - } if (!isPlay && !isRange || modelIndex >= 0) vwr.setCurrentModelIndexClear(modelIndex, false); if (isPlay && nFrames == 2 || isRange || isHyphen) { Modified: trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -1150,6 +1150,12 @@ return addXBool(SV.isLike(x1, x2)); case T.plus: switch (x1.tok) { + case T.hash: + Map<String, SV> ht = new Hashtable<String, SV>((Map<String, SV>) x1.value); + Map<String, SV> map = x2.getMap(); + if (map != null) + ht.putAll(map); // new Jmol 14.18 + return addX(SV.getVariableMap(ht)); case T.integer: if (!isDecimal(x2)) return addXInt(x1.intValue + x2.asInt()); Modified: trunk/Jmol/src/org/jmol/scriptext/CmdExt.java =================================================================== --- trunk/Jmol/src/org/jmol/scriptext/CmdExt.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/scriptext/CmdExt.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -4323,9 +4323,13 @@ + "///"); filter = null; } - if (msg == null) + if (msg == null) { + int level = Logger.getLogLevel(); + Logger.setLogLevel(4); msg = (tok == T.smiles ? vwr.getSmiles(null) : vwr .getOpenSmiles(null)); + Logger.setLogLevel(level); + } } catch (Exception ex) { msg = ex.getMessage(); } @@ -4439,6 +4443,9 @@ if (!chk) msg = vwr.getAllSettings(null); break; + case T.title: + msg = vwr.getFrameTitle(); + break; case T.url: // in a new window if ((len = slen) == 2) { Modified: trunk/Jmol/src/org/jmol/scriptext/MathExt.java =================================================================== --- trunk/Jmol/src/org/jmol/scriptext/MathExt.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/scriptext/MathExt.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -1884,10 +1884,10 @@ SV x2; switch (tok) { case T.push: - return (len == 2 && mp.addX(x1.pushPop(args[1], args[0])) || len == 1 - && mp.addX(x1.pushPop(args[0], null))); + return (len == 2 && mp.addX(x1.pushPop(args[0], args[1])) || len == 1 + && mp.addX(x1.pushPop(null, args[0]))); case T.pop: - return (len == 1 && mp.addX(x1.pushPop(null, args[0])) || len == 0 + return (len == 1 && mp.addX(x1.pushPop(args[0], null)) || len == 0 && mp.addX(x1.pushPop(null, null))); case T.add: if (len != 1 && len != 2) Modified: trunk/Jmol/src/org/jmol/smiles/SmilesSearch.java =================================================================== --- trunk/Jmol/src/org/jmol/smiles/SmilesSearch.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/smiles/SmilesSearch.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -1796,6 +1796,7 @@ } SmilesAtom atom2 = atoms[sBond.atom2.getMatchingAtomIndex()]; SmilesBond b = new SmilesBond(atom1, atom2, order, false); + b.isConnection = sBond.isConnection; // do NOT add this bond to the second atom -- we will do that later; atom2.bondCount--; if (Logger.debugging) Modified: trunk/Jmol/src/org/jmol/smiles/SmilesStereo.java =================================================================== --- trunk/Jmol/src/org/jmol/smiles/SmilesStereo.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/smiles/SmilesStereo.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -545,17 +545,13 @@ Logger.debug("checking stereochemistry..."); //for debugging, first try SET DEBUG - //for (int i = 0; i < ac; i++) { - // SmilesAtom sAtom = patternAtoms[i]; - // System.out.print(sAtom + "="); - //} - //System.out.println(""); - //for (int i = 0; i < ac; i++) { - // SmilesAtom sAtom = patternAtoms[i]; - // JmolSmilesNode atom0 = jmolAtoms[sAtom.getMatchingAtom()]; - // System.out.print(atom0.getIndex() + "-"); - //} - //System.out.println(""); +//System.out.println(""); +//for (int i = 0; i < search.ac; i++) { +// SmilesAtom sAtom = search.patternAtoms[i]; +// Node atom0 = sAtom.getMatchingAtom(); +// System.out.print(atom0.getIndex() + (sAtom.stereo != null ? "@" : "") + "-"); +//} +//System.out.println(""); for (int i = 0; i < search.ac; i++) { SmilesAtom pAtom = search.patternAtoms[i]; @@ -577,8 +573,8 @@ if (haveTopo && sAtom0.getChiralClass() != chiralClass) return false; if (Logger.debugging) - Logger.debug("...type " + chiralClass + " for pattern atom " + pAtom - + " " + atom0); + Logger.debug("...type " + chiralClass + " for pattern atom \n " + pAtom + + "\n " + atom0); switch (chiralClass) { case POLYHEDRAL: if (pAtom.stereo.isNot) @@ -950,14 +946,16 @@ * @return 1 for "@", 2 for "@@" */ static int getHandedness(SimpleNode a, SimpleNode b, SimpleNode c, SimpleNode pt, VTemp v) { - float d = Measure.getNormalThroughPoints((P3) a, (P3) b, (P3) c, v.vTemp, v.vA); -// int atat = (distanceToPlane(v.vTemp, d, (P3) pt) > 0 ? 1 : 2); + float d = Measure.getNormalThroughPoints((P3) a, (P3) b, (P3) c, v.vTemp, v.vA); + //int atat = (Measure.distanceToPlaneV(v.vTemp, d, (P3) pt) > 0 ? 1 : 2); // System.out.println("$ draw p1 " + P3.newP((P3)a) +" color red '"+a+" [2]'"); // System.out.println("$ draw p2 " + P3.newP((P3)b) +" color green '"+b+" [3]'"); // System.out.println("$ draw p3 " + P3.newP((P3)c) +" color blue '"+c+" [4]'"); // System.out.println("$ draw p " + P3.newP((P3)a) +" " + P3.newP((P3)b) +" " + P3.newP((P3)c) +"" ); // System.out.println("$ draw v vector {" + P3.newP((P3)pt) +"} " + v.vTemp+" '"+ (atat==2 ? "@@" : "@")+ pt + " [1]' color " + (atat == 2 ? "white" : "yellow")); - return (Measure.distanceToPlaneV(v.vTemp, d, (P3) pt) > 0 ? 1 : 2); + d = Measure.distanceToPlaneV(v.vTemp, d, (P3) pt); +// System.out.println("# " + d); + return (d > 0 ? 1 : 2); } private static void getPlaneNormals(P3 atom1, P3 atom2, P3 atom3, Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2017-06-05 03:25:50 UTC (rev 21629) @@ -56,8 +56,23 @@ # TODO: fix UNDO -Jmol.___JmolVersion="14.17.2" +Jmol.___JmolVersion="14.18.1" +bug fix: WRITE MOL should not generate > <JMOL_PARTIAL_CHARGES> because it is not SDF format +bug fix: WRITE SDF should generate > <JMOL_PARTIAL_CHARGES> with a trailing space +bug fix: (SMILES) targetString.find("SMILES",patternString) will fail for .[C@H]2 (new group and attached to a connection number) +bug fix: SHOW CHEMICAL SMILES fails when logLevel is set > 4 + +new feature: WRITE SDF writes > <.... user data + -- can be set using MODEL PROPERTY "molData" x where x is an associative array + +new feature: associativeArray.pop() -- clears associativeArray +new feature: assArray1.push(assArray2) -- adds all key/value entries in assArray2 to assArray1. +new feature: assArray1 + assArray2 -- adds all key/value entries into a new associative array. (Complements a1 - a2) + + +JmolVersion="14.17.2" // 2017.06.03 + bug fix: WRITE FILE not working when file has been cached. bug fix: array.find("regex...","") does not reset RegExp each time it runs RegExp.exec() so does not find all possibilities Modified: trunk/Jmol/src/org/jmol/viewer/PropertyManager.java =================================================================== --- trunk/Jmol/src/org/jmol/viewer/PropertyManager.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/viewer/PropertyManager.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -1218,7 +1218,6 @@ bsBonds = getCovalentBondsForAtoms(ms.bo, ms.bondCount, bsTemp); if (!(isOK = addMolFile(i, mol, bsTemp, bsBonds, false, false, noAromatic, q))) break; - mol.append("$$$$\n"); } } else if (isXYZ) { LabelToken[] tokensXYZ = LabelToken.compile(vwr, @@ -1314,6 +1313,7 @@ int nBonds = bsBonds.cardinality(); if (!asV3000 && !asJSON && (nAtoms > 999 || nBonds > 999)) return false; + boolean asSDF = (iModel >= 0); ModelSet ms = vwr.ms; int[] atomMap = new int[ms.ac]; P3 pTemp = new P3(); @@ -1354,15 +1354,31 @@ else { mol.append("M END\n"); } - if (!asJSON && !asV3000) { + if (asSDF) { + try { + @SuppressWarnings("unchecked") + Map<String, Object> molData = (Map<String, Object>) vwr.ms.getInfo(iModel, "molData"); float[] pc = ms.getPartialCharges(); if (pc != null) { - mol.append("> <JMOL_PARTIAL_CHARGES>\n").appendI(nAtoms) - .appendC('\n'); + if (molData == null) + molData = new Hashtable<String, Object>(); + SB sb = new SB(); + sb.appendI(nAtoms).appendC('\n'); for (int i = bsAtoms.nextSetBit(0), n = 0; i >= 0; i = bsAtoms .nextSetBit(i + 1)) - mol.appendI(++n).append(" ").appendF(pc[i]).appendC('\n'); + sb.appendI(++n).append(" ").appendF(pc[i]).appendC('\n'); + molData.put("jmol_partial_charges", sb.toString()); } + for (String key: molData.keySet()) { + Object o = molData.get(key); + if (o instanceof SV) + o = ((SV)o).asString(); + mol.append("> <" + key.toUpperCase() + ">\n").append(PT.trim(o.toString(), "\n")).append("\n\n"); + } + } catch (Throwable e) { + // ignore + } + mol.append("$$$$\n"); } return true; } Modified: trunk/Jmol/src/org/jmol/viewer/Viewer.java =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Viewer.java 2017-06-04 02:57:04 UTC (rev 21628) +++ trunk/Jmol/src/org/jmol/viewer/Viewer.java 2017-06-05 03:25:50 UTC (rev 21629) @@ -8972,10 +8972,10 @@ SV p = pickedList.pushPop(null, null); // don't allow double click if (p.tok == T.bitset) - pickedList.pushPop(p, null); + pickedList.pushPop(null, p); if (p.tok != T.bitset || !((BS) p.value).get(atomIndex)) - pickedList.pushPop(SV.newV(T.bitset, BSUtil.newAndSetBit(atomIndex)), - null); + pickedList.pushPop(null, + SV.newV(T.bitset, BSUtil.newAndSetBit(atomIndex))); } /** 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