Revision: 18330 http://sourceforge.net/p/jmol/code/18330 Author: hansonr Date: 2013-06-14 12:44:40 +0000 (Fri, 14 Jun 2013) Log Message: ----------- ___JmolVersion="13.1.17_dev_2013.06.14"
bug fix: COMPARE could rotate to less-good fit with SMARTS search bug fix: draw ARROW ATOM/BOND broken new feature: compare({atomset1} {atomset2} "ccCCN" "bonds") new feature: {1.1}.find("ccCCN", "BONDS") Modified Paths: -------------- trunk/Jmol/src/org/jmol/modelset/AtomCollection.java trunk/Jmol/src/org/jmol/modelset/ModelCollection.java trunk/Jmol/src/org/jmol/modelset/ModelSet.java trunk/Jmol/src/org/jmol/script/SV.java trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java trunk/Jmol/src/org/jmol/thread/SpinThread.java trunk/Jmol/src/org/jmol/util/Measure.java trunk/Jmol/src/org/jmol/viewer/ActionManager.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties trunk/Jmol/src/org/jmol/viewer/TransformManager.java trunk/Jmol/src/org/jmol/viewer/Viewer.java Modified: trunk/Jmol/src/org/jmol/modelset/AtomCollection.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/AtomCollection.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/modelset/AtomCollection.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -2537,6 +2537,7 @@ info.put("info", getAtomInfo(i, null)); info.put("sym", getElementSymbol(i)); } - + + } Modified: trunk/Jmol/src/org/jmol/modelset/ModelCollection.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/ModelCollection.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/modelset/ModelCollection.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -3381,4 +3381,30 @@ return info; } + public int[][] getDihedralMap(int[] alist) { + JmolList<int[]> list = new JmolList<int[]>(); + int n = alist.length; + Atom ai = null, aj = null, ak = null, al = null; + for (int i = n - 1; --i >= 0;) + for (int j = n; --j > i;) { + ai = atoms[alist[i]]; + aj = atoms[alist[j]]; + if (ai.isBonded(aj)) { + for (int k = n; --k >= 0;) + if (k != i && k != j && (ak = atoms[alist[k]]).isBonded(ai)) + for (int l = n; --l >= 0;) + if (l != i && l != j && l != k + && (al = atoms[alist[l]]).isBonded(aj)) + list.addLast(new int[] { ak.index, ai.index, aj.index, + al.index }); + } + } + n = list.size(); + int[][] ilist = new int[n][]; + for (int i = n; --i >= 0;) + ilist[n - i - 1] = list.get(i); + return ilist; + } + + } Modified: trunk/Jmol/src/org/jmol/modelset/ModelSet.java =================================================================== --- trunk/Jmol/src/org/jmol/modelset/ModelSet.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/modelset/ModelSet.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -25,6 +25,7 @@ package org.jmol.modelset; +import org.jmol.util.AxisAngle4f; import org.jmol.util.BS; import org.jmol.util.BSUtil; import org.jmol.util.JmolEdge; @@ -40,6 +41,7 @@ import org.jmol.util.V3; import org.jmol.viewer.JC; +import org.jmol.viewer.TransformManager; import org.jmol.viewer.Viewer; import org.jmol.script.T; import org.jmol.api.Interface; @@ -50,6 +52,7 @@ import org.jmol.util.JmolList; +import java.util.Hashtable; import java.util.Map; @@ -831,6 +834,29 @@ private final Matrix4f mat4t = new Matrix4f(); private final V3 vTemp = new V3(); + public void setDihedrals(float[] dihedralList, BS[] bsBranches, float f) { + int n = dihedralList.length / 6; + for (int j = 0, pt = 0; j < n; j++, pt += 6) { + BS bs = bsBranches[j]; + if (bs == null || bs.isEmpty()) + continue; + Atom a1 = atoms[(int) dihedralList[pt + 1]]; + Atom a2 = atoms[(int) dihedralList[pt + 2]]; + V3 v = V3.newV(a2); + v.sub(a1); + float angle = (dihedralList[pt + 5] - dihedralList[pt + 4]) * f; + AxisAngle4f aa = AxisAngle4f.newVA(v, (float)(-angle / TransformManager.degreesPerRadian)); + matTemp.setAA(aa); + ptTemp.setT(a1); + for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { + atoms[i].sub(ptTemp); + matTemp.transform(atoms[i]); + atoms[i].add(ptTemp); + taintAtom(i, TAINT_COORD); + } + } + } + public void moveAtoms(Matrix3f mNew, Matrix3f matrixRotate, V3 translation, BS bs, P3 center, boolean isInternal) { @@ -882,7 +908,6 @@ recalculatePositionDependentQuantities(bs, mat4); } - public void recalculatePositionDependentQuantities(BS bs, Matrix4f mat) { if (getHaveStraightness()) calculateStraightness(); @@ -901,5 +926,38 @@ */ } + public BS[] getBsBranches(float[] dihedralList) { + int n = dihedralList.length / 6; + BS[] bsBranches = new BS[n]; + Map<String, Boolean> map = new Hashtable<String, Boolean>(); + for (int i = 0, pt = 0; i < n; i++, pt += 6) { + float dv = dihedralList[pt + 5] - dihedralList[pt + 4]; + if (Math.abs(dv) < 1f) + continue; + int i0 = (int) dihedralList[pt + 1]; + int i1 = (int) dihedralList[pt + 2]; + String s = "" + i0 + "_" + i1; + if (map.containsKey(s)) + continue; + map.put(s, Boolean.TRUE); + BS bs = viewer.getBranchBitSet(i1, i0, true); + Bond[] bonds = atoms[i0].bonds; + Atom a0 = atoms[i0]; + for (int j = 0; j < bonds.length; j++) { + Bond b = bonds[j]; + if (!b.isCovalent()) + continue; + int i2 = b.getOtherAtom(a0).index; + if (i2 == i1) + continue; + if (bs.get(i2)) { + bs = null; + break; + } + } + bsBranches[i] = bs; + } + return bsBranches; + } } Modified: trunk/Jmol/src/org/jmol/script/SV.java =================================================================== --- trunk/Jmol/src/org/jmol/script/SV.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/script/SV.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -329,7 +329,7 @@ static SV getVariableAI(int[] ix) { JmolList<SV> objects = new JmolList<SV>(); for (int i = 0; i < ix.length; i++) - objects.addLast(newVariable(integer, Integer.valueOf(ix[i]))); + objects.addLast(newScriptVariableInt(ix[i])); return newVariable(varray, objects); } @@ -1254,6 +1254,28 @@ return list; } + static JmolList<Object> listAny(SV x) { + JmolList<Object> list = new JmolList<Object>(); + JmolList<SV> l = x.getList(); + for (int i = 0; i < l.size(); i++) { + SV v = l.get(i); + JmolList<SV> l2 = v.getList(); + if (l2 == null) { + list.addLast(v.value); + } else { + JmolList<Object> o = new JmolList<Object>(); + for (int j = 0; j < l2.size(); j++) { + v = l2.get(j); + System.out.println(v); + + } + list.addLast(o); + } + System.out.println(v); + } + return list; + + } static float[] flistValue(T x, int nMin) { if (x.tok != varray) return new float[] { fValue(x) }; Modified: trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -4591,6 +4591,7 @@ float[] fparams = null; int n = 0; String s = null; + iToken = i; switch (tokAt(i)) { case T.string: s = SV.sValue(st[i]); @@ -7358,7 +7359,7 @@ Matrix4f m4 = new Matrix4f(); float stddev = getSmilesCorrelation(bsFrom, bsTo, strSmiles, null, - null, m4, null, !isSmiles, false); + null, m4, null, !isSmiles, false, null); if (Float.isNaN(stddev)) error(ERROR_invalidArgument); V3 translation = new V3(); @@ -7396,7 +7397,7 @@ if (!useThreads()) doAnimate = false; viewer.rotateAboutPointsInternal(this, centerAndPoints[0][0], pt1, endDegrees - / nSeconds, endDegrees, doAnimate, bsFrom, translation, ptsB); + / nSeconds, endDegrees, doAnimate, bsFrom, translation, ptsB, null); if (doAnimate && isJS) throw new ScriptInterruption(this, "compare", 1); } @@ -7404,17 +7405,16 @@ float getSmilesCorrelation(BS bsA, BS bsB, String smiles, JmolList<P3> ptsA, JmolList<P3> ptsB, - Matrix4f m, JmolList<BS> vReturn, - boolean isSmarts, boolean asMap) + Matrix4f m4, JmolList<BS> vReturn, + boolean isSmarts, boolean asMap, int[][] mapSet) throws ScriptException { - float tolerance = 0.1f; // TODO + float tolerance = (mapSet == null ? 0.1f : Float.MAX_VALUE); try { if (ptsA == null) { ptsA = new JmolList<P3>(); ptsB = new JmolList<P3>(); } - if (m == null) - m = new Matrix4f(); + Matrix4f m = new Matrix4f(); Atom[] atoms = viewer.modelSet.atoms; int atomCount = viewer.getAtomCount(); @@ -7424,8 +7424,9 @@ evalError(viewer.getSmilesMatcher().getLastException(), null); if (maps.length == 0) return Float.NaN; - for (int i = 0; i < maps[0].length; i++) - ptsA.addLast(atoms[maps[0][i]]); + int[] mapA = maps[0]; + for (int i = 0; i < mapA.length; i++) + ptsA.addLast(atoms[mapA[i]]); maps = viewer.getSmilesMatcher().getCorrelationMaps(smiles, atoms, atomCount, bsB, isSmarts, false); if (maps == null) @@ -7456,9 +7457,16 @@ } if (stddev < lowestStdDev) { mapB = maps[i]; + if (m4 != null) + m4.setM(m); lowestStdDev = stddev; } } + if (mapSet != null) { + mapSet[0] = mapA; + mapSet[1] = mapB; + } + ptsB.clear(); for (int i = 0; i < mapB.length; i++) ptsB.addLast(atoms[mapB[i]]); return lowestStdDev; @@ -7515,7 +7523,7 @@ JmolList<BS> vReturn = new JmolList<BS>(); float stddev = getSmilesCorrelation(bsMatch3D, bsSelected, pattern, null, - null, null, vReturn, isSmarts, false); + null, null, vReturn, isSmarts, false, null); if (Float.isNaN(stddev)) { if (asOneBitset) return new BS(); @@ -10357,6 +10365,7 @@ float endDegrees = Float.MAX_VALUE; boolean isMolecular = false; boolean haveRotation = false; + float[] dihedralList = null; JmolList<P3> ptsA = null; P3[] points = new P3[2]; V3 rotAxis = V3.new3(0, 1, 0); @@ -10393,8 +10402,7 @@ // {X, Y, Z} // $drawObject[n] P3 pt1 = centerParameterForModel(i, viewer.getCurrentModelIndex()); - if (!chk && tok == T.dollarsign - && tokAt(i + 2) != T.leftsquare) { + if (!chk && tok == T.dollarsign && tokAt(i + 2) != T.leftsquare) { // rotation about an axis such as $line1 isMolecular = true; rotAxis = getDrawObjectAxis(objectNameParameter(++i), viewer @@ -10419,6 +10427,7 @@ if (isSpin) { // rotate spin ... [degreesPerSecond] // rotate spin ... [endDegrees] [degreesPerSecond] + // rotate spin BRANCH <DihedralList> [seconds] if (degreesPerSecond == Float.MIN_VALUE) { degreesPerSecond = floatParameter(i); continue; @@ -10481,17 +10490,23 @@ q = Quaternion.newVA(rotAxis, endDegrees); break; case T.branch: - haveRotation = true; - int iAtom1 = atomExpressionAt(++i).nextSetBit(0); - int iAtom2 = atomExpressionAt(++iToken).nextSetBit(0); - if (iAtom1 < 0 || iAtom2 < 0) - return; - bsAtoms = viewer.getBranchBitSet(iAtom2, iAtom1); isSelected = true; isMolecular = true; - points[0] = viewer.getAtomPoint3f(iAtom1); - points[1] = viewer.getAtomPoint3f(iAtom2); - nPoints = 2; + haveRotation = true; + if (isArrayParameter(++i)) { + dihedralList = floatParameterSet(i, 6, Integer.MAX_VALUE); + i = iToken; + isSpin = true; + } else { + int iAtom1 = atomExpressionAt(i).nextSetBit(0); + int iAtom2 = atomExpressionAt(++iToken).nextSetBit(0); + if (iAtom1 < 0 || iAtom2 < 0) + return; + bsAtoms = viewer.getBranchBitSet(iAtom2, iAtom1, true); + points[0] = viewer.getAtomPoint3f(iAtom1); + points[1] = viewer.getAtomPoint3f(iAtom2); + nPoints = 2; + } break; // 12.0 options @@ -10527,8 +10542,7 @@ if (endDegrees == 0 && points[0] != null) { // glide plane rotAxis.normalize(); - Measure.getPlaneThroughPoint(points[0], rotAxis, - invPlane = new P4()); + Measure.getPlaneThroughPoint(points[0], rotAxis, invPlane = new P4()); } q = Quaternion.newVA(rotAxis, endDegrees); nPoints = (points[0] == null ? 0 : 1); @@ -10552,8 +10566,8 @@ m4 = new Matrix4f(); points[0] = new P3(); nPoints = 1; - float stddev = (chk ? 0 : Measure.getTransformMatrix4(ptsA, - ptsB, m4, points[0])); + float stddev = (chk ? 0 : Measure.getTransformMatrix4(ptsA, ptsB, m4, + points[0])); // if the standard deviation is very small, we leave ptsB // because it will be used to set the absolute final positions if (stddev > 0.001) @@ -10589,11 +10603,11 @@ bsAtoms = bsCompare; } float rate = (degreesPerSecond == Float.MIN_VALUE ? 10 - : endDegrees == Float.MAX_VALUE ? degreesPerSecond - : (degreesPerSecond < 0) == (endDegrees > 0) ? - // -n means number of seconds, not degreesPerSecond - -endDegrees / degreesPerSecond - : degreesPerSecond); + : endDegrees == Float.MAX_VALUE ? degreesPerSecond + : (degreesPerSecond < 0) == (endDegrees > 0) ? + // -n means number of seconds, not degreesPerSecond + -endDegrees / degreesPerSecond + : degreesPerSecond); if (q != null) { // only when there is a translation (4x4 matrix or TRANSLATE) // do we set the rotation to be the center of the selected atoms or model @@ -10631,7 +10645,7 @@ if (rotAxis == null) return; } - if (nPoints < 2) { + if (nPoints < 2 && dihedralList == null) { if (!isMolecular) { // fixed-frame rotation // rotate x 10 # Chime-like @@ -10640,8 +10654,9 @@ // rotate x 10 $object # point-centered if (isSpin && bsAtoms == null && !useThreads()) return; - if (viewer.rotateAxisAngleAtCenter(this, points[0], rotAxis, rate, endDegrees, - isSpin, bsAtoms) && isJS && isSpin && bsAtoms == null) + if (viewer.rotateAxisAngleAtCenter(this, points[0], rotAxis, rate, + endDegrees, isSpin, bsAtoms) + && isJS && isSpin && bsAtoms == null) throw new ScriptInterruption(this, "rotate", 1); return; } @@ -10685,8 +10700,9 @@ } else { if (!useThreads()) return; - if (viewer.rotateAboutPointsInternal(this, points[0], points[1], rate, endDegrees, - isSpin, bsAtoms, translation, ptsB) && isJS && isSpin) + if (viewer.rotateAboutPointsInternal(this, points[0], points[1], rate, + endDegrees, isSpin, bsAtoms, translation, ptsB, dihedralList) + && isJS && isSpin) throw new ScriptInterruption(this, "rotate", 1); } } Modified: trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/script/ScriptMathProcessor.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -77,7 +77,7 @@ * */ - private boolean isSyntaxCheck; + private boolean chk; private boolean wasSyntaxCheck; private boolean logMessages; private ScriptEvaluator eval; @@ -105,7 +105,7 @@ this.eval = eval; this.viewer = eval.viewer; this.logMessages = eval.logMessages; - this.isSyntaxCheck = wasSyntaxCheck = eval.chk; + this.chk = wasSyntaxCheck = eval.chk; this.isArrayItem = isArrayItem; this.asVector = asVector || isArrayItem; this.asBitSet = asBitSet; @@ -453,7 +453,7 @@ case T.plusPlus: incrementX = (op.tok == T.plusPlus ? 1 : -1); if (ptid == ptx) { - if (isSyntaxCheck) + if (chk) return true; SV x = xStack[xPt]; xStack[xPt] = SV.newVariable(T.string, "").setv(x, false); @@ -625,7 +625,7 @@ boolean tf = getX().asBoolean(); addXVar(SV.getBoolean(tf)); if (tf == (op.tok == T.opOr)) { // TRUE or.. FALSE and... - isSyntaxCheck = true; + chk = true; op = (op.tok == T.opOr ? T.tokenOrTRUE : T.tokenAndFALSE); } } @@ -730,7 +730,7 @@ // we cannot know what variables are real // if this is a property selector, as in x.func(), then we // just exit; otherwise we add a new TRUE to xStack - if (isSyntaxCheck) + if (chk) return (op.tok == T.propselector ? true : addXBool(true)); switch (tok) { case T.abs: @@ -842,6 +842,7 @@ // compare({bitset},{bitset}[,"SMARTS"|"SMILES"],smilesString [,"stddev"]) // returns matrix4f for rotation/translation or stddev // compare({bitset},{bitset},"ISOMER") 12.1.5 + // compare({bitset},{bitset},"BONDS",smilesString) 13.1.17 if (args.length < 2 || args.length > 5) return false; @@ -849,7 +850,9 @@ String sOpt = SV.sValue(args[args.length - 1]); boolean isStdDev = sOpt.equalsIgnoreCase("stddev"); boolean isIsomer = sOpt.equalsIgnoreCase("ISOMER"); - boolean isSmiles = (!isIsomer && args.length > (isStdDev ? 3 : 2)); + boolean isBonds = sOpt.equalsIgnoreCase("BONDS"); + boolean isSmiles = (isBonds || !isIsomer + && args.length > (isStdDev ? 3 : 2)); BS bs1 = (args[0].tok == T.bitset ? (BS) args[0].value : null); BS bs2 = (args[1].tok == T.bitset ? (BS) args[1].value : null); String smiles1 = (bs1 == null ? SV.sValue(args[0]) : ""); @@ -861,51 +864,82 @@ if (bs1 == null || bs2 == null) return false; } + if (isBonds) { + if (args.length != 4) + return false; + smiles1 = SV.sValue(args[2]); + int[][] mapSet = ArrayUtil.newInt2(2); + eval.getSmilesCorrelation(bs1, bs2, smiles1, null, null, + null, null, true, false, mapSet); + int[][] bondMap1 = viewer.getDihedralMap(mapSet[0]); + int[][] bondMap2 = (bondMap1 == null ? null : viewer.getDihedralMap(mapSet[1])); + if (bondMap2 == null || bondMap2.length != bondMap1.length) + return addXStr(""); + float[][] angles = new float[bondMap1.length][3]; + Atom[] atoms = viewer.modelSet.atoms; + getTorsions(atoms, bondMap2, angles, 0); + getTorsions(atoms, bondMap1, angles, 1); + float[] data = new float[bondMap1.length * 6]; + for (int i = 0, pt = 0; i < bondMap1.length; i++) { + int[] map = bondMap1[i]; + data[pt++] = map[0]; + data[pt++] = map[1]; + data[pt++] = map[2]; + data[pt++] = map[3]; + data[pt++] = angles[i][0]; + data[pt++] = angles[i][1]; + } + return addXAF(data); + } if (isIsomer) { if (args.length != 3) return false; - if (bs1 == null && bs2 == null) - return addXStr(viewer.getSmilesMatcher().getRelationship(smiles1, smiles2).toUpperCase()); + if (bs1 == null && bs2 == null) + return addXStr(viewer.getSmilesMatcher().getRelationship(smiles1, + smiles2).toUpperCase()); String mf1 = (bs1 == null ? viewer.getSmilesMatcher() - .getMolecularFormula(smiles1, false) : JmolMolecule.getMolecularFormula( - viewer.getModelSet().atoms, bs1, false)); + .getMolecularFormula(smiles1, false) : JmolMolecule + .getMolecularFormula(viewer.getModelSet().atoms, bs1, false)); String mf2 = (bs2 == null ? viewer.getSmilesMatcher() - .getMolecularFormula(smiles2, false) : JmolMolecule.getMolecularFormula( - viewer.getModelSet().atoms, bs2, false)); + .getMolecularFormula(smiles2, false) : JmolMolecule + .getMolecularFormula(viewer.getModelSet().atoms, bs2, false)); if (!mf1.equals(mf2)) return addXStr("NONE"); if (bs1 != null) - smiles1 = (String) eval.getSmilesMatches("", null, bs1, null, false, true); + smiles1 = (String) eval.getSmilesMatches("", null, bs1, null, false, + true); boolean check; if (bs2 == null) { // note: find smiles1 IN smiles2 here check = (viewer.getSmilesMatcher().areEqual(smiles2, smiles1) > 0); } else { - check = (((BS) eval.getSmilesMatches(smiles1, null, bs2, null, - false, true)).nextSetBit(0) >= 0); + check = (((BS) eval.getSmilesMatches(smiles1, null, bs2, null, false, + true)).nextSetBit(0) >= 0); } if (!check) { // MF matched, but didn't match SMILES String s = smiles1 + smiles2; if (s.indexOf("/") >= 0 || s.indexOf("\\") >= 0 || s.indexOf("@") >= 0) { - if (smiles1.indexOf("@") >= 0 && (bs2 != null || smiles2.indexOf("@") >= 0)) { + if (smiles1.indexOf("@") >= 0 + && (bs2 != null || smiles2.indexOf("@") >= 0)) { // reverse chirality centers smiles1 = viewer.getSmilesMatcher().reverseChirality(smiles1); if (bs2 == null) { check = (viewer.getSmilesMatcher().areEqual(smiles1, smiles2) > 0); } else { - check = (((BS) eval.getSmilesMatches(smiles1, null, bs2, - null, false, true)).nextSetBit(0) >= 0); + check = (((BS) eval.getSmilesMatches(smiles1, null, bs2, null, + false, true)).nextSetBit(0) >= 0); } if (check) return addXStr("ENANTIOMERS"); } // remove all stereochemistry from SMILES string if (bs2 == null) { - check = (viewer.getSmilesMatcher().areEqual("/nostereo/" + smiles2, smiles1) > 0); + check = (viewer.getSmilesMatcher().areEqual("/nostereo/" + smiles2, + smiles1) > 0); } else { - Object ret = eval.getSmilesMatches("/nostereo/" + smiles1, null, bs2, null, - false, true); + Object ret = eval.getSmilesMatches("/nostereo/" + smiles1, null, + bs2, null, false, true); check = (((BS) ret).nextSetBit(0) >= 0); } if (check) @@ -918,12 +952,12 @@ if (bs1 == null || bs2 == null) return addXStr("IDENTICAL"); stddev = eval.getSmilesCorrelation(bs1, bs2, smiles1, null, null, null, - null, false, false); + null, false, false, null); return addXStr(stddev < 0.2f ? "IDENTICAL" : "IDENTICAL or CONFORMATIONAL ISOMERS (RMSD=" + stddev + ")"); } else if (isSmiles) { - ptsA = new JmolList<P3>(); - ptsB = new JmolList<P3>(); + ptsA = new JmolList<P3>(); + ptsB = new JmolList<P3>(); sOpt = SV.sValue(args[2]); boolean isMap = sOpt.equalsIgnoreCase("MAP"); isSmiles = (sOpt.equalsIgnoreCase("SMILES")); @@ -933,18 +967,19 @@ if (sOpt == null) return false; stddev = eval.getSmilesCorrelation(bs1, bs2, sOpt, ptsA, ptsB, m, null, - !isSmiles, isMap); + !isSmiles, isMap, null); if (isMap) { int nAtoms = ptsA.size(); if (nAtoms == 0) return addXStr(""); int nMatch = ptsB.size() / nAtoms; - JmolList<int[][]> ret = new JmolList<int[][]>(); + JmolList<int[][]> ret = new JmolList<int[][]>(); for (int i = 0, pt = 0; i < nMatch; i++) { int[][] a = ArrayUtil.newInt2(nAtoms); ret.addLast(a); for (int j = 0; j < nAtoms; j++, pt++) - a[j] = new int[] { ((Atom)ptsA.get(j)).index, ((Atom)ptsB.get(pt)).index}; + a[j] = new int[] { ((Atom) ptsA.get(j)).index, + ((Atom) ptsB.get(pt)).index }; } return addXList(ret); } @@ -957,6 +992,22 @@ return (isStdDev || Float.isNaN(stddev) ? addXFloat(stddev) : addXM4(m)); } + private static void getTorsions(Atom[] atoms, int[][] bondMap, + float[][] diff, int pt) { + for (int i = bondMap.length; --i >= 0;) { + int[] map = bondMap[i]; + float v = Measure.computeTorsion(atoms[map[0]], atoms[map[1]], + atoms[map[2]], atoms[map[3]], true); + if (pt == 1) { + if (v - diff[i][0] > 180) + v -= 360; + else if (v - diff[i][0] <= -180) + v += 360; + } + diff[i][pt] = v; + } + } + // private boolean evaluateVolume(ScriptVariable[] args) throws ScriptException { // ScriptVariable x1 = getX(); // if (x1.tok != Token.bitset) @@ -1209,7 +1260,7 @@ public P3 ptValue(SV x, boolean allowFloat) throws ScriptException { Object pt; - if (isSyntaxCheck) + if (chk) return new P3(); switch (x.tok) { case T.point3f: @@ -1236,7 +1287,7 @@ } private P4 planeValue(T x) { - if (isSyntaxCheck) + if (chk) return new P4(); switch (x.tok) { case T.point4f: @@ -1386,6 +1437,7 @@ // "CCCC".find("SMARTS", "CC") // "CCCC".find("SMILES", "MF") // {2.1}.find("CCCC",{1.1}) // find pattern "CCCC" in {2.1} with conformation given by {1.1} + // {*}.find("ccCCN","BONDS") SV x1 = getX(); String sFind = SV.sValue(args[0]); @@ -1399,7 +1451,9 @@ int iPt = (isSmiles || isSearch ? 2 : 1); BS bs2 = (iPt < args.length && args[iPt].tok == T.bitset ? (BS) args[iPt++].value : null); - boolean isAll = (args[args.length - 1].tok == T.on); + boolean asBonds = ("bonds".equalsIgnoreCase(SV + .sValue(args[args.length - 1]))); + boolean isAll = (asBonds || args[args.length - 1].tok == T.on); Object ret = null; switch (x1.tok) { case T.string: @@ -1407,12 +1461,12 @@ if (bs2 != null) return false; if (flags.equalsIgnoreCase("mf")) { - ret = viewer.getSmilesMatcher() - .getMolecularFormula(smiles, isSearch); + ret = viewer.getSmilesMatcher().getMolecularFormula(smiles, isSearch); if (ret == null) eval.evalError(viewer.getSmilesMatcher().getLastException(), null); } else { - ret = eval.getSmilesMatches(flags, smiles, null, null, isSearch, !isAll); + ret = eval.getSmilesMatches(flags, smiles, null, null, isSearch, + !isAll); } break; case T.bitset: @@ -1420,16 +1474,24 @@ return addXStr(JmolMolecule.getMolecularFormula( viewer.getModelSet().atoms, (BS) x1.value, false)); if (isSequence) - return addXStr(viewer.getSmiles(-1, -1, (BS) x1.value, true, isAll, isAll, false)); + return addXStr(viewer.getSmiles(-1, -1, (BS) x1.value, true, isAll, + isAll, false)); if (isSmiles || isSearch) sFind = flags; BS bsMatch3D = bs2; - ret = eval.getSmilesMatches(sFind, null, (BS) x1.value, bsMatch3D, !isSmiles, - !isAll); + if (asBonds) { + int[][] map = viewer.getSmilesMatcher().getCorrelationMaps(sFind, + viewer.modelSet.atoms, viewer.getAtomCount(), (BS) x1.value, + !isSmiles, true); + ret = (map.length > 0 ? viewer.getDihedralMap(map[0]) : new int[0]); + } else { + ret = eval.getSmilesMatches(sFind, null, (BS) x1.value, bsMatch3D, + !isSmiles, !isAll); + } break; } if (ret == null) - eval.error(ScriptEvaluator.ERROR_invalidArgument); + eval.error(ScriptEvaluator.ERROR_invalidArgument); return addXObj(ret); } boolean isReverse = (flags.indexOf("v") >= 0); @@ -1452,7 +1514,7 @@ int ipt = 0; int n = 0; Matcher matcher = null; - JmolList<String> v = (asMatch ? new JmolList<String>() : null); + JmolList<String> v = (asMatch ? new JmolList<String>() : null); for (int i = 0; i < list.length; i++) { String what = list[i]; matcher = pattern.matcher(what); @@ -1468,8 +1530,8 @@ } if (!isList) { return (asMatch ? addXStr(v.size() == 1 ? (String) v.get(0) : "") - : isReverse ? addXBool(n == 1) : asMatch ? addXStr(n == 0 ? "" : matcher - .group()) : addXInt(n == 0 ? 0 : matcher.start() + 1)); + : isReverse ? addXBool(n == 1) : asMatch ? addXStr(n == 0 ? "" + : matcher.group()) : addXInt(n == 0 ? 0 : matcher.start() + 1)); } if (n == 1) return addXStr(asMatch ? (String) v.get(0) : list[ipt]); @@ -2341,7 +2403,7 @@ return false; return addXBs(viewer.getBranchBitSet( ((BS) args[2].value).nextSetBit(0), ((BS) args[1].value) - .nextSetBit(0))); + .nextSetBit(0), true)); case T.smiles: case T.substructure: // same as "SMILES" case T.search: @@ -2506,7 +2568,7 @@ if (i == args.length || !(args[i].value instanceof BS)) return false; BS bsA = BSUtil.copy(SV.bsSelectVar(args[i++])); - if (isSyntaxCheck) + if (chk) return addXBs(new BS()); BS bsB = (i < args.length ? BSUtil.copy(SV .bsSelectVar(args[i])) : null); @@ -2719,14 +2781,14 @@ x2 = SV.selectItemVar(x2); if (op.tok == T.minusMinus || op.tok == T.plusPlus) { - if (!isSyntaxCheck && !x2.increment(incrementX)) + if (!chk && !x2.increment(incrementX)) return false; wasX = true; putX(x2); // reverse getX() return true; } if (op.tok == T.opNot) { - if (isSyntaxCheck) + if (chk) return addXBool(true); switch (x2.tok) { case T.point4f: // quaternion @@ -2802,9 +2864,9 @@ } break; case T.boundbox: - return (isSyntaxCheck ? addXStr("x") : getBoundBox(x2)); + return (chk ? addXStr("x") : getBoundBox(x2)); } - if (isSyntaxCheck) + if (chk) return addXStr(SV.sValue(x2)); if (x2.tok == T.string) { Object v = SV @@ -2820,9 +2882,9 @@ // binary: SV x1 = getX(); - if (isSyntaxCheck) { + if (chk) { if (op == T.tokenAndFALSE || op == T.tokenOrTRUE) - isSyntaxCheck = false; + chk = false; return addXVar(SV.newScriptVariableToken(x1)); } switch (op.tok) { @@ -3362,7 +3424,7 @@ throws ScriptException { if (x2.tok != T.bitset) return false; - if (isSyntaxCheck) + if (chk) return addXStr(""); BS bs = SV.bsSelectVar(x2); JmolList<T> tokens; @@ -3397,7 +3459,7 @@ private boolean getBoundBox(SV x2) { if (x2.tok != T.bitset) return false; - if (isSyntaxCheck) + if (chk) return addXStr(""); BoxInfo b = viewer.getBoxInfo(SV.bsSelectVar(x2), 1); P3[] pts = b.getBoundBoxPoints(true); Modified: trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java =================================================================== --- trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/smiles/SmilesMatcher.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -365,8 +365,7 @@ @SuppressWarnings({ "unchecked" }) private Object match(String pattern, JmolNode[] atoms, int atomCount, BS bsSelected, BS bsAromatic, boolean isSmarts, - boolean matchAllAtoms, boolean firstMatchOnly, - int mode) { + boolean matchAllAtoms, boolean firstMatchOnly, int mode) { InvalidSmilesException.setLastError(null); try { SmilesSearch search = SmilesParser.getMolecule(pattern, isSmarts); Modified: trunk/Jmol/src/org/jmol/thread/SpinThread.java =================================================================== --- trunk/Jmol/src/org/jmol/thread/SpinThread.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/thread/SpinThread.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -42,6 +42,7 @@ private final TransformManager transformManager; private float endDegrees; private JmolList<P3> endPositions; + private float[] dihedralList; private float nDegrees; private BS bsAtoms; private boolean isNav; @@ -51,16 +52,24 @@ private boolean haveNotified; private int index; //private boolean navigatingSurface; + private BS[] bsBranches; + private int nmove = 0; + public boolean isGesture() { return isGesture; } - public SpinThread(TransformManager transformManager, Viewer viewer, float endDegrees, JmolList<P3> endPositions, BS bsAtoms, boolean isNav, boolean isGesture) { + public SpinThread(TransformManager transformManager, Viewer viewer, + float endDegrees, JmolList<P3> endPositions, float[] dihedralList, BS bsAtoms, boolean isNav, + boolean isGesture) { super(); setViewer(viewer, "SpinThread"); this.transformManager = transformManager; - this.endDegrees = Math.abs(endDegrees); + this.endDegrees = endDegrees; + this.dihedralList = dihedralList; + if (dihedralList != null) + bsBranches = viewer.getBsBranches(dihedralList); this.endPositions = endPositions; this.bsAtoms = bsAtoms; this.isNav = isNav; @@ -163,7 +172,9 @@ mode = MAIN; break; case FINISH: - if (bsAtoms != null && endPositions != null) { + if (dihedralList != null) { + viewer.setDihedrals(dihedralList, bsBranches, 0F); + } else if (bsAtoms != null && endPositions != null) { // when the standard deviations of the end points was // exact, we know that we want EXACTLY those final positions viewer.setAtomCoords(bsAtoms, T.xyz, endPositions); @@ -180,7 +191,11 @@ } private void doTransform() { - if (isNav) { + if (dihedralList != null) { + float f = 1f / myFps / endDegrees; + viewer.setDihedrals(dihedralList, bsBranches, f); + nDegrees += 1f / myFps; + } else if (isNav) { transformManager.setNavigationOffsetRelative();//navigatingSurface); } else if (transformManager.isSpinInternal || transformManager.isSpinFixed) { Modified: trunk/Jmol/src/org/jmol/util/Measure.java =================================================================== --- trunk/Jmol/src/org/jmol/util/Measure.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/util/Measure.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -458,7 +458,7 @@ P3[] cptsB = getCenterAndPoints(ptsB); float[] retStddev = new float[2]; Quaternion q = calculateQuaternionRotation(new P3[][] { cptsA, - cptsB }, retStddev, false); + cptsB }, retStddev, true); // was false V3 v = V3.newV(cptsB[0]); v.sub(cptsA[0]); m.setMV(q.getMatrix(), v); Modified: trunk/Jmol/src/org/jmol/viewer/ActionManager.java =================================================================== --- trunk/Jmol/src/org/jmol/viewer/ActionManager.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/viewer/ActionManager.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -1870,7 +1870,7 @@ int[] points = new int[nb]; int ni = 0; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1), ni++) { - lengths[ni] = viewer.getBranchBitSet(i, atomIndex).cardinality(); + lengths[ni] = viewer.getBranchBitSet(i, atomIndex, true).cardinality(); points[ni] = i; } for (int j = 0; j < nb - 2; j++) { Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2013-06-14 12:44:40 UTC (rev 18330) @@ -9,8 +9,14 @@ # The quotes above look odd for a parameter file, but they are # important for the JavaScript version of Jmol. -___JmolVersion="13.1.17_dev_2013.06.13" +___JmolVersion="13.1.17_dev_2013.06.14" +bug fix: COMPARE could rotate to less-good fit with SMARTS search +bug fix: draw ARROW ATOM/BOND broken + +new feature: compare({atomset1} {atomset2} "ccCCN" "bonds") +new feature: {1.1}.find("ccCCN", "BONDS") + bug fix: animation MORPH broken for non-PyMOL files -- load trajectory ({0 6}) 1cdr.pdb -- animation MORPH 10 Modified: trunk/Jmol/src/org/jmol/viewer/TransformManager.java =================================================================== --- trunk/Jmol/src/org/jmol/viewer/TransformManager.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/viewer/TransformManager.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -223,7 +223,7 @@ unTransformPoint(pt2, pt2); viewer.setInMotion(false); rotateAboutPointsInternal(null, pt2, pt1, 10 * speed, Float.NaN, false, - true, null, true, null, null); + true, null, true, null, null, null); } final V3 arcBall0 = new V3(); @@ -361,7 +361,7 @@ isSpinInternal = false; isSpinFixed = true; isSpinSelected = (bsAtoms != null); - setSpin(eval, true, endDegrees, null, bsAtoms, false); + setSpin(eval, true, endDegrees, null, null, bsAtoms, false); return false; } float radians = endDegrees * JC.radiansPerDegree; @@ -388,7 +388,7 @@ float endDegrees, boolean isClockwise, boolean isSpin, BS bsAtoms, boolean isGesture, V3 translation, - JmolList<P3> finalPoints) { + JmolList<P3> finalPoints, float[] dihedralList) { // *THE* Viewer INTERNAL frame rotation entry point @@ -401,7 +401,7 @@ isSpin = false; } - if ((translation == null || translation.length() < 0.001) + if (dihedralList == null && (translation == null || translation.length() < 0.001) && (!isSpin || endDegrees == 0 || Float.isNaN(degreesPerSecond) || degreesPerSecond == 0) && (isSpin || endDegrees == 0)) return false; @@ -420,6 +420,7 @@ boolean isSelected = (bsAtoms != null); if (isSpin) { // we need to adjust the degreesPerSecond to match a multiple of the frame rate + if (dihedralList == null) { int nFrames = (int) (Math.abs(endDegrees) / Math.abs(degreesPerSecond) * spinFps + 0.5); if (Float.isNaN(endDegrees)) { @@ -433,7 +434,10 @@ isSpinInternal = true; isSpinFixed = false; isSpinSelected = isSelected; - setSpin(eval, true, endDegrees, finalPoints, bsAtoms, isGesture); + } else { + endDegrees = degreesPerSecond; + } + setSpin(eval, true, endDegrees, finalPoints, dihedralList, bsAtoms, isGesture); return false; } float radians = endDegrees * JC.radiansPerDegree; @@ -1964,15 +1968,16 @@ private SpinThread spinThread; public void setSpinOn() { - setSpin(null, true, Float.MAX_VALUE, null, null, false); + setSpin(null, true, Float.MAX_VALUE, null, null, null, false); } public void setSpinOff() { - setSpin(null, false, Float.MAX_VALUE, null, null, false); + setSpin(null, false, Float.MAX_VALUE, null, null, null, false); } private void setSpin(JmolScriptEvaluator eval, boolean spinOn, - float endDegrees, JmolList<P3> endPositions, BS bsAtoms, + float endDegrees, JmolList<P3> endPositions, float[] dihedralList, + BS bsAtoms, boolean isGesture) { if (navOn && spinOn) setNavOn(false); @@ -1980,7 +1985,7 @@ viewer.getGlobalSettings().setB("_spinning", spinOn); if (spinOn) { if (spinThread == null) { - spinThread = new SpinThread(this, viewer, endDegrees, endPositions, + spinThread = new SpinThread(this, viewer, endDegrees, endPositions, dihedralList, bsAtoms, false, isGesture); spinThread.setEval(eval); if (bsAtoms == null) { @@ -2000,7 +2005,7 @@ return; boolean wasOn = this.navOn; if (navOn && spinOn) - setSpin(null, false, 0, null, null, false); + setSpin(null, false, 0, null, null, null, false); this.navOn = navOn; viewer.getGlobalSettings().setB("_navigating", navOn); if (!navOn) @@ -2011,7 +2016,7 @@ if (navFps == 0) navFps = 10; if (spinThread == null) { - spinThread = new SpinThread(this, viewer, 0, null, null, true, false); + spinThread = new SpinThread(this, viewer, 0, null, null, null, true, false); spinThread.start(); } } else if (wasOn) { Modified: trunk/Jmol/src/org/jmol/viewer/Viewer.java =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Viewer.java 2013-06-14 12:43:25 UTC (rev 18329) +++ trunk/Jmol/src/org/jmol/viewer/Viewer.java 2013-06-14 12:44:40 UTC (rev 18330) @@ -3343,12 +3343,12 @@ return modelSet.getAtomsConnected(min, max, intType, bs); } - public BS getBranchBitSet(int atomIndex, int atomIndexNot) { + public BS getBranchBitSet(int atomIndex, int atomIndexNot, boolean allowCyclic) { if (atomIndex < 0 || atomIndex >= getAtomCount()) return new BS(); return JmolMolecule.getBranchBitSet(modelSet.atoms, atomIndex, getModelUndeletedAtomsBitSet(modelSet.atoms[atomIndex].modelIndex), - null, atomIndexNot, true, true); + null, atomIndexNot, allowCyclic, true); } public int getAtomIndexFromAtomNumber(int atomNumber) { @@ -7938,11 +7938,11 @@ P3 point2, float degreesPerSecond, float endDegrees, boolean isSpin, BS bsSelected, V3 translation, - JmolList<P3> finalPoints) { + JmolList<P3> finalPoints, float[] dihedralList) { // Eval: rotate INTERNAL boolean isOK = transformManager.rotateAboutPointsInternal(eval, point1, point2, degreesPerSecond, endDegrees, false, isSpin, bsSelected, false, - translation, finalPoints); + translation, finalPoints, dihedralList); if (isOK) refresh(-1, "rotateAxisAboutPointsInternal"); return isOK; @@ -7958,7 +7958,7 @@ } transformManager.rotateAboutPointsInternal(null, pt1, pt2, global.pickingSpinRate, Float.MAX_VALUE, isClockwise, true, null, - false, null, null); + false, null, null, null); } public V3 getModelDipole() { @@ -8154,7 +8154,7 @@ statusManager.setStatusAtomMoved(bs); } - void moveAtoms(Matrix3f mNew, Matrix3f matrixRotate, V3 translation, + public void moveAtoms(Matrix3f mNew, Matrix3f matrixRotate, V3 translation, P3 center, boolean isInternal, BS bsAtoms) { // from TransformManager exclusively if (bsAtoms.cardinality() == 0) @@ -8294,7 +8294,7 @@ } if (Measure.computeAngleABC(pt, atom1, atom2, true) > 90 || Measure.computeAngleABC(pt, atom2, atom1, true) > 90) { - bsBranch = getBranchBitSet(atom2.index, atom1.index); + bsBranch = getBranchBitSet(atom2.index, atom1.index, true); } if (bsBranch != null) for (int n = 0, i = atom1.getBonds().length; --i >= 0;) { @@ -8323,7 +8323,7 @@ bs.andNot(selectionManager.getMotionFixedAtoms()); rotateAboutPointsInternal(eval, atom1, atom2, 0, degrees, false, bs, null, - null); + null, null); } public void refreshMeasures(boolean andStopMinimization) { @@ -10036,4 +10036,16 @@ modelSet.setBondParametersBS(modelIndex, i, bsBonds, rad, pymolValence, argb, trans); } + public int[][] getDihedralMap(int[] atoms) { + return modelSet.getDihedralMap(atoms); + } + + public void setDihedrals(float[] dihedralList, BS[] bsBranches, float rate) { + modelSet.setDihedrals(dihedralList, bsBranches, rate); + } + + public BS[] getBsBranches(float[] dihedralList) { + return modelSet.getBsBranches(dihedralList); + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ Jmol-commits mailing list Jmol-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jmol-commits