3 * Copyright (c) 2006 The Regents of the University of California.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions, and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 * 3. Redistributions must acknowledge that this software was
16 * originally developed by the UCSF Computer Graphics Laboratory
17 * under support by the NIH National Center for Research Resources,
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 package ext.edu.ucsf.rbvi.strucviz2;
35 import java.awt.Color;
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.HashSet;
39 import java.util.List;
41 import java.util.TreeMap;
43 import ext.edu.ucsf.rbvi.strucviz2.StructureManager.ModelType;
46 * This class provides the implementation for the ChimeraModel, ChimeraChain,
47 * and ChimeraResidue objects
52 public class ChimeraModel implements ChimeraStructuralObject
55 private String name; // The name of this model
57 private ModelType type; // The type of the model
59 private int modelNumber; // The model number
61 private int subModelNumber; // The sub-model number
63 private Color modelColor = null; // The color of this model (from Chimera)
65 private Object userData = null; // User data associated with this model
67 private boolean selected = false; // The selected state of this model
69 private TreeMap<String, ChimeraChain> chainMap; // The list of chains
71 // private TreeMap<String, ChimeraResidue> residueMap; // The list of residues
72 private HashSet<ChimeraResidue> funcResidues; // List of functional residues
75 * Constructor to create a model
78 * the name of this model
83 * @param subModelNumber
84 * the sub-model number
86 public ChimeraModel(String name, ModelType type, int modelNumber,
91 this.modelNumber = modelNumber;
92 this.subModelNumber = subModelNumber;
94 this.chainMap = new TreeMap<String, ChimeraChain>();
95 this.funcResidues = new HashSet<ChimeraResidue>();
99 * Constructor to create a model from the Chimera input line
102 * Chimera input line from which to construct this model
104 // TODO: [Optional] How to distinguish between PDB and MODBASE?
105 // invoked when listing models: listm type molecule; lists level molecule
106 // line = model id #0 type Molecule name 1ert
107 public ChimeraModel(String inputLine)
109 this.name = ChimUtils.parseModelName(inputLine);
110 // TODO: [Optional] Write a separate method to get model type
111 if (name.startsWith("smiles"))
113 this.type = ModelType.SMILES;
117 this.type = ModelType.PDB_MODEL;
119 this.modelNumber = ChimUtils.parseModelNumber(inputLine)[0];
120 this.subModelNumber = ChimUtils.parseModelNumber(inputLine)[1];
122 this.chainMap = new TreeMap<String, ChimeraChain>();
123 this.funcResidues = new HashSet<ChimeraResidue>();
127 * Add a residue to this model
130 * to add to the model
132 public void addResidue(ChimeraResidue residue)
134 residue.setChimeraModel(this);
135 // residueMap.put(residue.getIndex(), residue);
136 String chainId = residue.getChainId();
139 addResidue(chainId, residue);
143 addResidue("_", residue);
145 // Put it in our map so that we can return it in order
146 // residueMap.put(residue.getIndex(), residue);
150 * Add a residue to a chain in this model. If the chain associated with
151 * chainId doesn't exist, it will be created.
154 * to add the residue to
156 * to add to the chain
158 public void addResidue(String chainId, ChimeraResidue residue)
160 ChimeraChain chain = null;
161 if (!chainMap.containsKey(chainId))
163 chain = new ChimeraChain(this.modelNumber, this.subModelNumber,
165 chain.setChimeraModel(this);
166 chainMap.put(chainId, chain);
170 chain = chainMap.get(chainId);
172 chain.addResidue(residue);
176 * Get the ChimeraModel (required for ChimeraStructuralObject interface)
178 * @return ChimeraModel
181 public ChimeraModel getChimeraModel()
187 * Get the model color of this model
189 * @return model color of this model
191 public Color getModelColor()
193 return this.modelColor;
197 * Set the color of this model
200 * Color of this model
202 public void setModelColor(Color color)
204 this.modelColor = color;
208 * Return the name of this model
212 public String getModelName()
218 * Set the name of this model
223 public void setModelName(String name)
229 * Get the model number of this model
231 * @return integer model number
233 public int getModelNumber()
239 * Set the model number of this model
242 * integer model number
244 public void setModelNumber(int modelNumber)
246 this.modelNumber = modelNumber;
250 * Get the sub-model number of this model
252 * @return integer sub-model number
254 public int getSubModelNumber()
256 return subModelNumber;
260 * Set the sub-model number of this model
262 * @param subModelNumber
263 * integer model number
265 public void setSubModelNumber(int subModelNumber)
267 this.subModelNumber = subModelNumber;
270 public ModelType getModelType()
275 public void setModelType(ModelType type)
280 public HashSet<ChimeraResidue> getFuncResidues()
285 public void setFuncResidues(List<String> residues)
287 for (String residue : residues)
289 for (ChimeraChain chain : getChains())
291 if (residue.indexOf("-") > 0)
293 funcResidues.addAll(chain.getResidueRange(residue));
297 funcResidues.add(chain.getResidue(residue));
304 * Get the user data for this model
309 public Object getUserData()
315 * Set the user data for this model
318 * user data to associate with this model
321 public void setUserData(Object data)
323 this.userData = data;
327 * Return the selected state of this model
329 * @return the selected state
332 public boolean isSelected()
338 * Set the selected state of this model
341 * a boolean to set the selected state to
344 public void setSelected(boolean selected)
346 this.selected = selected;
350 * Return the chains in this model as a List
352 * @return the chains in this model as a list
355 public List<ChimeraStructuralObject> getChildren()
357 return new ArrayList<ChimeraStructuralObject>(chainMap.values());
361 * Return the chains in this model as a colleciton
363 * @return the chains in this model
365 public Collection<ChimeraChain> getChains()
367 return chainMap.values();
371 * Get the number of chains in this model
373 * @return integer chain count
375 public int getChainCount()
377 return chainMap.size();
381 * Get the list of chain names associated with this model
383 * @return return the list of chain names for this model
385 public Collection<String> getChainNames()
387 return chainMap.keySet();
391 * Get the residues associated with this model
393 * @return the list of residues in this model
395 public Collection<ChimeraResidue> getResidues()
397 Collection<ChimeraResidue> residues = new ArrayList<ChimeraResidue>();
398 for (ChimeraChain chain : getChains())
400 residues.addAll(chain.getResidues());
406 * Get the number of residues in this model
408 * @return integer residues count
410 public int getResidueCount()
413 for (ChimeraChain chain : getChains())
415 count += chain.getResidueCount();
421 * Get a specific chain from the model
424 * the ID of the chain to return
425 * @return ChimeraChain associated with the chain
427 public ChimeraChain getChain(String chain)
429 if (chainMap.containsKey(chain))
431 return chainMap.get(chain);
437 * Return a specific residue based on its index
440 * of the residue to return
441 * @return the residue associated with that index
443 public ChimeraResidue getResidue(String chainId, String index)
445 if (chainMap.containsKey(chainId))
447 return chainMap.get(chainId).getResidue(index);
453 * Checks if this model has selected children.
456 public boolean hasSelectedChildren()
464 for (ChimeraChain chain : getChains())
466 if (chain.hasSelectedChildren())
476 * Return the list of selected residues
478 * @return all selected residues
480 public List<ChimeraResidue> getSelectedResidues()
482 List<ChimeraResidue> residueList = new ArrayList<ChimeraResidue>();
483 for (ChimeraChain chain : getChains())
487 residueList.addAll(chain.getSelectedResidues());
491 residueList.addAll(getResidues());
498 * Return the Chimera specification for this model.
501 public String toSpec()
503 if (subModelNumber == 0)
505 return ("#" + modelNumber);
507 return ("#" + modelNumber + "." + subModelNumber);
511 * Return a string representation for the model. Shorten if longer than 100
515 public String toString()
517 String modelName = "";
518 // TODO: [Optional] Change cutoff for shortening model names in the
519 // structure naviagator dialog
520 if (getChainCount() > 0)
522 modelName = "Model " + toSpec() + " " + name + " (" + getChainCount()
523 + " chains, " + getResidueCount() + " residues)";
525 else if (getResidueCount() > 0)
527 modelName = "Model " + toSpec() + " " + name + " ("
528 + getResidueCount() + " residues)";
532 modelName = "Model " + toSpec() + " " + name + "";
535 Set<String> networkNames = new HashSet<String>();
536 Set<String> nodeNames = new HashSet<String>();
537 Set<String> edgeNames = new HashSet<String>();
539 String cytoName = " [";
540 if (networkNames.size() > 0)
542 if (networkNames.size() == 1)
544 cytoName += "Network {";
546 else if (networkNames.size() > 1)
548 cytoName += "Networks {";
550 for (String cName : networkNames)
552 cytoName += cName + ",";
554 cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
556 if (nodeNames.size() > 0)
558 if (nodeNames.size() == 1)
560 cytoName += "Node {";
562 else if (nodeNames.size() > 1)
564 cytoName += "Nodes {";
566 for (String cName : nodeNames)
568 cytoName += cName + ",";
570 cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
572 if (edgeNames.size() > 0)
574 if (edgeNames.size() == 1)
576 cytoName += "Edge {";
578 else if (edgeNames.size() > 1)
580 cytoName += "Edges {";
582 for (String cName : edgeNames)
584 cytoName += cName + ",";
586 cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
588 if (cytoName.endsWith(", "))
590 cytoName = cytoName.substring(0, cytoName.length() - 2);
593 String nodeName = modelName + cytoName;
594 if (nodeName.length() > 100)
596 nodeName = nodeName.substring(0, 100) + "...";
602 public boolean equals(Object otherChimeraModel)
604 if (!(otherChimeraModel instanceof ChimeraModel))
608 ChimeraModel otherCM = ((ChimeraModel) otherChimeraModel);
609 return this.name.equals(otherCM.name)
610 && this.modelNumber == otherCM.modelNumber
611 && this.type == otherCM.type;
615 public int hashCode()
618 hashCode = hashCode * 37 + this.name.hashCode();
619 hashCode = hashCode * 37 + this.type.hashCode();
620 hashCode = (hashCode * 37) + modelNumber;