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