Clazz.declarePackage ("JS"); Clazz.load (["JU.JmolMolecule", "JU.BS", "$.Lst"], "JS.SmilesSearch", ["java.lang.Float", "java.util.Hashtable", "JU.AU", "$.SB", "JS.InvalidSmilesException", "$.SmilesAromatic", "$.SmilesAtom", "$.SmilesBond", "$.SmilesMeasure", "$.SmilesParser", "$.VTemp", "JU.BSUtil", "$.Edge", "$.Logger"], function () { c$ = Clazz.decorateAsClass (function () { this.isSmarts = false; this.top = null; this.pattern = null; this.patternAtoms = null; this.targetAtoms = null; this.targetAtomCount = 0; this.bsSelected = null; this.v = null; this.aromaticOpen = false; this.aromaticStrict = false; this.aromaticPlanar = false; this.aromaticDouble = false; this.noAromatic = false; this.ignoreAtomClass = false; this.ignoreStereochemistry = false; this.invertStereochemistry = false; this.exitFirstMatch = false; this.groupByModel = false; this.setAtropicity = false; this.patternAromatic = false; this.haveTopo = false; this.isTopology = false; this.patternBioSequence = false; this.subSearches = null; this.haveSelected = false; this.haveBondStereochemistry = false; this.stereo = null; this.needRingData = false; this.needAromatic = true; this.needRingMemberships = false; this.nDouble = 0; this.ringDataMax = -2147483648; this.ringSets = null; this.ringCount = 0; this.measures = null; this.flags = 0; this.bsAromatic = null; this.bsAromatic5 = null; this.bsAromatic6 = null; this.atropKeys = null; this.lastChainAtom = null; this.asVector = false; this.getMaps = false; this.isNormalized = false; this.haveComponents = false; this.isSilent = false; this.isRingCheck = false; this.selectedAtomCount = 0; this.ringData = null; this.ringCounts = null; this.ringConnections = null; this.bsFound = null; this.htNested = null; this.nNested = 0; this.nestedBond = null; this.vReturn = null; this.uniqueList = null; this.bsReturn = null; this.bsCheck = null; this.mapUnique = false; this.bsAromaticRings = null; Clazz.instantialize (this, arguments); }, JS, "SmilesSearch", JU.JmolMolecule); Clazz.prepareFields (c$, function () { this.patternAtoms = new Array (16); this.measures = new JU.Lst (); this.bsAromatic = new JU.BS (); this.bsAromatic5 = new JU.BS (); this.bsAromatic6 = new JU.BS (); this.bsFound = new JU.BS (); this.bsReturn = new JU.BS (); }); Clazz.makeConstructor (c$, function () { Clazz.superConstructor (this, JS.SmilesSearch, []); this.top = this; this.v = new JS.VTemp (); }); Clazz.defineMethod (c$, "setTop", function (parent) { while (parent.top !== parent) parent = parent.top; this.top = parent; }, "JS.SmilesSearch"); c$.addFlags = Clazz.defineMethod (c$, "addFlags", function (flags, strFlags) { if (strFlags.indexOf ("OPEN") >= 0) flags |= 5; if (strFlags.indexOf ("BIO") >= 0) flags |= 1048576; if (strFlags.indexOf ("HYDROGEN") >= 0) flags |= 4096; if (strFlags.indexOf ("FIRSTMATCHONLY") >= 0) flags |= 8; if (strFlags.indexOf ("STRICT") >= 0) flags |= 256; if (strFlags.indexOf ("PLANAR") >= 0) flags |= 1024; if (strFlags.indexOf ("NOAROMATIC") >= 0 || strFlags.indexOf ("NONAROMATIC") >= 0) flags |= 16; if (strFlags.indexOf ("AROMATICDOUBLE") >= 0) flags |= 512; if (strFlags.indexOf ("AROMATICDEFINED") >= 0) flags |= 128; if (strFlags.indexOf ("MMFF94") >= 0) flags |= 768; if (strFlags.indexOf ("TOPOLOGY") >= 0) flags |= 8192; if (strFlags.indexOf ("NOATOMCLASS") >= 0) flags |= 2048; if (strFlags.indexOf ("NOSTEREO") >= 0) { flags |= 32; } else if (strFlags.indexOf ("INVERTSTEREO") >= 0) { if ((flags & 64) != 0) flags &= -65; else flags |= 64; }if (strFlags.indexOf ("ATOMCOMMENT") >= 0) flags |= 131072; if (strFlags.indexOf ("GROUPBYMODEL") >= 0) flags |= 67108864; if ((flags & 1048576) == 1048576) { if (strFlags.indexOf ("NOCOMMENT") >= 0) flags |= 34603008; if (strFlags.indexOf ("UNMATCHED") >= 0) flags |= 3145728; if (strFlags.indexOf ("COVALENT") >= 0) flags |= 5242880; if (strFlags.indexOf ("HBOND") >= 0) flags |= 9437184; }return flags; }, "~N,~S"); Clazz.defineMethod (c$, "setFlags", function (flags) { this.flags = flags; this.exitFirstMatch = new Boolean (this.exitFirstMatch | ((flags & 8) == 8)).valueOf (); this.aromaticOpen = ((flags & 5) == 5); this.aromaticDouble = ((flags & 512) == 512); this.aromaticStrict = ((flags & 256) == 256); this.aromaticPlanar = ((flags & 1024) == 1024); this.groupByModel = ((flags & 67108864) == 67108864); this.noAromatic = ((flags & 16) == 16); this.ignoreAtomClass = ((flags & 2048) == 2048); this.ignoreStereochemistry = ((flags & 32) == 32); this.invertStereochemistry = !this.ignoreStereochemistry && ((flags & 64) == 64); }, "~N"); Clazz.defineMethod (c$, "set", function () { if (this.patternAtoms.length > this.ac) this.patternAtoms = JU.AU.arrayCopyObject (this.patternAtoms, this.ac); this.nodes = this.patternAtoms; this.isTopology = true; this.patternAromatic = false; this.patternBioSequence = true; for (var i = this.ac; --i >= 0; ) { var atom = this.patternAtoms[i]; if (this.isTopology && atom.isDefined ()) this.isTopology = false; if (!atom.isBioResidue) this.patternBioSequence = false; if (atom.isAromatic) this.patternAromatic = true; atom.setBondArray (); if (!this.isSmarts && atom.bioType == '\0' && !atom.setHydrogenCount ()) throw new JS.InvalidSmilesException ("unbracketed atoms must be one of: B, C, N, O, P, S, F, Cl, Br, I, *,"); } if (this.haveComponents) { for (var i = this.ac; --i >= 0; ) { var a = this.patternAtoms[i]; var bonds = a.bonds; var ia = a.component; for (var j = a.bondCount; --j >= 0; ) { var b = bonds[j]; var ib; if (b.isConnection && b.atom2 === a && (ib = b.atom1.component) != ia) { for (var k = this.ac; --k >= 0; ) if (this.patternAtoms[k].component == ia) this.patternAtoms[k].component = ib; }} } }}); Clazz.defineMethod (c$, "setSelected", function (bs) { if (bs == null) { bs = JU.BS.newN (this.targetAtomCount); bs.setBits (0, this.targetAtomCount); }this.bsSelected = bs; }, "JU.BS"); Clazz.defineMethod (c$, "addAtom", function () { return this.appendAtom ( new JS.SmilesAtom ()); }); Clazz.defineMethod (c$, "appendAtom", function (sAtom) { if (this.ac >= this.patternAtoms.length) this.patternAtoms = JU.AU.doubleLength (this.patternAtoms); return this.patternAtoms[this.ac] = sAtom.setIndex (this.ac++); }, "JS.SmilesAtom"); Clazz.defineMethod (c$, "addNested", function (pattern) { if (this.htNested == null) this.htNested = new java.util.Hashtable (); this.setNested (++this.nNested, pattern); return this.nNested; }, "~S"); Clazz.defineMethod (c$, "clear", function () { this.bsReturn.clearAll (); this.nNested = 0; this.htNested = null; this.nestedBond = null; this.clearBsFound (-1); }); Clazz.defineMethod (c$, "clearBsFound", function (iAtom) { if (iAtom < 0) { if (this.bsCheck == null) { this.bsFound.clearAll (); }} else this.bsFound.clear (iAtom); }, "~N"); Clazz.defineMethod (c$, "setNested", function (iNested, o) { this.top.htNested.put ("_" + iNested, o); }, "~N,~O"); Clazz.defineMethod (c$, "getNested", function (iNested) { return this.top.htNested.get ("_" + iNested); }, "~N"); Clazz.defineMethod (c$, "getMissingHydrogenCount", function () { var n = 0; var nH; for (var i = 0; i < this.ac; i++) if ((nH = this.patternAtoms[i].explicitHydrogenCount) >= 0) n += nH; return n; }); Clazz.defineMethod (c$, "setRingData", function (bsA, vRings, doProcessAromatic) { if (this.isTopology || this.patternBioSequence) this.needAromatic = false; if (this.needAromatic) this.needRingData = true; var noAromatic = ((this.flags & 16) == 16); this.needAromatic = new Boolean (this.needAromatic & ( new Boolean ((bsA == null) & !noAromatic).valueOf ())).valueOf (); if (!this.needAromatic) { this.bsAromatic.clearAll (); if (bsA != null) this.bsAromatic.or (bsA); if (!this.needRingMemberships && !this.needRingData) return; }this.getRingData (vRings, this.needRingData, doProcessAromatic); }, "JU.BS,~A,~B"); Clazz.defineMethod (c$, "getRingData", function (vRings, needRingData, doTestAromatic) { var isStrict = this.aromaticStrict || !this.aromaticOpen && !this.aromaticPlanar; var isOpenNotStrict = this.aromaticOpen && !this.aromaticStrict; var strictness = (!isStrict ? 0 : (this.flags & 768) == 768 ? 2 : 1); var checkExplicit = (strictness == 0); var isDefined = ((this.flags & 128) == 128); var doFinalize = (this.needAromatic && doTestAromatic && (isStrict || isOpenNotStrict)); var aromaticMax = 7; var lstAromatic = (vRings == null ? new JU.Lst () : (vRings[3] = new JU.Lst ())); var lstSP2 = (doFinalize ? new JU.Lst () : null); var eCounts = (doFinalize ? Clazz.newIntArray (this.targetAtomCount, 0) : null); if (isDefined && this.needAromatic) { JS.SmilesAromatic.checkAromaticDefined (this.targetAtoms, this.bsSelected, this.bsAromatic); strictness = 0; }var nAtoms = this.targetAtomCount; var justCheckBonding = (nAtoms == 0 || (Clazz.instanceOf (this.targetAtoms[0], JS.SmilesAtom))); if (this.ringDataMax < 0) this.ringDataMax = 8; if (strictness > 0 && this.ringDataMax < 6) this.ringDataMax = 6; if (needRingData) { this.ringCounts = Clazz.newIntArray (nAtoms, 0); this.ringConnections = Clazz.newIntArray (this.targetAtomCount, 0); this.ringData = new Array (this.ringDataMax + 1); }this.ringSets = new JU.Lst (); var s = "****"; var max = this.ringDataMax; while (s.length < max) s += s; for (var i = 3; i <= max; i++) { if (i > nAtoms) continue; var smarts = "*1" + s.substring (0, i - 2) + "*1"; var search = JS.SmilesParser.newSearch (smarts, true, true); var vR = this.subsearch (search, 2); if (vRings != null && i <= 5) { var v = new JU.Lst (); for (var j = vR.size (); --j >= 0; ) v.addLast (vR.get (j)); vRings[i - 3] = v; }if (vR.size () == 0) continue; if (this.needAromatic && !isDefined && i >= 4 && i <= aromaticMax) JS.SmilesAromatic.setAromatic (i, this.targetAtoms, this.bsSelected, vR, this.bsAromatic, strictness, isOpenNotStrict, justCheckBonding, checkExplicit, this.v, lstAromatic, lstSP2, eCounts, doTestAromatic); if (needRingData) { this.ringData[i] = new JU.BS (); for (var k = vR.size (); --k >= 0; ) { var r = vR.get (k); this.ringData[i].or (r); for (var j = r.nextSetBit (0); j >= 0; j = r.nextSetBit (j + 1)) this.ringCounts[j]++; } }} if (this.needAromatic) { if (doFinalize) JS.SmilesAromatic.finalizeAromatic (this.targetAtoms, this.bsAromatic, lstAromatic, lstSP2, eCounts, isOpenNotStrict, isStrict); this.bsAromatic5.clearAll (); this.bsAromatic6.clearAll (); for (var i = lstAromatic.size (); --i >= 0; ) { var bs = lstAromatic.get (i); bs.and (this.bsAromatic); switch (bs.cardinality ()) { case 5: this.bsAromatic5.or (bs); break; case 6: this.bsAromatic6.or (bs); break; } } }if (needRingData) { for (var i = this.bsSelected.nextSetBit (0); i >= 0; i = this.bsSelected.nextSetBit (i + 1)) { var atom = this.targetAtoms[i]; var bonds = atom.getEdges (); if (bonds != null) for (var k = bonds.length; --k >= 0; ) if (this.ringCounts[atom.getBondedAtomIndex (k)] > 0) this.ringConnections[i]++; } }}, "~A,~B,~B"); Clazz.defineMethod (c$, "subsearch", function (search, submode) { search.ringSets = this.ringSets; search.mapUnique = this.mapUnique; search.targetAtoms = this.targetAtoms; search.targetAtomCount = this.targetAtomCount; search.bsSelected = this.bsSelected; search.htNested = this.htNested; search.haveTopo = this.haveTopo; search.bsCheck = this.bsCheck; search.isSmarts = true; search.bsAromatic = this.bsAromatic; search.bsAromatic5 = this.bsAromatic5; search.bsAromatic6 = this.bsAromatic6; search.ringData = this.ringData; search.ringCounts = this.ringCounts; search.ringConnections = this.ringConnections; switch (submode) { case 1: search.exitFirstMatch = false; break; case 2: search.isRingCheck = true; search.isSilent = true; search.asVector = true; break; case 3: search.ignoreAtomClass = this.ignoreAtomClass; search.aromaticDouble = this.aromaticDouble; search.haveSelected = this.haveSelected; search.exitFirstMatch = this.exitFirstMatch; search.getMaps = this.getMaps; search.asVector = this.asVector; search.vReturn = this.vReturn; search.bsReturn = this.bsReturn; search.haveBondStereochemistry = this.haveBondStereochemistry; break; } return search.search2 (submode == 1); }, "JS.SmilesSearch,~N"); Clazz.defineMethod (c$, "search", function () { return this.search2 (false); }); Clazz.defineMethod (c$, "search2", function (firstAtomOnly) { this.setFlags (this.flags); if (!this.isRingCheck && JU.Logger.debugging && !this.isSilent) JU.Logger.debug ("SmilesSearch processing " + this.pattern); if (this.vReturn == null && (this.asVector || this.getMaps)) this.vReturn = new JU.Lst (); if (this.bsSelected == null) { this.bsSelected = JU.BS.newN (this.targetAtomCount); this.bsSelected.setBits (0, this.targetAtomCount); }this.selectedAtomCount = this.bsSelected.cardinality (); if (this.subSearches != null) { for (var i = 0; i < this.subSearches.length; i++) { if (this.subSearches[i] == null) continue; this.subsearch (this.subSearches[i], 3); if (this.exitFirstMatch) { if (this.vReturn == null ? this.bsReturn.nextSetBit (0) >= 0 : this.vReturn.size () > 0) break; }} } else if (this.ac > 0) { if (this.nestedBond == null) { this.clearBsFound (-1); } else { this.bsReturn.clearAll (); }this.nextPatternAtom (-1, -1, firstAtomOnly, -1); }return (this.asVector || this.getMaps ? this.vReturn : this.bsReturn); }, "~B"); Clazz.defineMethod (c$, "nextPatternAtom", function (atomNum, iAtom, firstAtomOnly, c) { var jmolAtom; var jmolBonds; if (++atomNum < this.ac) { var newPatternAtom = this.patternAtoms[atomNum]; var newPatternBond = (iAtom >= 0 ? newPatternAtom.getBondTo (null) : atomNum == 0 ? this.nestedBond : null); if (newPatternBond == null) { var bs = JU.BSUtil.copy (this.bsFound); var bs0 = JU.BSUtil.copy (this.bsFound); if (newPatternAtom.notBondedIndex >= 0) { var pa = this.patternAtoms[newPatternAtom.notBondedIndex]; var a = pa.getMatchingAtom (); if (pa.isBioAtom) { var ii = a.getOffsetResidueAtom ("\0", 1); if (ii >= 0) bs.set (ii); ii = a.getOffsetResidueAtom ("\0", -1); if (ii >= 0) bs.set (ii); } else { jmolBonds = a.getEdges (); for (var k = 0; k < jmolBonds.length; k++) bs.set (jmolBonds[k].getOtherNode (a).getIndex ()); }}var skipGroup = ((newPatternAtom.isBioAtomWild)); var j1 = this.bsSelected.nextSetBit (0); j1 = (skipGroup && j1 >= 0 ? this.targetAtoms[j1].getOffsetResidueAtom ("\0", j1) : j1); var oldJmolComponent; var oldPatternComponent = (atomNum > 0 ? this.patternAtoms[atomNum - 1] : newPatternAtom).component; var thisPatternComponent = newPatternAtom.component; var checkComponents = this.haveComponents && thisPatternComponent != -2147483648; for (var j = j1; j >= 0; j = this.bsSelected.nextSetBit (j + 1)) { if (!bs.get (j) && !this.bsFound.get (j)) { jmolAtom = this.targetAtoms[j]; if (checkComponents && !this.isRingCheck) { c = (this.groupByModel ? jmolAtom.getModelIndex () : jmolAtom.getMoleculeNumber (false)); oldJmolComponent = (atomNum > 0 ? this.patternAtoms[atomNum - 1].matchingComponent : c); if ((oldPatternComponent == thisPatternComponent) != (oldJmolComponent == c)) continue; }if (!this.nextTargetAtom (newPatternAtom, jmolAtom, atomNum, j, firstAtomOnly, c)) return false; }if (skipGroup) { j1 = this.targetAtoms[j].getOffsetResidueAtom (newPatternAtom.bioAtomName, 1); if (j1 >= 0) j = j1 - 1; }} this.bsFound = bs0; return true; }jmolAtom = newPatternBond.atom1.getMatchingAtom (); switch (newPatternBond.order) { case 96: var nextGroupAtom = jmolAtom.getOffsetResidueAtom (newPatternAtom.bioAtomName, 1); if (nextGroupAtom >= 0) { var bs = JU.BSUtil.copy (this.bsFound); jmolAtom.getGroupBits (this.bsFound); if (this.doCheckAtom (nextGroupAtom) && !this.nextTargetAtom (newPatternAtom, this.targetAtoms[nextGroupAtom], atomNum, nextGroupAtom, firstAtomOnly, c)) return false; this.bsFound = bs; }return true; case 112: var vLinks = new JU.Lst (); jmolAtom.getCrossLinkVector (vLinks, true, true); var bs = JU.BSUtil.copy (this.bsFound); jmolAtom.getGroupBits (this.bsFound); for (var j = 2; j < vLinks.size (); j += 3) { var ia = vLinks.get (j).intValue (); if (this.doCheckAtom (ia) && !this.nextTargetAtom (newPatternAtom, this.targetAtoms[ia], atomNum, ia, firstAtomOnly, c)) return false; } this.bsFound = bs; return true; } jmolBonds = jmolAtom.getEdges (); if (jmolBonds != null) for (var j = 0; j < jmolBonds.length; j++) { var ia = jmolAtom.getBondedAtomIndex (j); if (this.doCheckAtom (ia) && !this.nextTargetAtom (newPatternAtom, this.targetAtoms[ia], atomNum, ia, firstAtomOnly, c)) return false; } this.clearBsFound (iAtom); return true; }if (!this.ignoreStereochemistry && !this.isRingCheck && !this.checkStereochemistry ()) return true; var bs = new JU.BS (); var nMatch = 0; for (var j = 0; j < this.ac; j++) { var i = this.patternAtoms[j].getMatchingAtomIndex (); if (!firstAtomOnly && this.top.haveSelected && !this.patternAtoms[j].selected) continue; nMatch++; bs.set (i); if (this.patternAtoms[j].isBioAtomWild) this.targetAtoms[i].getGroupBits (bs); if (firstAtomOnly) break; if (!this.isSmarts) if (!this.setAtropicity && this.patternAtoms[j].explicitHydrogenCount > 0) { var atom = this.targetAtoms[i]; for (var k = 0, n = atom.getEdges ().length; k < n; k++) { var ia = atom.getBondedAtomIndex (k); if (this.targetAtoms[ia].getElementNumber () == 1) bs.set (ia); } }} if (!this.isSmarts && bs.cardinality () != this.selectedAtomCount) return true; if (this.bsCheck != null) { if (firstAtomOnly) { this.bsCheck.clearAll (); for (var j = 0; j < this.ac; j++) { this.bsCheck.set (this.patternAtoms[j].getMatchingAtomIndex ()); } if (this.bsCheck.cardinality () != this.ac) return true; } else { if (bs.cardinality () != this.ac) return true; }}this.bsReturn.or (bs); if (this.getMaps) { if (this.mapUnique) { if (this.uniqueList == null) this.uniqueList = new JU.Lst (); for (var j = this.uniqueList.size (); --j >= 0; ) if (this.uniqueList.get (j).equals (bs)) return true; this.uniqueList.addLast (bs); }var map = Clazz.newIntArray (nMatch, 0); for (var j = 0, nn = 0; j < this.ac; j++) { if (!firstAtomOnly && this.top.haveSelected && !this.patternAtoms[j].selected) continue; map[nn++] = this.patternAtoms[j].getMatchingAtomIndex (); } this.vReturn.addLast (map); return !this.exitFirstMatch; }if (this.asVector) { var isOK = true; for (var j = this.vReturn.size (); --j >= 0 && isOK; ) isOK = !((this.vReturn.get (j)).equals (bs)); if (!isOK) return true; this.vReturn.addLast (bs); }if (this.isRingCheck) { var bsRing = new JU.BS (); for (var k = atomNum * 3 + 2; --k > atomNum; ) bsRing.set (this.patternAtoms[(k <= atomNum * 2 ? atomNum * 2 - k + 1 : k - 1) % atomNum].getMatchingAtomIndex ()); this.ringSets.addLast (bsRing); return true; }if (this.exitFirstMatch) return false; return (bs.cardinality () != this.selectedAtomCount); }, "~N,~N,~B,~N"); Clazz.defineMethod (c$, "doCheckAtom", function (j) { return this.bsSelected.get (j) && !this.bsFound.get (j); }, "~N"); Clazz.defineMethod (c$, "nextTargetAtom", function (patternAtom, jmolAtom, atomNum, iAtom, firstAtomOnly, c) { var jmolBonds; if (!this.isRingCheck && !this.isTopology) { if (patternAtom.subAtoms == null) { if (!this.checkPrimitiveAtom (patternAtom, iAtom)) return true; } else if (patternAtom.isAND) { for (var i = 0; i < patternAtom.nSubAtoms; i++) if (!this.checkPrimitiveAtom (patternAtom.subAtoms[i], iAtom)) return true; } else { for (var i = 0; i < patternAtom.nSubAtoms; i++) if (!this.nextTargetAtom (patternAtom.subAtoms[i], jmolAtom, atomNum, iAtom, firstAtomOnly, c)) return false; return true; }}jmolBonds = jmolAtom.getEdges (); for (var i = patternAtom.getBondCount (); --i >= 0; ) { var patternBond = patternAtom.getBond (i); if (patternBond.getAtomIndex2 () != patternAtom.index) continue; var atom1 = patternBond.atom1; var matchingAtom = atom1.getMatchingAtomIndex (); switch (patternBond.order) { case 96: case 112: if (!this.checkMatchBond (patternAtom, atom1, patternBond, iAtom, matchingAtom, null)) return true; break; default: var k = 0; var jmolBond = null; for (; k < jmolBonds.length; k++) if ((jmolBond = jmolBonds[k]).isCovalent () && (jmolBond.getAtomIndex1 () == matchingAtom || jmolBond.getAtomIndex2 () == matchingAtom)) break; if (k == jmolBonds.length) return true; if (!this.checkMatchBond (patternAtom, atom1, patternBond, iAtom, matchingAtom, jmolBond)) return true; } } patternAtom = this.patternAtoms[patternAtom.index]; patternAtom.setMatchingAtom (this.targetAtoms[iAtom], iAtom); patternAtom.matchingComponent = c; if (JU.Logger.debuggingHigh && !this.isRingCheck) { for (var i = 0; i <= atomNum; i++) JU.Logger.debug ("pattern atoms " + this.patternAtoms[i] + " " + this.patternAtoms[i].matchingComponent); JU.Logger.debug ("--ss--"); }this.bsFound.set (iAtom); if (!this.nextPatternAtom (atomNum, iAtom, firstAtomOnly, c)) return false; if (iAtom >= 0) this.clearBsFound (iAtom); return true; }, "JS.SmilesAtom,JU.Node,~N,~N,~B,~N"); Clazz.defineMethod (c$, "checkPrimitiveAtom", function (patternAtom, iTarget) { if (patternAtom.nSubAtoms > 0) { for (var i = 0; i < patternAtom.nSubAtoms; i++) if (this.checkPrimitiveAtom (patternAtom.subAtoms[i], iTarget)) return true; return false; }var targetAtom = this.targetAtoms[iTarget]; var foundAtom = patternAtom.not; while (true) { if (patternAtom.iNested > 0) { var o = this.getNested (patternAtom.iNested); if (Clazz.instanceOf (o, JS.SmilesSearch)) { var search = o; if (patternAtom.isBioAtom) search.nestedBond = patternAtom.getBondTo (null); o = this.subsearch (search, 1); if (o == null) o = new JU.BS (); if (!patternAtom.isBioAtom) this.setNested (patternAtom.iNested, o); }foundAtom = (patternAtom.not != ((o).get (iTarget))); break; }var na = targetAtom.getElementNumber (); var n = patternAtom.elementNumber; if (na >= 0 && n >= 0 && n != na) break; if (patternAtom.isBioResidue) { var a = targetAtom; if (patternAtom.bioAtomName != null && (patternAtom.isLeadAtom () ? !a.isLeadAtom () : !patternAtom.bioAtomName.equals (a.getAtomName ().toUpperCase ()))) break; if (patternAtom.residueName != null && !patternAtom.residueName.equals (a.getGroup3 (false).toUpperCase ())) break; if (patternAtom.residueNumber != -2147483648 && patternAtom.residueNumber != a.getResno ()) break; if (patternAtom.insCode != '\0' && patternAtom.insCode != a.getInsertionCode ()) break; if (patternAtom.residueChar != null || patternAtom.elementNumber == -2) { var atype = a.getBioSmilesType (); var ptype = patternAtom.getBioSmilesType (); var ok = true; var isNucleic = false; switch (ptype) { case '\0': case '*': ok = true; break; case 'n': ok = (atype == 'r' || atype == 'c'); isNucleic = true; break; case 'r': case 'c': isNucleic = true; default: ok = (atype == ptype); break; } if (!ok) break; var s = a.getGroup1 ('\0').toUpperCase (); var resChar = (patternAtom.residueChar == null ? '*' : patternAtom.residueChar.charAt (0)); var isOK = (resChar == s.charAt (0)); switch (resChar) { case '*': isOK = true; break; case 'N': isOK = isNucleic ? (atype == 'r' || atype == 'c') : isOK; break; case 'R': isOK = isNucleic ? a.isPurine () : isOK; break; case 'Y': isOK = isNucleic ? a.isPyrimidine () : isOK; break; } if (!isOK) break; }if (patternAtom.isBioAtom) { if (patternAtom.notCrossLinked && a.getCrossLinkVector (null, true, true)) break; }} else { if (patternAtom.atomNumber != -2147483648 && patternAtom.atomNumber != targetAtom.getAtomNumber ()) break; if (patternAtom.jmolIndex >= 0 && targetAtom.getIndex () != patternAtom.jmolIndex) break; if (patternAtom.atomType != null && !patternAtom.atomType.equals (targetAtom.getAtomType ())) break; if ((n = patternAtom.getAtomicMass ()) != -2147483648 && (n >= 0 && n != (na = targetAtom.getIsotopeNumber ()) || n < 0 && na != 0 && -n != na)) break; if (!this.noAromatic && !patternAtom.aromaticAmbiguous && patternAtom.isAromatic != this.bsAromatic.get (iTarget)) break; if ((n = patternAtom.getCharge ()) != -2147483648 && n != targetAtom.getFormalCharge ()) break; n = patternAtom.getCovalentHydrogenCount () + patternAtom.explicitHydrogenCount; if (n >= 0 && n != targetAtom.getTotalHydrogenCount ()) break; if ((n = patternAtom.implicitHydrogenCount) != -2147483648) { na = targetAtom.getImplicitHydrogenCount (); if (n == -1 ? na == 0 : n != na) break; }if (patternAtom.degree > 0 && patternAtom.degree != targetAtom.getCovalentBondCount () - targetAtom.getImplicitHydrogenCount ()) break; if (patternAtom.nonhydrogenDegree > 0 && patternAtom.nonhydrogenDegree != targetAtom.getCovalentBondCount () - targetAtom.getCovalentHydrogenCount ()) break; if (this.isSmarts && patternAtom.valence > 0 && patternAtom.valence != targetAtom.getTotalValence ()) break; if (patternAtom.connectivity > 0 && patternAtom.connectivity != targetAtom.getCovalentBondCountPlusMissingH ()) break; if (patternAtom.atomNumber != -2147483648 && patternAtom.atomNumber != targetAtom.getAtomNumber ()) break; if (patternAtom.jmolIndex >= 0 && targetAtom.getIndex () != patternAtom.jmolIndex) break; if (patternAtom.atomType != null && !patternAtom.atomType.equals (targetAtom.getAtomType ())) break; if (!this.ignoreAtomClass || this.isSmarts) { if (!Float.isNaN (patternAtom.atomClass) && patternAtom.atomClass != targetAtom.getFloatProperty ("property_atomclass")) break; }if (this.ringData != null) { if (patternAtom.ringSize >= -1) { if (patternAtom.ringSize <= 0) { if ((this.ringCounts[iTarget] == 0) != (patternAtom.ringSize == 0)) break; } else { var rd = this.ringData[patternAtom.ringSize == 500 ? 5 : patternAtom.ringSize == 600 ? 6 : patternAtom.ringSize]; if (rd == null || !rd.get (iTarget)) break; if (!this.noAromatic) if (patternAtom.ringSize == 500) { if (!this.bsAromatic5.get (iTarget)) break; } else if (patternAtom.ringSize == 600) { if (!this.bsAromatic6.get (iTarget)) break; }}}if (patternAtom.ringMembership >= -1) { if (patternAtom.ringMembership == -1 ? this.ringCounts[iTarget] == 0 : this.ringCounts[iTarget] != patternAtom.ringMembership) break; }if (patternAtom.ringConnectivity >= 0) { n = this.ringConnections[iTarget]; if (patternAtom.ringConnectivity == -1 && n == 0 || patternAtom.ringConnectivity != -1 && n != patternAtom.ringConnectivity) break; }}}foundAtom = !foundAtom; break; } return foundAtom; }, "JS.SmilesAtom,~N"); Clazz.defineMethod (c$, "checkMatchBond", function (patternAtom, atom1, patternBond, iAtom, matchingAtom, bond) { if (patternBond.bondsOr != null) { for (var ii = 0; ii < patternBond.nBondsOr; ii++) if (this.checkMatchBond (patternAtom, atom1, patternBond.bondsOr[ii], iAtom, matchingAtom, bond)) return true; return false; }if (!this.isRingCheck && !this.isTopology) if (patternBond.nPrimitives == 0) { if (!this.checkPrimitiveBond (patternBond, iAtom, matchingAtom, bond)) return false; } else { for (var i = 0; i < patternBond.nPrimitives; i++) { var prim = patternBond.setPrimitive (i); if (!this.checkPrimitiveBond (prim, iAtom, matchingAtom, bond)) return false; } }patternBond.matchingBond = bond; return true; }, "JS.SmilesAtom,JS.SmilesAtom,JS.SmilesBond,~N,~N,JU.Edge"); Clazz.defineMethod (c$, "checkPrimitiveBond", function (patternBond, iAtom1, iAtom2, bond) { var bondFound = false; switch (patternBond.order) { case 96: return (patternBond.isNot != (this.targetAtoms[iAtom2].getOffsetResidueAtom ("\0", 1) == this.targetAtoms[iAtom1].getOffsetResidueAtom ("\0", 0))); case 112: return (patternBond.isNot != this.targetAtoms[iAtom1].isCrossLinked (this.targetAtoms[iAtom2])); } var isAromatic1 = (!this.noAromatic && this.bsAromatic.get (iAtom1)); var isAromatic2 = (!this.noAromatic && this.bsAromatic.get (iAtom2)); var order = bond.getCovalentOrder (); var patternOrder = patternBond.order; if (isAromatic1 && isAromatic2) { switch (patternOrder) { case 17: case 65: bondFound = JS.SmilesSearch.isRingBond (this.ringSets, null, iAtom1, iAtom2); break; case 1: bondFound = !this.isSmarts || !JS.SmilesSearch.isRingBond (this.ringSets, this.getBSAromaticRings (), iAtom1, iAtom2); break; case 2: bondFound = this.isNormalized || this.aromaticDouble && (order == 2 || order == 514); break; case 65537: case 65538: bondFound = !patternBond.isNot; break; case 81: case -1: bondFound = true; break; } } else { switch (patternOrder) { case 17: if (!this.noAromatic) break; case 81: case -1: bondFound = true; break; case 1: case 1025: case 1041: switch (order) { case 1: case 1025: case 1041: bondFound = true; break; } break; case 65537: case 65538: switch (order) { case 1: case 65537: case 65538: bondFound = !patternBond.isNot; break; } break; case 2: case 3: case 4: bondFound = (order == patternOrder); break; case 65: bondFound = JS.SmilesSearch.isRingBond (this.ringSets, null, iAtom1, iAtom2); break; } }return bondFound != patternBond.isNot; }, "JS.SmilesBond,~N,~N,JU.Edge"); Clazz.defineMethod (c$, "getBSAromaticRings", function () { if (this.bsAromaticRings == null) { this.bsAromaticRings = new JU.BS (); if (this.ringSets != null && this.bsAromatic != null) { for (var i = this.ringSets.size (); --i >= 0; ) { var bsRing = this.ringSets.get (i).clone (); bsRing.andNot (this.bsAromatic); if (bsRing.isEmpty ()) this.bsAromaticRings.set (i); } }}return this.bsAromaticRings; }); c$.isRingBond = Clazz.defineMethod (c$, "isRingBond", function (ringSets, bsAromaticRings, a1, a2) { if (ringSets != null) for (var i = ringSets.size (); --i >= 0; ) { var bsRing = ringSets.get (i); if (bsRing.get (a1) && bsRing.get (a2)) { if (bsAromaticRings == null || bsAromaticRings.get (i)) return true; }} return false; }, "JU.Lst,JU.BS,~N,~N"); Clazz.defineMethod (c$, "checkStereochemistry", function () { for (var i = 0; i < this.measures.size (); i++) if (!this.measures.get (i).check ()) return false; if (this.stereo != null && !this.stereo.checkStereoChemistry (this, this.v)) return false; if (!this.haveBondStereochemistry) return true; var lstAtrop = null; var b = null; for (var k = 0; k < this.ac; k++) { var sAtom1 = this.patternAtoms[k]; var sAtom2 = null; var sAtomDirected1 = null; var sAtomDirected2 = null; var dir1 = 0; var dir2 = 0; var bondType = 0; var nBonds = sAtom1.getBondCount (); var isAtropisomer = false; var indexOrder = true; for (var j = 0; j < nBonds; j++) { b = sAtom1.getBond (j); var isAtom2 = (b.atom2 === sAtom1); indexOrder = (b.atom1.index < b.atom2.index); var type = b.order; switch (type) { case 65537: case 65538: if (!indexOrder) continue; case 2: if (isAtom2) continue; sAtom2 = b.atom2; bondType = type; isAtropisomer = (type != 2); if (isAtropisomer) dir1 = (b.isNot ? -1 : 1); break; case 1025: case 1041: sAtomDirected1 = (isAtom2 ? b.atom1 : b.atom2); dir1 = (isAtom2 != (type == 1025) ? 1 : -1); break; } } if (isAtropisomer) { if (this.setAtropicity) { if (lstAtrop == null) lstAtrop = new JU.Lst (); lstAtrop.addLast (b); continue; }var b1 = sAtom1.getBond (b.atropType[0]); if (b1 == null) return false; sAtomDirected1 = b1.getOtherAtom (sAtom1); b1 = sAtom2.getBond (b.atropType[1]); if (b1 == null) return false; sAtomDirected2 = b1.getOtherAtom (sAtom2); if (JU.Logger.debugging) JU.Logger.info ("atropisomer check for atoms " + sAtomDirected1 + sAtom1 + " " + sAtom2 + sAtomDirected2); } else { if (sAtom2 == null || dir1 == 0) continue; var a10 = sAtom1; var nCumulene = 0; while (sAtom2.getBondCount () == 2 && sAtom2.getValence () == 4) { nCumulene++; var e2 = sAtom2.getEdges (); var e = e2[e2[0].getOtherNode (sAtom2) === a10 ? 1 : 0]; a10 = sAtom2; sAtom2 = e.getOtherNode (sAtom2); } if (nCumulene % 2 == 1) continue; nBonds = sAtom2.getBondCount (); for (var j = 0; j < nBonds && dir2 == 0; j++) { b = sAtom2.getBond (j); var type = b.order; switch (type) { case 1025: case 1041: var isAtom2 = (b.atom2 === sAtom2); sAtomDirected2 = (isAtom2 ? b.atom1 : b.atom2); dir2 = (isAtom2 != (type == 1025) ? 1 : -1); break; } } if (dir2 == 0) continue; }var dbAtom1 = sAtom1.getMatchingAtom (); var dbAtom2 = sAtom2.getMatchingAtom (); var dbAtom1a = sAtomDirected1.getMatchingAtom (); var dbAtom2a = sAtomDirected2.getMatchingAtom (); if (dbAtom1a == null || dbAtom2a == null) return false; if (this.haveTopo) this.setTopoCoordinates (dbAtom1, dbAtom2, dbAtom1a, dbAtom2a, bondType); var d = JS.SmilesMeasure.setTorsionData (dbAtom1a, dbAtom1, dbAtom2, dbAtom2a, this.v, isAtropisomer); if (isAtropisomer) { d *= dir1 * (bondType == 65537 ? 1 : -1) * (indexOrder ? 1 : -1); if (JU.Logger.debugging) JU.Logger.info ("atrop dihedral " + d + " " + sAtom1 + " " + sAtom2 + " " + b); if (d < 1.0) return false; } else { if (this.v.vTemp1.dot (this.v.vTemp2) * dir1 * dir2 < 0) return false; }} if (this.setAtropicity) { this.atropKeys = ""; for (var i = 0; i < lstAtrop.size (); i++) this.atropKeys += "," + this.getAtropIndex ((b = lstAtrop.get (i)), true) + this.getAtropIndex (b, false); }return true; }); Clazz.defineMethod (c$, "getAtropIndex", function (b, isFirst) { var s1 = (isFirst ? b.atom1 : b.atom2); var a1 = s1.getMatchingAtom (); var a11 = JU.Edge.getAtropismNode (b.matchingBond.order, a1, isFirst); var b1 = s1.bonds; for (var i = s1.getBondCount (); --i >= 0; ) if ((b1[i].getOtherNode (s1)).getMatchingAtom () === a11) return i + 1; return 0; }, "JS.SmilesBond,~B"); Clazz.defineMethod (c$, "setTopoCoordinates", function (dbAtom1, dbAtom2, dbAtom1a, dbAtom2a, bondType) { dbAtom1.set (-1, 0, 0); dbAtom2.set (1, 0, 0); if (bondType != 2) { var bond = dbAtom1.getBondTo (dbAtom2); var dir = (bond.order == 65537 ? 1 : -1); dbAtom1a.set (-1, 1, 0); dbAtom2a.set (1, 1, dir / 2.0); return; }var nBonds = 0; var dir1 = 0; var bonds = dbAtom1.getEdges (); for (var k = bonds.length; --k >= 0; ) { var bond = bonds[k]; if (bond.order == 2) continue; var atom = bond.getOtherNode (dbAtom1); (atom).set (-1, (nBonds++ == 0) ? -1 : 1, 0); var mode = (bond.getAtomIndex2 () == dbAtom1.getIndex () ? nBonds : -nBonds); switch (bond.order) { case 1025: dir1 = mode; break; case 1041: dir1 = -mode; } } var dir2 = 0; nBonds = 0; var atoms = new Array (2); bonds = dbAtom2.getEdges (); for (var k = bonds.length; --k >= 0; ) { var bond = bonds[k]; if (bond.order == 2) continue; var atom = bond.getOtherNode (dbAtom2); atoms[nBonds] = atom; (atom).set (1, (nBonds++ == 0) ? 1 : -1, 0); var mode = (bond.getAtomIndex2 () == dbAtom2.getIndex () ? nBonds : -nBonds); switch (bond.order) { case 1025: dir2 = mode; break; case 1041: dir2 = -mode; } } if ((dir1 * dir2 > 0) == (Math.abs (dir1) % 2 == Math.abs (dir2) % 2)) { var y = (atoms[0]).y; (atoms[0]).y = (atoms[1]).y; (atoms[1]).y = y; }}, "JS.SmilesAtom,JS.SmilesAtom,JS.SmilesAtom,JS.SmilesAtom,~N"); Clazz.defineMethod (c$, "createTopoMap", function (bsAro) { var isForMF = (bsAro == null); var nAtomsMissing = this.getMissingHydrogenCount (); var totalAtoms = this.ac + nAtomsMissing; var atoms = new Array (totalAtoms); this.targetAtoms = atoms; for (var i = 0, ptAtom = 0; i < this.ac; i++, ptAtom++) { var sAtom = this.patternAtoms[i]; var n = sAtom.explicitHydrogenCount; if (n < 0) n = 0; var atom = atoms[ptAtom] = new JS.SmilesAtom ().setTopoAtom (sAtom.component, ptAtom, sAtom.symbol, sAtom.getCharge (), i); atom.implicitHydrogenCount = n; if (isForMF) continue; atom.mapIndex = i; atom.stereo = sAtom.stereo; atom.setAtomicMass (sAtom.getAtomicMass ()); atom.bioAtomName = sAtom.bioAtomName; atom.residueName = sAtom.residueName; atom.residueChar = sAtom.residueChar; atom.residueNumber = sAtom.residueNumber; atom.atomNumber = sAtom.residueNumber; atom.insCode = sAtom.insCode; atom.atomClass = sAtom.atomClass; atom.explicitHydrogenCount = 0; atom.isBioAtom = sAtom.isBioAtom; atom.bioType = sAtom.bioType; atom.$isLeadAtom = sAtom.$isLeadAtom; if (!isForMF && sAtom.isAromatic) bsAro.set (ptAtom); sAtom.setMatchingAtom (null, ptAtom); var bonds = new Array (sAtom.getBondCount () + n); atom.setBonds (bonds); while (--n >= 0) { var atomH = atoms[++ptAtom] = new JS.SmilesAtom ().setTopoAtom (atom.component, ptAtom, "H", 0, -1); atomH.mapIndex = -i - 1; atomH.setBonds ( new Array (1)); var b = new JS.SmilesBond (atom, atomH, 1, false); if (JU.Logger.debugging) JU.Logger.info ("" + b); } } if (isForMF) return; for (var i = 0; i < this.ac; i++) { var sAtom = this.patternAtoms[i]; var i1 = sAtom.getMatchingAtomIndex (); var atom1 = atoms[i1]; var n = sAtom.getBondCount (); for (var j = 0; j < n; j++) { var sBond = sAtom.getBond (j); var firstAtom = (sBond.atom1 === sAtom); if (firstAtom) { var order = 1; switch (sBond.order) { case 1: case 2: case 3: case 4: case 1025: case 1041: case 65537: case 65538: case 112: case 96: order = sBond.order; break; case 17: order = 514; break; } var atom2 = atoms[sBond.atom2.getMatchingAtomIndex ()]; var b = new JS.SmilesBond (atom1, atom2, order, false); b.isConnection = sBond.isConnection; atom2.bondCount--; if (JU.Logger.debugging) JU.Logger.info ("" + b); } else { var atom2 = atoms[sBond.atom1.getMatchingAtomIndex ()]; var b = atom2.getBondTo (atom1); atom1.addBond (b); }} } for (var i = 0; i < totalAtoms; i++) { var a = atoms[i]; var bonds = a.bonds; if (bonds.length < 2 || bonds[0].isFromPreviousTo (a)) continue; for (var k = bonds.length; --k >= 1; ) if (bonds[k].isFromPreviousTo (a)) { var b = bonds[k]; bonds[k] = bonds[0]; bonds[0] = b; break; } } if (!this.ignoreStereochemistry) for (var i = this.ac; --i >= 0; ) { var sAtom = this.patternAtoms[i]; if (sAtom.stereo != null) sAtom.stereo.fixStereo (sAtom); } }, "JU.BS"); c$.normalizeAromaticity = Clazz.defineMethod (c$, "normalizeAromaticity", function (atoms, bsAromatic, flags) { var ss = new JS.SmilesSearch (); ss.setFlags (flags); ss.targetAtoms = atoms; ss.targetAtomCount = atoms.length; ss.bsSelected = JU.BSUtil.newBitSet2 (0, atoms.length); var vRings = JU.AU.createArrayOfArrayList (4); ss.setRingData (null, vRings, true); bsAromatic.or (ss.bsAromatic); if (!bsAromatic.isEmpty ()) { var lst = vRings[3]; for (var i = lst.size (); --i >= 0; ) { var bs = lst.get (i); for (var j = bs.nextSetBit (0); j >= 0; j = bs.nextSetBit (j + 1)) { var a = atoms[j]; if (a.isAromatic || a.elementNumber == -2 || a.elementNumber == 0) continue; a.setSymbol (a.symbol.toLowerCase ()); } } }}, "~A,JU.BS,~N"); Clazz.defineMethod (c$, "getSelections", function () { var ht = this.top.htNested; if (ht == null || this.targetAtoms.length == 0) return; var htNew = new java.util.Hashtable (); for (var entry, $entry = ht.entrySet ().iterator (); $entry.hasNext () && ((entry = $entry.next ()) || true);) { var key = entry.getValue ().toString (); if (key.startsWith ("select")) { var bs = (htNew.containsKey (key) ? htNew.get (key) : this.targetAtoms[0].findAtomsLike (key.substring (6))); if (bs == null) bs = new JU.BS (); htNew.put (key, bs); entry.setValue (bs); }} }); Clazz.defineMethod (c$, "findImplicitHydrogen", function (atom) { var edges = atom.getEdges (); for (var i = edges.length; --i >= 0; ) { var k = atom.getBondedAtomIndex (i); if (this.targetAtoms[k].getElementNumber () == 1 && !this.bsFound.get (k)) return this.targetAtoms[k]; } return null; }, "JU.Node"); Clazz.defineMethod (c$, "toString", function () { var sb = new JU.SB ().append (this.pattern); sb.append ("\nmolecular formula: " + this.getMolecularFormula (true, null, false)); return sb.toString (); }); Clazz.defineStatics (c$, "SUBMODE_NESTED", 1, "SUBMODE_RINGCHECK", 2, "SUBMODE_OR", 3); });