1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2021-12-04 23:29:43 -0600 (Sat, 04 Dec 2021) $ 4 * $Revision: 22271 $ 5 * 6 * Copyright (C) 2002-2005 The Jmol Development Team 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 package org.jmol.modelset; 25 26 import java.util.Hashtable; 27 28 import java.util.Map; 29 import java.util.Properties; 30 31 import org.jmol.api.SymmetryInterface; 32 import javajs.util.BS; 33 34 35 import javajs.util.AU; 36 import javajs.util.M4; 37 import javajs.util.P3; 38 import javajs.util.SB; 39 40 import org.jmol.util.BSUtil; 41 import org.jmol.viewer.FileManager; 42 43 public class Model { 44 45 /* 46 * In Jmol all atoms and bonds are kept as a set of arrays in 47 * the AtomCollection and BondCollection objects. 48 * Thus, "Model" is not atoms and bonds. 49 * It is a description of all the: 50 * 51 * chains (as defined in the file) 52 * and their associated file-associated groups, 53 * polymers (same, I think, but in terms of secondary structure) 54 * and their associated monomers 55 * molecules (as defined by connectivity) 56 * 57 * A Model then is just a small set of fields, a few arrays pointing 58 * to other objects, and a couple of hash tables for information storage 59 * 60 * Additional information here includes 61 * how many atoms there were before symmetry was applied 62 * as well as a bit about insertions and alternative locations. 63 * 64 * 65 * one model = one animation "frame", but we don't use the "f" word 66 * here because that would confuse the issue. 67 * 68 * If multiple files are loaded, then they will appear here in 69 * at least as many Model objects. Each vibration will be a complete 70 * set of atoms as well. 71 * 72 * Jmol 11.3.58 developed the trajectory idea -- where 73 * multiple models may share the same structures, bonds, etc., but 74 * just differ in atom positions, saved in the Trajectories Vector 75 * in ModelCollection. 76 * 77 */ 78 79 /** 80 * BE CAREFUL: FAILURE TO NULL REFERENCES TO modelSet WILL PREVENT 81 * FINALIZATION AND CREATE A MEMORY LEAK. 82 * 83 */ 84 public ModelSet ms; 85 86 /** 87 * mat4 tracks the rotation/translation of the full model using rotateSelected or translateSelected 88 */ 89 public M4 mat4; 90 91 public int modelIndex; // our 0-based reference 92 int fileIndex; // 0-based file reference 93 public boolean isBioModel; 94 public boolean isPdbWithMultipleBonds; 95 public boolean isModelKit; 96 97 98 public Chain[] chains = new Chain[8]; 99 100 public SymmetryInterface simpleCage; 101 public Map<String, Object> dssrCache; 102 public Orientation orientation; 103 public Map<String, Object> auxiliaryInfo; 104 public Properties properties; 105 public SymmetryInterface biosymmetry; 106 Map<String, Integer> dataFrames; 107 P3 translation; 108 109 int dataSourceFrame = -1; 110 111 112 public String loadState = ""; 113 public SB loadScript = new SB(); 114 115 public boolean hasRasmolHBonds; 116 public boolean structureTainted; 117 public boolean isJmolDataFrame; 118 boolean isTrajectory; 119 120 public int trajectoryBaseIndex; 121 122 public int altLocCount; 123 int insertionCount; 124 /** 125 * atom count; includes deleted atoms only if not being nulled (Jmol 14.31 or below) 126 */ 127 public int act = 0; 128 private int bondCount = -1; 129 protected int chainCount = 0; 130 public int groupCount = -1; 131 public int hydrogenCount; 132 public int moleculeCount; 133 int biosymmetryCount; 134 135 public int firstAtomIndex; 136 int firstMoleculeIndex; 137 138 /** 139 * Note that this bitset may or may not include bsAtomsDeleted 140 * 141 */ 142 public final BS bsAtoms = new BS(); 143 public final BS bsAtomsDeleted = new BS(); 144 145 float defaultRotationRadius; 146 public long frameDelay; 147 public int selectedTrajectory = -1; 148 149 String jmolData; // from a PDB remark "Jmol PDB-encoded data" 150 String jmolFrameType; 151 152 public String pdbID; 153 Model()154 public Model() { 155 156 } 157 set(ModelSet modelSet, int modelIndex, int trajectoryBaseIndex, String jmolData, Properties properties, Map<String, Object> auxiliaryInfo)158 public Model set(ModelSet modelSet, int modelIndex, int trajectoryBaseIndex, 159 String jmolData, Properties properties, Map<String, Object> auxiliaryInfo) { 160 ms = modelSet; 161 dataSourceFrame = this.modelIndex = modelIndex; 162 isTrajectory = (trajectoryBaseIndex >= 0); 163 this.trajectoryBaseIndex = (isTrajectory ? trajectoryBaseIndex : modelIndex); 164 if (auxiliaryInfo == null) { 165 auxiliaryInfo = new Hashtable<String, Object>(); 166 } 167 this.auxiliaryInfo = auxiliaryInfo; 168 Integer bc = ((Integer) auxiliaryInfo.get("biosymmetryCount")); 169 if (bc != null) { 170 biosymmetryCount = bc.intValue(); 171 biosymmetry = (SymmetryInterface) auxiliaryInfo.get("biosymmetry"); 172 } 173 String fname = (String) auxiliaryInfo.get("fileName"); 174 if (fname != null) 175 auxiliaryInfo.put("fileName", FileManager.stripTypePrefix(fname)); 176 177 this.properties = properties; 178 if (jmolData == null) { 179 jmolFrameType = "modelSet"; 180 } else { 181 this.jmolData = jmolData; 182 isJmolDataFrame = true; 183 auxiliaryInfo.put("jmolData", jmolData); 184 auxiliaryInfo.put("title", jmolData); 185 jmolFrameType = (jmolData.indexOf("ramachandran") >= 0 ? "ramachandran" 186 : jmolData.indexOf("quaternion") >= 0 ? "quaternion" : "data"); 187 } 188 return this; 189 } 190 191 /** 192 * not actually accessed -- just pointing out what it is 193 * @return true atom count 194 */ 195 // this one is variable and calculated only if necessary: getTrueAtomCount()196 public int getTrueAtomCount() { 197 return BSUtil.andNot(bsAtoms, bsAtomsDeleted).cardinality(); 198 } 199 200 private BS bsCheck; 201 202 boolean hasChirality; 203 204 /** 205 * a flag that, when false, indicates that the model has atoms in different regions of the Atom[] array 206 * 207 */ 208 public boolean isOrderly = true; 209 210 /** 211 * 212 * @param bs 213 * @return true if all undeleted atom bits in this model are in bs 214 */ isContainedIn(BS bs)215 public boolean isContainedIn(BS bs) { 216 if (bsCheck == null) 217 bsCheck = new BS(); 218 bsCheck.clearAll(); 219 bsCheck.or(bs); 220 BS bsa = BSUtil.andNot(bsAtoms, bsAtomsDeleted); 221 bsCheck.and(bsa); 222 return bsCheck.equals(bsa); 223 } 224 resetBoundCount()225 public void resetBoundCount() { 226 bondCount = -1; 227 } 228 getBondCount()229 public int getBondCount() { 230 if (bondCount >= 0) 231 return bondCount; 232 Bond[] bonds = ms.bo; 233 bondCount = 0; 234 for (int i = ms.bondCount; --i >= 0;) 235 if (bonds[i].atom1.mi == modelIndex) 236 bondCount++; 237 return bondCount; 238 } 239 getChainCount(boolean countWater)240 public int getChainCount(boolean countWater) { 241 if (chainCount > 1 && !countWater) 242 for (int i = 0; i < chainCount; i++) 243 if (chains[i].chainID == '\0') 244 return chainCount - 1; 245 return chainCount; 246 } 247 calcSelectedGroupsCount(BS bsSelected)248 void calcSelectedGroupsCount(BS bsSelected) { 249 for (int i = chainCount; --i >= 0;) 250 chains[i].calcSelectedGroupsCount(bsSelected); 251 } 252 getGroupCount()253 public int getGroupCount() { 254 if (groupCount < 0) { 255 groupCount = 0; 256 for (int i = chainCount; --i >= 0;) 257 groupCount += chains[i].groupCount; 258 } 259 return groupCount; 260 } 261 getChainAt(int i)262 public Chain getChainAt(int i) { 263 return (i < chainCount ? chains[i] : null); 264 } 265 getChain(int chainID)266 Chain getChain(int chainID) { 267 for (int i = chainCount; --i >= 0;) { 268 Chain chain = chains[i]; 269 if (chain.chainID == chainID) 270 return chain; 271 } 272 return null; 273 } 274 275 /** 276 * Something has changed; clear the DSSR cache and possibly remove DSSR entirely. 277 * 278 * 279 * @param totally set TRUE if atoms have moved so we force a new DSSR calculation. 280 */ resetDSSR(boolean totally)281 public void resetDSSR(boolean totally) { 282 dssrCache = null; 283 if (totally) 284 auxiliaryInfo.remove("dssr"); 285 } 286 fixIndices(int modelIndex, int nAtomsDeleted, BS bsDeleted)287 public void fixIndices(int modelIndex, int nAtomsDeleted, BS bsDeleted) { 288 // also in BioModel 289 fixIndicesM(modelIndex, nAtomsDeleted, bsDeleted); 290 } 291 fixIndicesM(int modelIndex, int nAtomsDeleted, BS bsDeleted)292 protected void fixIndicesM(int modelIndex, int nAtomsDeleted, BS bsDeleted) { 293 if (dataSourceFrame > modelIndex) 294 dataSourceFrame--; 295 if (trajectoryBaseIndex > modelIndex) 296 trajectoryBaseIndex--; 297 firstAtomIndex -= nAtomsDeleted; 298 for (int i = 0; i < chainCount; i++) 299 chains[i].fixIndices(nAtomsDeleted, bsDeleted); 300 BSUtil.deleteBits(bsAtoms, bsDeleted); 301 BSUtil.deleteBits(bsAtomsDeleted, bsDeleted); 302 } 303 freeze()304 public boolean freeze() { 305 freezeM(); 306 return false; 307 } 308 freezeM()309 protected void freezeM() { 310 for (int i = 0; i < chainCount; i++) 311 if (chains[i].groupCount == 0) { 312 for (int j = i + 1; j < chainCount; j++) 313 chains[j - 1] = chains[j]; 314 chainCount--; 315 } 316 chains = (Chain[]) AU.arrayCopyObject(chains, chainCount); 317 groupCount = -1; 318 getGroupCount(); 319 for (int i = 0; i < chainCount; ++i) 320 chains[i].groups = (Group[]) AU.arrayCopyObject(chains[i].groups, 321 chains[i].groupCount); 322 } 323 324 } 325