UNPKG

biojs-vis-pdbviewer

Version:

A BioJS 2.0 component to view protein structures

542 lines (531 loc) 18.7 kB
Clazz.declarePackage ("J.adapter.readers.xtal"); Clazz.load (["J.adapter.smarter.AtomSetCollectionReader"], "J.adapter.readers.xtal.JanaReader", ["java.lang.Boolean", "$.Exception", "$.Float", "java.util.Hashtable", "JU.A4", "$.BS", "$.Lst", "$.Matrix", "$.P3", "$.PT", "$.Quat", "$.Rdr", "$.V3", "J.adapter.smarter.Atom", "J.api.Interface", "JU.Logger"], function () { c$ = Clazz.decorateAsClass (function () { this.lattvecs = null; this.thisSub = 0; this.modAxes = null; this.modDim = 0; this.haveM40Data = false; this.qicount = 0; this.molName = null; this.molAtoms = null; this.molTtypes = null; this.modelMolecule = null; this.molHasTLS = false; this.matR = null; this.rho = null; this.firstPosition = false; this.vR = null; this.v0Cart = null; this.floats = null; Clazz.instantialize (this, arguments); }, J.adapter.readers.xtal, "JanaReader", J.adapter.smarter.AtomSetCollectionReader); Clazz.prepareFields (c$, function () { this.floats = Clazz.newFloatArray (6, 0); }); Clazz.overrideMethod (c$, "initializeReader", function () { this.modAxes = this.getFilter ("MODAXES="); this.setFractionalCoordinates (true); this.asc.newAtomSet (); this.asc.setAtomSetAuxiliaryInfo ("autoBondUsingOccupation", Boolean.TRUE); }); Clazz.overrideMethod (c$, "checkLine", function () { if (this.line.length < 3) return true; JU.Logger.info (this.line); this.parseTokenStr (this.line); switch ("tit cell ndim qi lat sym spg end wma".indexOf (this.line.substring (0, 3))) { case 0: this.asc.setAtomSetName (this.line.substring (5).trim ()); break; case 5: this.cell (); this.setSymmetryOperator ("x,y,z"); break; case 10: this.ndim (); break; case 20: if (this.lattvecs == null) this.lattvecs = new JU.Lst (); if (!this.ms.addLatticeVector (this.lattvecs, this.line.substring (8))) this.appendLoadNote (this.line + " not supported"); break; case 30: this.setSpaceGroupName (this.getTokens ()[1]); break; case 25: this.symmetry (); break; case 15: this.qi (); break; case 35: while (this.rd () != null) { if (this.line.startsWith ("command") || this.parseIntStr (this.line) >= 0) { this.readM40Data (true); break; }} this.continuing = false; break; case 40: var n = 3 + this.modDim; var m; if (this.thisSub++ == 0) { m = JU.Matrix.identity (n, n); this.ms.addSubsystem ("" + this.thisSub++, m); }m = new JU.Matrix (null, n, n); var a = m.getArray (); var data = Clazz.newFloatArray (n * n, 0); this.fillFloatArray (null, 0, data); for (var i = 0, pt = 0; i < n; i++) for (var j = 0; j < n; j++, pt++) a[i][j] = data[pt]; this.ms.addSubsystem ("" + this.thisSub, m); } return true; }); Clazz.overrideMethod (c$, "doPreSymmetry", function () { if (this.ms != null) this.ms.setModulation (false); }); Clazz.overrideMethod (c$, "finalizeReader", function () { if (!this.haveM40Data) this.readM40Data (false); if (this.lattvecs != null && this.lattvecs.size () > 0) this.asc.getSymmetry ().addLatticeVectors (this.lattvecs); this.applySymmetryAndSetTrajectory (); this.adjustM40Occupancies (); if (this.ms != null) { this.ms.setModulation (true); this.ms.finalizeModulation (); }this.finalizeReaderASCR (); }); Clazz.defineMethod (c$, "cell", function () { for (var ipt = 0; ipt < 6; ipt++) this.setUnitCellItem (ipt, this.parseFloat ()); }); Clazz.defineMethod (c$, "ndim", function () { this.ms = J.api.Interface.getOption ("adapter.readers.cif.MSRdr"); this.modDim = this.ms.initialize (this, (this.parseIntStr (this.getTokens ()[1]) - 3)); }); Clazz.defineMethod (c$, "qi", function () { var pt = Clazz.newDoubleArray (this.modDim, 0); pt[this.qicount] = 1; this.ms.addModulation (null, "W_" + (++this.qicount), [this.parseFloat (), this.parseFloat (), this.parseFloat ()], -1); this.ms.addModulation (null, "F_" + this.qicount + "_coefs_", pt, -1); }); Clazz.defineMethod (c$, "symmetry", function () { this.setSymmetryOperator (JU.PT.rep (this.line.substring (9).trim (), " ", ",")); }); Clazz.defineMethod (c$, "readM40Data", function (haveReader) { if (haveReader) { this.parseM40Floats (); } else { var m40File = this.filePath; var ipt = m40File.lastIndexOf ("."); if (ipt < 0) return; m40File = m40File.substring (0, ipt + 2) + "40"; var id = m40File.substring (0, ipt); ipt = id.lastIndexOf ("/"); id = id.substring (ipt + 1); this.reader.close (); this.reader = JU.Rdr.getBR (this.vwr.getLigandModel (id, m40File, "_file", "----")); if (this.out != null) this.out.append ("******************************* M40 DATA *******************************\n"); this.readM40Floats (); }this.haveM40Data = true; if (this.line.startsWith ("command")) this.readM40WaveVectors (); var nFree = 0; var nGroups = 0; var isAxial = false; var newSub = (this.thisSub == 0 ? null : new JU.BS ()); var iSub = (this.thisSub == 0 ? 1 : this.thisSub); for (var i = 0, n = 0, pt = 0; i < iSub; i++, pt += 10) { nFree = this.getInt (pt, pt + 5); nGroups = this.getInt (pt + 5, pt + 10); isAxial = (this.getInt (pt + 15, pt + 20) == 1); if (nGroups != 0 && i > 0) { throw new Exception ("Jmol cannot read rigid body M40 files for composites"); }if (newSub != null) newSub.set (n = n + nFree); } iSub = (newSub == null ? 0 : 1); var nAtoms = -1; var refAtomName = null; this.rho = null; if (nGroups > 0) { JU.Logger.info ("JanaReader found " + nFree + " free atoms and " + nGroups + " groups"); this.molName = null; this.molAtoms = new JU.Lst (); this.molTtypes = new JU.Lst (); }while (this.skipToNextAtom () != null) { nAtoms++; var atom = new J.adapter.smarter.Atom (); JU.Logger.info (this.line); var name = this.line.substring (0, 9).trim (); atom.atomName = name; var isRefAtom = name.equals (refAtomName); atom.foccupancy = this.floats[2]; var isJanaMolecule = Float.isNaN (atom.foccupancy); if (isJanaMolecule) { var pointGroup = this.getStr (12, 18); if (pointGroup.length > 0 && !pointGroup.equals ("1")) { throw new Exception ("Jmol cannot process M40 files with molecule positions based on point-group symmetry."); }refAtomName = null; if (Float.isNaN (this.floats[4])) refAtomName = this.getStr (28, 37); else this.rho = JU.P3.new3 (this.floats[3], this.floats[4], this.floats[5]); this.molName = name; this.molAtoms.clear (); this.molTtypes.clear (); this.molHasTLS = false; this.firstPosition = true; this.modelMolecule = new JU.Lst (); continue; }var isExcluded = false; var posName = (name.startsWith ("pos#") ? name : null); if (posName == null) { if (!this.filterAtom (atom, 0)) { if (!isRefAtom) continue; isExcluded = true; }this.setAtomCoordXYZ (atom, this.floats[3], this.floats[4], this.floats[5]); if (isRefAtom) { this.rho = JU.P3.newP (atom); if (isExcluded) continue; }this.asc.addAtom (atom); if (iSub > 0) { if (newSub.get (nAtoms)) iSub++; atom.altLoc = ("" + iSub).charAt (0); }this.readAtomRecord (atom, null, null, false); if (this.molAtoms != null) this.molAtoms.addLast (atom); } else { if (this.molAtoms.size () == 0) continue; this.processPosition (posName, atom, isAxial); }} }, "~B"); Clazz.defineMethod (c$, "getInt", function (col1, col2) { var n = this.line.length; return (n > col1 ? this.parseIntStr (this.getStr (col1, col2)) : 0); }, "~N,~N"); Clazz.defineMethod (c$, "getStr", function (col1, col2) { var n = this.line.length; return (n > col1 ? this.line.substring (col1, Math.min (n, col2)).trim () : ""); }, "~N,~N"); Clazz.defineMethod (c$, "getFlag", function (i) { return (this.getInt (i, i + 1) > 0); }, "~N"); Clazz.defineMethod (c$, "skipToNextAtom", function () { while (this.readM40Floats () != null && (this.line.length == 0 || this.line.charAt (0) == ' ' || this.line.charAt (0) == '-')) { } return this.line; }); Clazz.defineMethod (c$, "readM40WaveVectors", function () { while (!this.readM40Floats ().contains ("end")) if (this.line.startsWith ("wave")) { var tokens = this.getTokens (); var pt = Clazz.newDoubleArray (this.modDim, 0); for (var i = 0; i < this.modDim; i++) pt[i] = this.parseFloatStr (tokens[i + 2]); this.ms.addModulation (null, "F_" + this.parseIntStr (tokens[1]) + "_coefs_", pt, -1); } this.readM40Floats (); }); Clazz.defineMethod (c$, "processPosition", function (posName, pos, isAxial) { pos.atomName = this.molName + "_" + posName; var isImproper = (this.getInt (9, 11) == -1); var systType = this.getInt (13, 14); var rm = (systType == 0 ? null : new JU.P3 ()); var rp = (systType == 0 ? null : new JU.P3 ()); if (systType != 0) { throw new Exception ("Jmol can only read rigid body groups with basic crystallographic settings."); }var rotData = this.readAtomRecord (pos, rm, rp, true); var name = pos.atomName; var n = this.molAtoms.size (); JU.Logger.info (name + " Molecular group " + this.molName + " has " + n + " atoms"); var ext = "_" + posName.substring (4); var vTrans = JU.V3.new3 (pos.anisoBorU[3], pos.anisoBorU[4], pos.anisoBorU[5]); var phi = JU.Quat.newAA (JU.A4.newVA (JU.V3.new3 (0, 0, 1), (pos.anisoBorU[0] / 180 * 3.141592653589793))); var chi = JU.Quat.newAA (JU.A4.newVA (isAxial ? JU.V3.new3 (0, 1, 0) : JU.V3.new3 (1, 0, 0), (pos.anisoBorU[1] / 180 * 3.141592653589793))); var psi = JU.Quat.newAA (JU.A4.newVA (isAxial ? JU.V3.new3 (1, 0, 0) : JU.V3.new3 (0, 0, 1), (pos.anisoBorU[2] / 180 * 3.141592653589793))); this.matR = phi.mulQ (chi).mulQ (psi).getMatrix (); if (isImproper) this.matR.scale (-1); var script = ""; for (var i = 0; i < n; i++) { var a = this.molAtoms.get (i); var newName = a.atomName; script += ", " + newName; if (this.firstPosition) { newName += ext; this.modelMolecule.addLast (JU.P3.newP (a)); } else { a = this.asc.newCloneAtom (a); newName = newName.substring (0, newName.lastIndexOf ("_")) + ext; }a.atomName = newName; var v0 = JU.V3.newVsub (this.modelMolecule.get (i), this.rho); this.getSymmetry ().toCartesian (this.v0Cart = JU.V3.newV (v0), true); this.vR = JU.V3.newV (v0); this.cartesianProduct (this.vR, null); a.setT (this.rho); a.add (vTrans); a.add (this.vR); this.copyModulations (";" + pos.atomName, ";" + newName); if (rotData != null) this.setRigidBodyRotations (";" + newName, rotData); } this.firstPosition = false; script = "@" + this.molName + ext + script.substring (1); this.addJmolScript (script); this.appendLoadNote (script); }, "~S,J.adapter.smarter.Atom,~B"); Clazz.defineMethod (c$, "cartesianProduct", function (vA, vB) { this.symmetry.toCartesian (vA, true); if (vB == null) this.matR.rotate2 (vA, vA); else vA.cross (vA, vB); this.symmetry.toFractional (vA, true); }, "JU.T3,JU.T3"); Clazz.defineMethod (c$, "readAtomRecord", function (atom, rm, rp, isPos) { var label = ";" + atom.atomName; var tType = (isPos ? -1 : this.getInt (13, 14)); if (!isPos && this.molTtypes != null) this.molTtypes.addLast (Integer.$valueOf (tType)); var haveSpecialOcc = this.getFlag (60); var haveSpecialDisp = this.getFlag (61); var haveSpecialUij = this.getFlag (62); var nOcc = this.getInt (65, 68); var nDisp = this.getInt (68, 71); var nUij = this.getInt (71, 74); if (rm != null) { this.readM40Floats (); rm.set (this.floats[0], this.floats[1], this.floats[2]); rp.set (this.floats[3], this.floats[4], this.floats[5]); }if (tType > 2) this.readM40Floats (); this.readM40Floats (); switch (tType) { case 6: case 5: case 4: case 3: this.readLines (tType - 1); this.appendLoadNote ("Skipping temperature factors with order > 2"); case 2: case -1: for (var j = 0; j < 6; j++) this.asc.setU (atom, j, this.floats[j]); break; case 1: if (this.floats[0] != 0) this.asc.setU (atom, 7, this.floats[0]); break; case 0: this.molHasTLS = true; this.appendLoadNote ("Jmol cannot process molecular TLS parameters"); break; } if (this.modDim == 0) return null; if (isPos && this.molHasTLS) this.readLines (4); var pt; var o_0 = (nOcc > 0 && !haveSpecialOcc ? this.parseFloatStr (this.rd ()) : 1); if (o_0 != 1) this.ms.addModulation (null, "J_O#0" + label, [atom.foccupancy, o_0, 0], -1); atom.foccupancy *= o_0; var wv = 0; var a1; var a2; for (var j = 0; j < nOcc; j++) { if (haveSpecialOcc) { var data = this.readM40FloatLines (2, 1); a2 = data[0][0]; a1 = data[1][0]; } else { wv = j + 1; this.readM40Floats (); a1 = this.floats[0]; a2 = this.floats[1]; }pt = [a1, a2, 0]; if (a1 != 0 || a2 != 0) this.ms.addModulation (null, "O_" + wv + "#0" + label, pt, -1); } for (var j = 0; j < nDisp; j++) { if (haveSpecialDisp) { this.readM40Floats (); var c = this.floats[3]; var w = this.floats[4]; for (var k = 0; k < 3; k++) if (this.floats[k] != 0) this.ms.addModulation (null, "D_S#" + J.adapter.readers.xtal.JanaReader.XYZ[k] + label, [c, w, this.floats[k]], -1); } else { this.addSinCos (j, "D_", label, isPos); }} var rotData = (isPos && nDisp > 0 ? this.readM40FloatLines (nDisp, 6) : null); if (!isPos) for (var j = 0; j < nUij; j++) { this.ensureFourier (j); if (tType == 1) { this.addSinCos (j, "U_", label, false); } else { if (haveSpecialUij) { JU.Logger.error ("JanaReader -- not interpreting SpecialUij flag: " + this.line); } else { var data = this.readM40FloatLines (2, 6); for (var k = 0, p = 0; k < 6; k++, p += 3) this.ms.addModulation (null, "U_" + (j + 1) + "#" + "U11U22U33U12U13U23UISO".substring (p, p + 3) + label, [data[1][k], data[0][k], 0], -1); }}} return rotData; }, "J.adapter.smarter.Atom,JU.P3,JU.P3,~B"); Clazz.defineMethod (c$, "addSinCos", function (j, key, label, isPos) { this.ensureFourier (j); this.readM40Floats (); for (var k = 0; k < 3; ++k) { var csin = this.floats[k]; var ccos = this.floats[k + 3]; if (csin == 0 && ccos == 0) { if (!isPos) continue; csin = 1e-10; }var axis = J.adapter.readers.xtal.JanaReader.XYZ[k % 3]; if (this.modAxes != null && this.modAxes.indexOf (axis.toUpperCase ()) < 0) continue; var id = key + (j + 1) + "#" + axis + label; this.ms.addModulation (null, id, [csin, ccos, 0], -1); } }, "~N,~S,~S,~B"); Clazz.defineMethod (c$, "ensureFourier", function (j) { var pt; if (j > 0 && this.ms.getMod ("F_" + (++j) + "_coefs_") == null && (pt = this.ms.getMod ("F_1_coefs_")) != null) { var p = Clazz.newDoubleArray (this.modDim, 0); for (var i = this.modDim; --i >= 0; ) p[i] = pt[i] * j; this.ms.addModulation (null, "F_" + j + "_coefs_", p, -1); }}, "~N"); Clazz.defineMethod (c$, "readM40Floats", function () { if ((this.line = this.rd ()) == null || this.line.indexOf ("-------") >= 0) return (this.line = null); if (JU.Logger.debugging) JU.Logger.debug (this.line); this.parseM40Floats (); return this.line; }); Clazz.defineMethod (c$, "parseM40Floats", function () { var ptLast = this.line.length - 9; for (var i = 0, pt = 0; i < 6; i++, pt += 9) { this.floats[i] = (pt <= ptLast ? this.parseFloatStr (this.line.substring (pt, pt + 9)) : NaN); } }); Clazz.defineMethod (c$, "readM40FloatLines", function (nLines, nFloats) { var data = Clazz.newFloatArray (nLines, nFloats, 0); for (var i = 0; i < nLines; i++) { this.readM40Floats (); for (var j = 0; j < nFloats; j++) data[i][j] = this.floats[j]; } return data; }, "~N,~N"); Clazz.defineMethod (c$, "adjustM40Occupancies", function () { var htSiteMult = new java.util.Hashtable (); var atoms = this.asc.atoms; var symmetry = this.asc.getSymmetry (); for (var i = this.asc.ac; --i >= 0; ) { var a = atoms[i]; var ii = htSiteMult.get (a.atomName); if (ii == null) htSiteMult.put (a.atomName, ii = Integer.$valueOf (symmetry.getSiteMultiplicity (a))); a.foccupancy *= ii.intValue (); } }); Clazz.defineMethod (c$, "copyModulations", function (label, newLabel) { var mapTemp = new java.util.Hashtable (); for (var e, $e = this.ms.getModulationMap ().entrySet ().iterator (); $e.hasNext () && ((e = $e.next ()) || true);) { var key = e.getKey (); if (!key.contains (label)) continue; key = JU.PT.rep (key, label, newLabel); var val = e.getValue (); switch (key.charAt (0)) { case 'O': this.setRigidBodyPhase (key, val = [val[0], val[1], 0]); break; case 'D': break; case 'U': continue; } mapTemp.put (key, val); } for (var e, $e = mapTemp.entrySet ().iterator (); $e.hasNext () && ((e = $e.next ()) || true);) this.ms.addModulation (null, e.getKey (), e.getValue (), -1); }, "~S,~S"); Clazz.defineMethod (c$, "setRigidBodyPhase", function (key, v) { var isCenter = false; switch (this.ms.getModType (key)) { case 'o': case 'f': case 'u': break; case 'c': case 's': isCenter = true; break; } var nqDotD = 0; var n = -1; var qcoefs = this.ms.getQCoefs (key); for (var i = this.modDim; --i >= 0; ) { if (qcoefs[i] != 0) { n = qcoefs[i]; var q = this.ms.getMod ("W_" + (i + 1)); nqDotD = n * (q[0] * this.vR.x + q[1] * this.vR.y + q[2] * this.vR.z); break; }} if (isCenter) { v[0] += nqDotD; } else { var sA = v[0]; var cA = v[1]; var sX = Math.sin (2 * 3.141592653589793 * nqDotD); var cX = Math.cos (2 * 3.141592653589793 * nqDotD); v[0] = sA * cX + cA * sX; v[1] = -sA * sX + cA * cX; }return v; }, "~S,~A"); Clazz.defineMethod (c$, "setRigidBodyRotations", function (label, params) { var n = params.length; for (var i = 0; i < n; i++) { this.ensureFourier (i); var key = "D_" + (i + 1); var data = params[i]; var vsin = JU.V3.new3 (data[0], data[1], data[2]); var vcos = JU.V3.new3 (data[3], data[4], data[5]); this.cartesianProduct (vcos, this.v0Cart); this.cartesianProduct (vsin, this.v0Cart); var keyx = key + "#x" + label; var keyy = key + "#y" + label; var keyz = key + "#z" + label; var vx = this.combineModulation (keyx, vsin.x, vcos.x); var vy = this.combineModulation (keyy, vsin.y, vcos.y); var vz = this.combineModulation (keyz, vsin.z, vcos.z); vsin.set (vx[0], vy[0], vz[0]); vcos.set (vx[1], vy[1], vz[1]); this.cartesianProduct (vsin, null); this.cartesianProduct (vcos, null); this.setMolecularModulation (keyx, vsin.x, vcos.x); this.setMolecularModulation (keyy, vsin.y, vcos.y); this.setMolecularModulation (keyz, vsin.z, vcos.z); } }, "~S,~A"); Clazz.defineMethod (c$, "combineModulation", function (key, csin, ccos) { var v = this.ms.getMod (key); return [v[0] + csin, v[1] + ccos, 0]; }, "~S,~N,~N"); Clazz.defineMethod (c$, "setMolecularModulation", function (key, csin, ccos) { this.ms.addModulation (null, key, this.setRigidBodyPhase (key, [csin, ccos, 0]), -1); }, "~S,~N,~N"); Clazz.defineStatics (c$, "records", "tit cell ndim qi lat sym spg end wma", "TITLE", 0, "CELL", 5, "NDIM", 10, "QI", 15, "LATT", 20, "SYM", 25, "SPG", 30, "END", 35, "WMATRIX", 40, "U_LIST", "U11U22U33U12U13U23UISO", "XYZ", ["x", "y", "z"]); });