1 package ext.edu.ucsf.rbvi.strucviz2;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.HashMap;
7 import java.util.HashSet;
11 import java.util.TreeMap;
13 import ext.edu.ucsf.rbvi.strucviz2.StructureManager.ModelType;
16 * This class provides the implementation for the ChimeraModel, ChimeraChain, and ChimeraResidue
22 public class ChimeraModel implements ChimeraStructuralObject {
24 private String name; // The name of this model
25 private ModelType type; // The type of the model
26 private int modelNumber; // The model number
27 private int subModelNumber; // The sub-model number
29 private Color modelColor = null; // The color of this model (from Chimera)
30 private Object userData = null; // User data associated with this model
31 private boolean selected = false; // The selected state of this model
33 private TreeMap<String, ChimeraChain> chainMap; // The list of chains
34 // private TreeMap<String, ChimeraResidue> residueMap; // The list of residues
35 private HashSet<ChimeraResidue> funcResidues; // List of functional residues
38 * Constructor to create a model
41 * the name of this model
46 * @param subModelNumber
47 * the sub-model number
49 public ChimeraModel(String name, ModelType type, int modelNumber, int subModelNumber) {
52 this.modelNumber = modelNumber;
53 this.subModelNumber = subModelNumber;
55 this.chainMap = new TreeMap<String, ChimeraChain>();
56 this.funcResidues = new HashSet<ChimeraResidue>();
60 * Constructor to create a model from the Chimera input line
63 * Chimera input line from which to construct this model
65 // TODO: [Optional] How to distinguish between PDB and MODBASE?
66 // invoked when listing models: listm type molecule; lists level molecule
67 // line = model id #0 type Molecule name 1ert
68 public ChimeraModel(String inputLine) {
69 this.name = ChimUtils.parseModelName(inputLine);
70 // TODO: [Optional] Write a separate method to get model type
71 if (name.startsWith("smiles")) {
72 this.type = ModelType.SMILES;
74 this.type = ModelType.PDB_MODEL;
76 this.modelNumber = ChimUtils.parseModelNumber(inputLine)[0];
77 this.subModelNumber = ChimUtils.parseModelNumber(inputLine)[1];
79 this.chainMap = new TreeMap<String, ChimeraChain>();
80 this.funcResidues = new HashSet<ChimeraResidue>();
84 * Add a residue to this model
89 public void addResidue(ChimeraResidue residue) {
90 residue.setChimeraModel(this);
91 // residueMap.put(residue.getIndex(), residue);
92 String chainId = residue.getChainId();
93 if (chainId != null) {
94 addResidue(chainId, residue);
96 addResidue("_", residue);
98 // Put it in our map so that we can return it in order
99 // residueMap.put(residue.getIndex(), residue);
103 * Add a residue to a chain in this model. If the chain associated with chainId doesn't exist,
104 * it will be created.
107 * to add the residue to
109 * to add to the chain
111 public void addResidue(String chainId, ChimeraResidue residue) {
112 ChimeraChain chain = null;
113 if (!chainMap.containsKey(chainId)) {
114 chain = new ChimeraChain(this.modelNumber, this.subModelNumber, chainId);
115 chain.setChimeraModel(this);
116 chainMap.put(chainId, chain);
118 chain = chainMap.get(chainId);
120 chain.addResidue(residue);
124 * Get the ChimeraModel (required for ChimeraStructuralObject interface)
126 * @return ChimeraModel
128 public ChimeraModel getChimeraModel() {
133 * Get the model color of this model
135 * @return model color of this model
137 public Color getModelColor() {
138 return this.modelColor;
142 * Set the color of this model
145 * Color of this model
147 public void setModelColor(Color color) {
148 this.modelColor = color;
152 * Return the name of this model
156 public String getModelName() {
161 * Set the name of this model
166 public void setModelName(String name) {
171 * Get the model number of this model
173 * @return integer model number
175 public int getModelNumber() {
180 * Set the model number of this model
183 * integer model number
185 public void setModelNumber(int modelNumber) {
186 this.modelNumber = modelNumber;
190 * Get the sub-model number of this model
192 * @return integer sub-model number
194 public int getSubModelNumber() {
195 return subModelNumber;
199 * Set the sub-model number of this model
201 * @param subModelNumber
202 * integer model number
204 public void setSubModelNumber(int subModelNumber) {
205 this.subModelNumber = subModelNumber;
208 public ModelType getModelType() {
212 public void setModelType(ModelType type) {
216 public HashSet<ChimeraResidue> getFuncResidues() {
220 public void setFuncResidues(List<String> residues) {
221 for (String residue : residues) {
222 for (ChimeraChain chain : getChains()) {
223 if (residue.indexOf("-") > 0) {
224 funcResidues.addAll(chain.getResidueRange(residue));
226 funcResidues.add(chain.getResidue(residue));
233 * Get the user data for this model
237 public Object getUserData() {
242 * Set the user data for this model
245 * user data to associate with this model
247 public void setUserData(Object data) {
248 this.userData = data;
252 * Return the selected state of this model
254 * @return the selected state
256 public boolean isSelected() {
261 * Set the selected state of this model
264 * a boolean to set the selected state to
266 public void setSelected(boolean selected) {
267 this.selected = selected;
271 * Return the chains in this model as a List
273 * @return the chains in this model as a list
275 public List<ChimeraStructuralObject> getChildren() {
276 return new ArrayList<ChimeraStructuralObject>(chainMap.values());
280 * Return the chains in this model as a colleciton
282 * @return the chains in this model
284 public Collection<ChimeraChain> getChains() {
285 return chainMap.values();
289 * Get the number of chains in this model
291 * @return integer chain count
293 public int getChainCount() {
294 return chainMap.size();
298 * Get the list of chain names associated with this model
300 * @return return the list of chain names for this model
302 public Collection<String> getChainNames() {
303 return chainMap.keySet();
307 * Get the residues associated with this model
309 * @return the list of residues in this model
311 public Collection<ChimeraResidue> getResidues() {
312 Collection<ChimeraResidue> residues = new ArrayList<ChimeraResidue>();
313 for (ChimeraChain chain : getChains()) {
314 residues.addAll(chain.getResidues());
320 * Get the number of residues in this model
322 * @return integer residues count
324 public int getResidueCount() {
326 for (ChimeraChain chain : getChains()) {
327 count += chain.getResidueCount();
333 * Get a specific chain from the model
336 * the ID of the chain to return
337 * @return ChimeraChain associated with the chain
339 public ChimeraChain getChain(String chain) {
340 if (chainMap.containsKey(chain)) {
341 return chainMap.get(chain);
347 * Return a specific residue based on its index
350 * of the residue to return
351 * @return the residue associated with that index
353 public ChimeraResidue getResidue(String chainId, String index) {
354 if (chainMap.containsKey(chainId)) {
355 return chainMap.get(chainId).getResidue(index);
361 * Checks if this model has selected children.
363 public boolean hasSelectedChildren() {
367 for (ChimeraChain chain : getChains()) {
368 if (chain.hasSelectedChildren()) {
377 * Return the list of selected residues
379 * @return all selected residues
381 public List<ChimeraResidue> getSelectedResidues() {
382 List<ChimeraResidue> residueList = new ArrayList<ChimeraResidue>();
383 for (ChimeraChain chain : getChains()) {
385 residueList.addAll(chain.getSelectedResidues());
387 residueList.addAll(getResidues());
395 * Return the Chimera specification for this model.
397 public String toSpec() {
398 if (subModelNumber == 0)
399 return ("#" + modelNumber);
400 return ("#" + modelNumber + "." + subModelNumber);
404 * Return a string representation for the model. Shorten if longer than 100 characters.
406 public String toString() {
407 String modelName = "";
408 // TODO: [Optional] Change cutoff for shortening model names in the structure naviagator dialog
409 if (getChainCount() > 0) {
410 modelName = "Model " + toSpec() + " " + name + " (" + getChainCount() + " chains, "
411 + getResidueCount() + " residues)";
412 } else if (getResidueCount() > 0) {
413 modelName = "Model " + toSpec() + " " + name + " (" + getResidueCount() + " residues)";
415 modelName = "Model " + toSpec() + " " + name + "";
418 Set<String> networkNames = new HashSet<String>();
419 Set<String> nodeNames = new HashSet<String>();
420 Set<String> edgeNames = new HashSet<String>();
422 String cytoName = " [";
423 if (networkNames.size() > 0) {
424 if (networkNames.size() == 1) {
425 cytoName += "Network {";
426 } else if (networkNames.size() > 1) {
427 cytoName += "Networks {";
429 for (String cName : networkNames) {
430 cytoName += cName + ",";
432 cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
434 if (nodeNames.size() > 0) {
435 if (nodeNames.size() == 1) {
436 cytoName += "Node {";
437 } else if (nodeNames.size() > 1) {
438 cytoName += "Nodes {";
440 for (String cName : nodeNames) {
441 cytoName += cName + ",";
443 cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
445 if (edgeNames.size() > 0) {
446 if (edgeNames.size() == 1) {
447 cytoName += "Edge {";
448 } else if (edgeNames.size() > 1) {
449 cytoName += "Edges {";
451 for (String cName : edgeNames) {
452 cytoName += cName + ",";
454 cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
456 if (cytoName.endsWith(", ")) {
457 cytoName = cytoName.substring(0, cytoName.length() - 2);
460 String nodeName = modelName + cytoName;
461 if (nodeName.length() > 100) {
462 nodeName = nodeName.substring(0, 100) + "...";