1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2006-03-05 12:22:08 -0600 (Sun, 05 Mar 2006) $ 4 * $Revision: 4545 $ 5 * 6 * Copyright (C) 2002-2005 The Jmol Development Team 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 25 package org.jmol.scriptext; 26 27 import javajs.util.AU; 28 import javajs.util.Lst; 29 import javajs.util.M4; 30 import javajs.util.Measure; 31 import javajs.util.P3; 32 33 import java.util.Map; 34 35 import org.jmol.api.Interface; 36 import org.jmol.api.SmilesMatcherInterface; 37 import javajs.util.BS; 38 import org.jmol.modelset.Atom; 39 import org.jmol.script.ScriptEval; 40 import org.jmol.script.ScriptException; 41 import org.jmol.util.Logger; 42 import org.jmol.viewer.JC; 43 44 public class SmilesExt { 45 46 private ScriptEval e; 47 SmilesExt()48 public SmilesExt() { 49 // used by Reflection 50 } 51 init(Object se)52 public SmilesExt init(Object se) { 53 e = (ScriptEval) se; 54 return this; 55 } 56 57 ///////////// ScriptMathProcessor extensions /////////// 58 59 /** 60 * The major interface to org.jmol.smiles, this method allows for a wide 61 * variety of correlation functionality. 62 * 63 * @param bsA 64 * @param bsB 65 * @param smiles 66 * @param ptsA 67 * @param ptsB 68 * @param m4 69 * @param vReturn 70 * @param asMap 71 * @param mapSet 72 * @param center 73 * @param bestMap 74 * @param flags 75 * @return standard deviation 76 * @throws ScriptException 77 */ getSmilesCorrelation(BS bsA, BS bsB, String smiles, Lst<P3> ptsA, Lst<P3> ptsB, M4 m4, Lst<BS> vReturn, boolean asMap, int[][] mapSet, P3 center, boolean bestMap, int flags)78 public float getSmilesCorrelation(BS bsA, BS bsB, String smiles, Lst<P3> ptsA, 79 Lst<P3> ptsB, M4 m4, Lst<BS> vReturn, 80 boolean asMap, int[][] mapSet, P3 center, 81 boolean bestMap, int flags) 82 throws ScriptException { 83 84 // middle two: boolean isSmarts,boolean firstMatchOnly, 85 float tolerance = (mapSet == null ? 0.1f : Float.MAX_VALUE); 86 try { 87 if (ptsA == null) { 88 ptsA = new Lst<P3>(); 89 ptsB = new Lst<P3>(); 90 } 91 M4 m = new M4(); 92 P3 c = new P3(); 93 94 Atom[] atoms = e.vwr.ms.at; 95 int ac = e.vwr.ms.ac; 96 SmilesMatcherInterface sm = e.vwr.getSmilesMatcher(); 97 int[][] maps = sm.getCorrelationMaps(smiles, atoms, ac, bsA, 98 flags | JC.SMILES_FIRST_MATCH_ONLY); 99 if (maps == null) 100 e.evalError(sm.getLastException(), null); 101 if (maps.length == 0) 102 return Float.NaN; 103 int[] mapFirst = maps[0]; 104 for (int i = 0; i < mapFirst.length; i++) 105 ptsA.addLast(atoms[mapFirst[i]]); 106 maps = sm.getCorrelationMaps(smiles, atoms, ac, bsB, flags); 107 if (maps == null) 108 e.evalError(sm.getLastException(), null); 109 if (maps.length == 0) 110 return Float.NaN; 111 Logger.info(maps.length + " mappings found"); 112 if (bestMap || !asMap) { 113 float lowestStdDev = Float.MAX_VALUE; 114 int[] mapBest = null; 115 for (int i = 0; i < maps.length; i++) { 116 ptsB.clear(); 117 for (int j = 0; j < maps[i].length; j++) 118 ptsB.addLast(atoms[maps[i][j]]); 119 Interface.getInterface("javajs.util.Eigen", e.vwr, "script"); 120 float stddev = (ptsB.size() == 1 ? 0 121 : Measure.getTransformMatrix4(ptsA, ptsB, m, null)); 122 Logger.info("getSmilesCorrelation stddev=" + stddev); 123 if (vReturn != null) { 124 if (stddev < tolerance) { 125 BS bs = new BS(); 126 for (int j = 0; j < maps[i].length; j++) 127 bs.set(maps[i][j]); 128 vReturn.addLast(bs); 129 } 130 } 131 if (stddev < lowestStdDev) { 132 mapBest = maps[i]; 133 if (m4 != null) 134 m4.setM4(m); 135 if (center != null) 136 center.setT(c); 137 lowestStdDev = stddev; 138 } 139 } 140 if (mapSet != null) { 141 mapSet[0] = mapFirst; 142 mapSet[1] = mapBest; 143 } 144 ptsB.clear(); 145 for (int i = 0; i < mapBest.length; i++) 146 ptsB.addLast(atoms[mapBest[i]]); 147 return lowestStdDev; 148 } 149 // deliver all maps as a list of points 150 for (int i = 0; i < maps.length; i++) 151 for (int j = 0; j < maps[i].length; j++) 152 ptsB.addLast(atoms[maps[i][j]]); 153 } catch (Exception ex) { 154 e.evalError(ex.getMessage(), null); 155 } 156 return 0; 157 } 158 159 /** 160 * @param pattern 161 * e 162 * @param smiles 163 * @param bsSelected 164 * @param bsMatch3D 165 * @param flags 166 * @param asOneBitset 167 * @param firstMatchOnly 168 * @return Object 169 * @throws ScriptException 170 */ getSmilesMatches(String pattern, String smiles, BS bsSelected, BS bsMatch3D, int flags, boolean asOneBitset, boolean firstMatchOnly)171 public Object getSmilesMatches(String pattern, String smiles, BS bsSelected, 172 BS bsMatch3D, int flags, boolean asOneBitset, 173 boolean firstMatchOnly) 174 throws ScriptException { 175 176 // just retrieving the SMILES or bioSMILES string 177 if (pattern.length() == 0 || pattern.endsWith("///") || pattern.equals("H") 178 || pattern.equals("H2") || pattern.equals("top") 179 || pattern.equalsIgnoreCase("NOAROMATIC")) { 180 try { 181 182 return e.vwr.getSmilesOpt(bsSelected, 0, 0, 183 flags | (pattern.equals("H2") ? JC.SMILES_GEN_EXPLICIT_H2_ONLY : 0) 184 | (pattern.equals("H") ? JC.SMILES_GEN_EXPLICIT_H_ALL : 0) 185 | (pattern.equals("top") ? JC.SMILES_GEN_TOPOLOGY : 0) 186 | (pattern.equalsIgnoreCase("NOAROMATIC") 187 ? JC.SMILES_NO_AROMATIC 188 : 0), 189 (pattern.endsWith("///") ? pattern : null)); 190 } catch (Exception ex) { 191 e.evalError(ex.getMessage(), null); 192 } 193 } 194 BS[] b; 195 if (bsMatch3D == null) { 196 // getting a BitSet or BitSet[] from a set of atoms or a pattern. 197 // not for string.find(string....) 198 try { 199 if (smiles == null) { 200 b = e.vwr.getSubstructureSetArray(pattern, bsSelected, flags); 201 } else if (pattern.equals("chirality")) { 202 return e.vwr.calculateChiralityForSmiles(smiles); 203 } else { 204 boolean isSmarts = ((flags 205 & JC.SMILES_TYPE_SMARTS) == JC.SMILES_TYPE_SMARTS); 206 boolean ignoreElements = ((flags 207 & JC.SMILES_GEN_TOPOLOGY) == JC.SMILES_GEN_TOPOLOGY); 208 int[][] map = e.vwr.getSmilesMatcher().find(pattern, smiles, 209 (isSmarts ? JC.SMILES_TYPE_SMARTS : JC.SMILES_TYPE_SMILES) 210 | (firstMatchOnly ? JC.SMILES_FIRST_MATCH_ONLY : 0) 211 | (ignoreElements ? JC.SMILES_GEN_TOPOLOGY : 0)); 212 if (!asOneBitset) 213 return (!firstMatchOnly ? map 214 : map.length == 0 ? new int[0] : map[0]); 215 BS bs = new BS(); 216 for (int j = 0; j < map.length; j++) { 217 int[] a = map[j]; 218 for (int k = a.length; --k >= 0;) 219 if (a[k] >= 0) 220 bs.set(a[k]); 221 } 222 if (!isSmarts) 223 return new int[bs.cardinality()]; 224 int[] iarray = new int[bs.cardinality()]; 225 int pt = 0; 226 for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) 227 iarray[pt++] = i; 228 return iarray; 229 } 230 } catch (Exception ex) { 231 e.evalError(ex.getMessage(), null); 232 return null; 233 } 234 } else { 235 236 // getting a correlation 237 238 Lst<BS> vReturn = new Lst<BS>(); 239 float stddev = getSmilesCorrelation(bsMatch3D, bsSelected, pattern, null, 240 null, null, vReturn, false, null, null, false, flags); 241 if (Float.isNaN(stddev)) 242 return (asOneBitset ? new BS() : new String[] {}); 243 e.showString("RMSD " + stddev + " Angstroms"); 244 b = vReturn.toArray(new BS[vReturn.size()]); 245 } 246 if (asOneBitset) { 247 // sum total of all now, not just first 248 BS bs = new BS(); 249 for (int j = 0; j < b.length; j++) 250 bs.or(b[j]); 251 return bs; 252 } 253 Lst<BS> list = new Lst<BS>(); 254 for (int j = 0; j < b.length; j++) 255 list.addLast(b[j]); 256 return list; 257 } 258 getFlexFitList(BS bs1, BS bs2, String smiles1, boolean isSmarts)259 public float[] getFlexFitList(BS bs1, BS bs2, String smiles1, 260 boolean isSmarts) 261 throws ScriptException { 262 int[][] mapSet = AU.newInt2(2); 263 getSmilesCorrelation(bs1, bs2, smiles1, null, null, null, null, false, 264 mapSet, null, false, 265 isSmarts ? JC.SMILES_TYPE_SMARTS : JC.SMILES_TYPE_SMILES); 266 if (mapSet[0] == null) 267 return null; 268 int[][] bondMap1 = e.vwr.ms.getDihedralMap(mapSet[0]); 269 int[][] bondMap2 = (bondMap1 == null ? null 270 : e.vwr.ms.getDihedralMap(mapSet[1])); 271 if (bondMap2 == null || bondMap2.length != bondMap1.length) 272 return null; 273 float[][] angles = new float[bondMap1.length][3]; 274 Atom[] atoms = e.vwr.ms.at; 275 getTorsions(atoms, bondMap2, angles, 0); 276 getTorsions(atoms, bondMap1, angles, 1); 277 float[] data = new float[bondMap1.length * 6]; 278 for (int i = 0, pt = 0; i < bondMap1.length; i++) { 279 int[] map = bondMap1[i]; 280 data[pt++] = map[0]; 281 data[pt++] = map[1]; 282 data[pt++] = map[2]; 283 data[pt++] = map[3]; 284 data[pt++] = angles[i][0]; 285 data[pt++] = angles[i][1]; 286 } 287 return data; 288 } 289 getTorsions(Atom[] atoms, int[][] bondMap, float[][] diff, int pt)290 private static void getTorsions(Atom[] atoms, int[][] bondMap, float[][] diff, 291 int pt) { 292 for (int i = bondMap.length; --i >= 0;) { 293 int[] map = bondMap[i]; 294 float v = Measure.computeTorsion(atoms[map[0]], atoms[map[1]], 295 atoms[map[2]], atoms[map[3]], true); 296 if (pt == 1) { 297 if (v - diff[i][0] > 180) 298 v -= 360; 299 else if (v - diff[i][0] <= -180) 300 v += 360; 301 } 302 diff[i][pt] = v; 303 } 304 } 305 306 @SuppressWarnings("unchecked") mapPolyhedra(int i1, int i2, boolean isSmiles, M4 m)307 public float mapPolyhedra(int i1, int i2, boolean isSmiles, M4 m) 308 throws ScriptException { 309 Lst<P3> ptsA = new Lst<P3>(); 310 Lst<P3> ptsB = new Lst<P3>(); 311 Object[] data; 312 data = new Object[] { Integer.valueOf(i1), null }; 313 e.getShapePropertyData(JC.SHAPE_POLYHEDRA, "syminfo", data); 314 Map<String, Object> p1 = (Map<String, Object>) data[1]; 315 data[0] = Integer.valueOf(i2); 316 data[1] = null; 317 e.getShapePropertyData(JC.SHAPE_POLYHEDRA, "syminfo", data); 318 Map<String, Object> p2 = (Map<String, Object>) data[1]; 319 if (p1 == null || p2 == null) 320 return Float.NaN; 321 String smiles1 = (String) p1.get("polySmiles"); 322 String smiles2 = (String) p2.get("polySmiles"); 323 int[] map = (int[]) getSmilesMatches(smiles2, smiles1, null, null, 324 isSmiles ? JC.SMILES_TYPE_SMILES 325 : JC.SMILES_GEN_TOPOLOGY | JC.SMILES_TYPE_SMILES, 326 false, true); 327 if (map.length == 0) 328 return Float.NaN; 329 // map new list 330 ptsA.addLast((P3) p1.get("center")); 331 P3[] a = (P3[]) p1.get("vertices"); 332 for (int i = 0, n = a.length; i < n; i++) 333 ptsA.add(a[map[i + 1] - 1]); 334 ptsB.addLast((P3) p2.get("center")); 335 a = (P3[]) p2.get("vertices"); 336 for (int i = 0, n = a.length; i < n; i++) 337 ptsB.add(a[i]); 338 Interface.getInterface("javajs.util.Eigen", e.vwr, "script"); 339 return Measure.getTransformMatrix4(ptsA, ptsB, m, null); 340 } 341 342 } 343