Clazz.declarePackage ("JM"); Clazz.load (["JM.AtomCollection"], "JM.BondCollection", ["JU.AU", "$.BS", "JM.Bond", "$.BondIteratorSelected", "$.BondSet", "$.HBond", "JU.BSUtil", "$.C", "$.Edge", "$.Logger"], function () { c$ = Clazz.decorateAsClass (function () { this.bo = null; this.bondCount = 0; this.numCached = null; this.freeBonds = null; this.molecules = null; this.moleculeCount = 0; this.defaultCovalentMad = 0; this.bsAromaticSingle = null; this.bsAromaticDouble = null; this.bsAromatic = null; this.haveHiddenBonds = false; Clazz.instantialize (this, arguments); }, JM, "BondCollection", JM.AtomCollection); Clazz.defineMethod (c$, "setupBC", function () { this.bsAromatic = new JU.BS (); this.numCached = Clazz.newIntArray (5, 0); this.freeBonds = new Array (5); for (var i = 5; --i > 0; ) this.freeBonds[i] = new Array (200); this.setupAC (); }); Clazz.defineMethod (c$, "releaseModelSetBC", function () { this.bo = null; this.freeBonds = null; this.releaseModelSetAC (); }); Clazz.defineMethod (c$, "getBondIteratorForType", function (bondType, bsAtoms) { return new JM.BondIteratorSelected (this.bo, this.bondCount, bondType, bsAtoms, this.vwr.getBoolean (603979812)); }, "~N,JU.BS"); Clazz.defineMethod (c$, "getBondIterator", function (bsBonds) { return new JM.BondIteratorSelected (this.bo, this.bondCount, 131071, bsBonds, false); }, "JU.BS"); Clazz.defineMethod (c$, "getBondColix1", function (i) { return JU.C.getColixInherited (this.bo[i].colix, this.bo[i].atom1.colixAtom); }, "~N"); Clazz.defineMethod (c$, "getBondColix2", function (i) { return JU.C.getColixInherited (this.bo[i].colix, this.bo[i].atom2.colixAtom); }, "~N"); Clazz.defineMethod (c$, "getBondCountInModel", function (modelIndex) { var n = 0; for (var i = this.bondCount; --i >= 0; ) if (this.bo[i].atom1.mi == modelIndex) n++; return n; }, "~N"); Clazz.defineMethod (c$, "getBondsForSelectedAtoms", function (bsAtoms, bondSelectionModeOr) { var bs = new JU.BS (); for (var iBond = 0; iBond < this.bondCount; ++iBond) { var bond = this.bo[iBond]; var isSelected1 = bsAtoms.get (bond.atom1.i); var isSelected2 = bsAtoms.get (bond.atom2.i); if (bondSelectionModeOr ? isSelected1 || isSelected2 : isSelected1 && isSelected2) bs.set (iBond); } return bs; }, "JU.BS,~B"); Clazz.defineMethod (c$, "bondAtoms", function (atom1, atom2, order, mad, bsBonds, energy, addGroup, isNew) { var bond = this.getOrAddBond (atom1, atom2, order, mad, bsBonds, energy, true); if (isNew) { bond.order |= 131072; if (addGroup) { atom1.group = atom2.group; atom1.group.addAtoms (atom1.i); }}return bond; }, "JM.Atom,JM.Atom,~N,~N,JU.BS,~N,~B,~B"); Clazz.defineMethod (c$, "getOrAddBond", function (atom, atomOther, order, mad, bsBonds, energy, overrideBonding) { var i; if (order == 131071 || order == 65535) order = 1; if (atom.isBonded (atomOther)) { i = atom.getBond (atomOther).index; if (overrideBonding) { this.bo[i].setOrder (order); this.bo[i].setMad (mad); if (Clazz.instanceOf (this.bo[i], JM.HBond)) (this.bo[i]).energy = energy; }} else { if (this.bondCount == this.bo.length) this.bo = JU.AU.arrayCopyObject (this.bo, this.bondCount + 250); i = this.setBond (this.bondCount++, this.bondMutually (atom, atomOther, order, mad, energy)).index; }if (bsBonds != null) bsBonds.set (i); return this.bo[i]; }, "JM.Atom,JM.Atom,~N,~N,JU.BS,~N,~B"); Clazz.defineMethod (c$, "setBond", function (index, bond) { return this.bo[bond.index = index] = bond; }, "~N,JM.Bond"); Clazz.defineMethod (c$, "bondMutually", function (atom, atomOther, order, mad, energy) { var bond; if (JU.Edge.isOrderH (order)) { bond = new JM.HBond (atom, atomOther, order, mad, 0, energy); } else { bond = new JM.Bond (atom, atomOther, order, mad, 0); }this.addBondToAtom (atom, bond); this.addBondToAtom (atomOther, bond); return bond; }, "JM.Atom,JM.Atom,~N,~N,~N"); Clazz.defineMethod (c$, "addBondToAtom", function (atom, bond) { if (atom.bonds == null) { atom.bonds = new Array (1); atom.bonds[0] = bond; } else { atom.bonds = this.addToBonds (bond, atom.bonds); }}, "JM.Atom,JM.Bond"); Clazz.defineMethod (c$, "addToBonds", function (newBond, oldBonds) { var newBonds; if (oldBonds == null) { if (this.numCached[1] > 0) newBonds = this.freeBonds[1][--this.numCached[1]]; else newBonds = new Array (1); newBonds[0] = newBond; } else { var oldLength = oldBonds.length; var newLength = oldLength + 1; if (newLength < 5 && this.numCached[newLength] > 0) newBonds = this.freeBonds[newLength][--this.numCached[newLength]]; else newBonds = new Array (newLength); newBonds[oldLength] = newBond; for (var i = oldLength; --i >= 0; ) newBonds[i] = oldBonds[i]; if (oldLength < 5 && this.numCached[oldLength] < 200) this.freeBonds[oldLength][this.numCached[oldLength]++] = oldBonds; }return newBonds; }, "JM.Bond,~A"); Clazz.defineMethod (c$, "addHBond", function (atom1, atom2, order, energy) { if (this.bondCount == this.bo.length) this.bo = JU.AU.arrayCopyObject (this.bo, this.bondCount + 250); return this.setBond (this.bondCount++, this.bondMutually (atom1, atom2, order, 1, energy)).index; }, "JM.Atom,JM.Atom,~N,~N"); Clazz.defineMethod (c$, "deleteAllBonds2", function () { this.vwr.setShapeProperty (1, "reset", null); for (var i = this.bondCount; --i >= 0; ) { this.bo[i].deleteAtomReferences (); this.bo[i] = null; } this.bondCount = 0; }); Clazz.defineMethod (c$, "getDefaultMadFromOrder", function (order) { return (JU.Edge.isOrderH (order) ? 1 : order == 32768 ? Clazz.doubleToInt (Math.floor (this.vwr.getFloat (570425406) * 2000)) : this.defaultCovalentMad); }, "~N"); Clazz.defineMethod (c$, "deleteConnections", function (minD, maxD, order, bsA, bsB, isBonds, matchNull) { var minDIsFraction = (minD < 0); var maxDIsFraction = (maxD < 0); var isFractional = (minDIsFraction || maxDIsFraction); minD = this.fixD (minD, minDIsFraction); maxD = this.fixD (maxD, maxDIsFraction); var bsDelete = new JU.BS (); var nDeleted = 0; var newOrder = order |= 131072; if (!matchNull && JU.Edge.isOrderH (order)) order = 30720; var bsBonds; if (isBonds) { bsBonds = bsA; } else { bsBonds = new JU.BS (); for (var i = bsA.nextSetBit (0); i >= 0; i = bsA.nextSetBit (i + 1)) { var a = this.at[i]; if (a.bonds != null) for (var j = a.bonds.length; --j >= 0; ) if (bsB.get (a.getBondedAtomIndex (j))) bsBonds.set (a.bonds[j].index); } }for (var i = bsBonds.nextSetBit (0); i < this.bondCount && i >= 0; i = bsBonds.nextSetBit (i + 1)) { var bond = this.bo[i]; if (!this.isInRange (bond.atom1, bond.atom2, minD, maxD, minDIsFraction, maxDIsFraction, isFractional)) continue; if (matchNull || newOrder == (bond.order & -257 | 131072) || (order & bond.order & 30720) != 0) { bsDelete.set (i); nDeleted++; }} if (nDeleted > 0) this.dBm (bsDelete, false); return Clazz.newIntArray (-1, [0, nDeleted]); }, "~N,~N,~N,JU.BS,JU.BS,~B,~B"); Clazz.defineMethod (c$, "fixD", function (d, isF) { return (isF ? -d : d * d); }, "~N,~B"); Clazz.defineMethod (c$, "isInRange", function (atom1, atom2, minD, maxD, minFrac, maxfrac, isFractional) { var d2 = atom1.distanceSquared (atom2); if (isFractional) { var dAB = Math.sqrt (d2); var dABcalc = atom1.getBondingRadius () + atom2.getBondingRadius (); return ((minFrac ? dAB >= dABcalc * minD : d2 >= minD) && (maxfrac ? dAB <= dABcalc * maxD : d2 <= maxD)); }return (d2 >= minD && d2 <= maxD); }, "JM.Atom,JM.Atom,~N,~N,~B,~B,~B"); Clazz.defineMethod (c$, "dBm", function (bsBonds, isFullModel) { (this).deleteBonds (bsBonds, isFullModel); }, "JU.BS,~B"); Clazz.defineMethod (c$, "dBb", function (bsBond, isFullModel) { var iDst = bsBond.nextSetBit (0); if (iDst < 0) return; (this).resetMolecules (); var modelIndexLast = -1; var n = bsBond.cardinality (); for (var iSrc = iDst; iSrc < this.bondCount; ++iSrc) { var bond = this.bo[iSrc]; if (n > 0 && bsBond.get (iSrc)) { n--; if (!isFullModel) { var modelIndex = bond.atom1.mi; if (modelIndex != modelIndexLast) (this).am[modelIndexLast = modelIndex].resetBoundCount (); }bond.deleteAtomReferences (); } else { this.setBond (iDst++, bond); }} for (var i = this.bondCount; --i >= iDst; ) this.bo[i] = null; this.bondCount = iDst; var sets = this.vwr.getShapeProperty (1, "sets"); if (sets != null) for (var i = 0; i < sets.length; i++) JU.BSUtil.deleteBits (sets[i], bsBond); JU.BSUtil.deleteBits (this.bsAromatic, bsBond); }, "JU.BS,~B"); Clazz.defineMethod (c$, "resetAromatic", function () { for (var i = this.bondCount; --i >= 0; ) { var bond = this.bo[i]; if (bond.isAromatic ()) bond.setOrder (515); } }); Clazz.defineMethod (c$, "assignAromaticBondsBs", function (isUserCalculation, bsBonds) { if (!isUserCalculation) this.bsAromatic = new JU.BS (); this.bsAromaticSingle = new JU.BS (); this.bsAromaticDouble = new JU.BS (); var isAll = (bsBonds == null); var i0 = (isAll ? this.bondCount - 1 : bsBonds.nextSetBit (0)); for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsBonds.nextSetBit (i + 1))) { var bond = this.bo[i]; if (this.bsAromatic.get (i)) bond.setOrder (515); switch (bond.order & -131073) { case 515: if (!this.assignAromaticMustBeSingle (bond.atom1) && !this.assignAromaticMustBeSingle (bond.atom2)) { this.bsAromatic.set (i); break; }bond.order = 513; case 513: this.bsAromaticSingle.set (i); break; case 514: this.bsAromaticDouble.set (i); break; } } var bond; isAll = (bsBonds == null); i0 = (isAll ? this.bondCount - 1 : bsBonds.nextSetBit (0)); var bsTest = new JU.BS (); for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsBonds.nextSetBit (i + 1))) { bond = this.bo[i]; if (!bond.is (515) || this.bsAromaticDouble.get (i) || this.bsAromaticSingle.get (i)) continue; bsTest.set (i); if (bond.atom1.getElementNumber () == 8 || bond.atom2.getElementNumber () == 8) { if (!this.assignAromaticDouble (bond)) this.assignAromaticSingle (bond); } else { bsTest.set (i); }} for (var i = bsTest.nextSetBit (0); i >= 0; i = bsTest.nextSetBit (i + 1)) if (!this.assignAromaticDouble (bond = this.bo[i])) this.assignAromaticSingle (bond); var bsModels = new JU.BS (); for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsBonds.nextSetBit (i + 1))) { bond = this.bo[i]; if (this.bsAromaticDouble.get (i)) { if (!bond.is (514)) { this.bsAromatic.set (i); bsModels.set (bond.atom1.mi); bond.setOrder (514); }} else if (this.bsAromaticSingle.get (i) || bond.isAromatic ()) { if (!bond.is (513)) { this.bsAromatic.set (i); bond.setOrder (513); }}} var models = (this).am; for (var i = bsModels.nextSetBit (0); i >= 0; i = bsModels.nextSetBit (i + 1)) if (models[i].isBioModel) models[i].isPdbWithMultipleBonds = true; this.assignAromaticNandO (bsBonds); this.bsAromaticSingle = null; this.bsAromaticDouble = null; }, "~B,JU.BS"); Clazz.defineMethod (c$, "assignAromaticDouble", function (bond) { var bondIndex = bond.index; if (this.bsAromaticSingle.get (bondIndex)) return false; if (this.bsAromaticDouble.get (bondIndex)) return true; this.bsAromaticDouble.set (bondIndex); if (!this.assignAromaticSingleForAtom (bond.atom1, bondIndex) || !this.assignAromaticSingleForAtom (bond.atom2, bondIndex)) { this.bsAromaticDouble.clear (bondIndex); return false; }return true; }, "JM.Bond"); Clazz.defineMethod (c$, "assignAromaticSingle", function (bond) { var bondIndex = bond.index; if (this.bsAromaticDouble.get (bondIndex)) return false; if (this.bsAromaticSingle.get (bondIndex)) return true; this.bsAromaticSingle.set (bondIndex); if (!this.assignAromaticDoubleForAtom (bond.atom1) || !this.assignAromaticDoubleForAtom (bond.atom2)) { this.bsAromaticSingle.clear (bondIndex); return false; }return true; }, "JM.Bond"); Clazz.defineMethod (c$, "assignAromaticSingleForAtom", function (atom, notBondIndex) { var bonds = atom.bonds; if (bonds == null) return false; for (var i = bonds.length; --i >= 0; ) { var bond = bonds[i]; var bondIndex = bond.index; if (bondIndex == notBondIndex || !bond.isAromatic () || this.bsAromaticSingle.get (bondIndex)) continue; if (this.bsAromaticDouble.get (bondIndex) || !this.assignAromaticSingle (bond)) { return false; }} return true; }, "JM.Atom,~N"); Clazz.defineMethod (c$, "assignAromaticDoubleForAtom", function (atom) { var bonds = atom.bonds; if (bonds == null) return false; var haveDouble = false; var lastBond = -1; for (var i = bonds.length; --i >= 0; ) { if (this.bsAromaticDouble.get (bonds[i].index)) haveDouble = true; if (bonds[i].isAromatic ()) lastBond = i; } for (var i = bonds.length; --i >= 0; ) { var bond = bonds[i]; var bondIndex = bond.index; if (!bond.isAromatic () || this.bsAromaticDouble.get (bondIndex) || this.bsAromaticSingle.get (bondIndex)) continue; if (!haveDouble && this.assignAromaticDouble (bond)) haveDouble = true; else if ((haveDouble || i < lastBond) && !this.assignAromaticSingle (bond)) { return false; }} return haveDouble; }, "JM.Atom"); Clazz.defineMethod (c$, "allowAromaticBond", function (b) { if (this.assignAromaticMustBeSingle (b.atom1) || this.assignAromaticMustBeSingle (b.atom2)) return false; switch (b.getCovalentOrder ()) { case 1: case 2: return b.atom1.getCovalentBondCount () <= 3 && b.atom2.getCovalentBondCount () <= 3; default: return false; } }, "JM.Bond"); Clazz.defineMethod (c$, "assignAromaticMustBeSingle", function (atom) { var n = atom.getElementNumber (); switch (n) { case 6: case 7: case 8: case 16: break; default: return true; } var nAtoms = atom.getValence (); switch (n) { case 6: return (nAtoms == 4); case 7: return (atom.group.getNitrogenAtom () === atom || nAtoms == 3 && atom.getFormalCharge () < 1); case 8: return (atom.group.getCarbonylOxygenAtom () !== atom && nAtoms == 2 && atom.getFormalCharge () < 1); case 16: return (atom.group.groupID == 5 || nAtoms == 2 && atom.getFormalCharge () < 1); } return false; }, "JM.Atom"); Clazz.defineMethod (c$, "assignAromaticNandO", function (bsSelected) { var bond; var isAll = (bsSelected == null); var i0 = (isAll ? this.bondCount - 1 : bsSelected.nextSetBit (0)); for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsSelected.nextSetBit (i + 1))) { bond = this.bo[i]; if (!bond.is (513)) continue; var atom1; var atom2 = bond.atom2; var n1; var n2 = atom2.getElementNumber (); if (n2 == 7 || n2 == 8) { n1 = n2; atom1 = atom2; atom2 = bond.atom1; n2 = atom2.getElementNumber (); } else { atom1 = bond.atom1; n1 = atom1.getElementNumber (); }if (n1 != 7 && n1 != 8) continue; var valence = atom1.getValence (); if (valence < 0) continue; var bondorder = atom1.getCovalentBondCount (); var charge = atom1.getFormalCharge (); switch (n1) { case 7: if (valence == 3 && bondorder == 3 && charge < 1 && n2 == 6 && atom2.getValence () == 3) bond.setOrder (514); break; case 8: if (valence == 1 && charge == 0 && (n2 == 14 || n2 == 16)) bond.setOrder (514); break; } } }, "JU.BS"); Clazz.defineMethod (c$, "getAtomBitsMDb", function (tokType, specInfo) { var bs = new JU.BS (); switch (tokType) { default: return this.getAtomBitsMDa (tokType, specInfo, bs); case 1677721602: var bsBonds = specInfo; for (var i = bsBonds.nextSetBit (0); i >= 0; i = bsBonds.nextSetBit (i + 1)) { bs.set (this.bo[i].atom1.i); bs.set (this.bo[i].atom2.i); } return bs; case 1073742331: for (var i = this.bondCount; --i >= 0; ) if (this.bo[i].isAromatic ()) { bs.set (this.bo[i].atom1.i); bs.set (this.bo[i].atom2.i); } return bs; } }, "~N,~O"); Clazz.defineMethod (c$, "assignBond", function (bondIndex, type) { var bondOrder = type.charCodeAt (0) - 48; var bond = this.bo[bondIndex]; (this).clearDB (bond.atom1.i); switch (type) { case '0': case '1': case '2': case '3': break; case 'p': case 'm': bondOrder = JU.Edge.getBondOrderNumberFromOrder (bond.getCovalentOrder ()).charCodeAt (0) - 48 + (type == 'p' ? 1 : -1); if (bondOrder > 3) bondOrder = 1; else if (bondOrder < 0) bondOrder = 3; break; default: return null; } var bsAtoms = new JU.BS (); try { if (bondOrder == 0) { var bs = new JU.BS (); bs.set (bond.index); bsAtoms.set (bond.atom1.i); bsAtoms.set (bond.atom2.i); this.dBm (bs, false); return bsAtoms; }bond.setOrder (bondOrder | 131072); if (bond.atom1.getElementNumber () != 1 && bond.atom2.getElementNumber () != 1) { this.removeUnnecessaryBonds (bond.atom1, false); this.removeUnnecessaryBonds (bond.atom2, false); }bsAtoms.set (bond.atom1.i); bsAtoms.set (bond.atom2.i); } catch (e) { if (Clazz.exceptionOf (e, Exception)) { JU.Logger.error ("Exception in seBondOrder: " + e.toString ()); } else { throw e; } } return bsAtoms; }, "~N,~S"); Clazz.defineMethod (c$, "removeUnnecessaryBonds", function (atom, deleteAtom) { var bs = new JU.BS (); var bsBonds = new JU.BS (); var bonds = atom.bonds; if (bonds == null) return; for (var i = 0; i < bonds.length; i++) if (bonds[i].isCovalent ()) { var atom2 = bonds[i].getOtherAtom (atom); if (atom2.getElementNumber () == 1) bs.set (bonds[i].getOtherAtom (atom).i); } else { bsBonds.set (bonds[i].index); } if (bsBonds.nextSetBit (0) >= 0) this.dBm (bsBonds, false); if (deleteAtom) bs.set (atom.i); if (bs.nextSetBit (0) >= 0) this.vwr.deleteAtoms (bs, false); }, "JM.Atom,~B"); Clazz.defineMethod (c$, "displayBonds", function (bs, isDisplay) { if (!isDisplay) this.haveHiddenBonds = true; for (var i = bs.nextSetBit (0); i >= 0; i = bs.nextSetBit (i + 1)) if (i < this.bondCount && this.bo[i].mad != 0) this.bo[i].setShapeVisibility (isDisplay); }, "JM.BondSet,~B"); Clazz.defineMethod (c$, "getAtomsConnected", function (min, max, intType, bs) { var isBonds = Clazz.instanceOf (bs, JM.BondSet); var bsResult = (isBonds ? new JM.BondSet () : new JU.BS ()); var nBonded = Clazz.newIntArray (this.ac, 0); var i; var ishbond = (intType == 30720); var isall = (intType == 65535); for (var ibond = 0; ibond < this.bondCount; ibond++) { var bond = this.bo[ibond]; if (isall || bond.is (intType) || ishbond && bond.isHydrogen ()) { if (isBonds) { bsResult.set (ibond); } else { if (bs.get (bond.atom1.i)) { nBonded[i = bond.atom2.i]++; bsResult.set (i); }if (bs.get (bond.atom2.i)) { nBonded[i = bond.atom1.i]++; bsResult.set (i); }}}} if (isBonds) return bsResult; var nonbonded = (min == 0); for (i = this.ac; --i >= 0; ) { var n = nBonded[i]; if (n < min || n > max) bsResult.clear (i); else if (nonbonded && n == 0) bsResult.set (i); } return bsResult; }, "~N,~N,~N,JU.BS"); Clazz.defineStatics (c$, "BOND_GROWTH_INCREMENT", 250, "MAX_BONDS_LENGTH_TO_CACHE", 5, "MAX_NUM_TO_CACHE", 200); });