text: 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"]);
  });
  