JAL-1645 source formatting and organise imports
[jalview.git] / src / ext / edu / ucsf / rbvi / strucviz2 / ChimeraModel.java
1 package ext.edu.ucsf.rbvi.strucviz2;
2
3 import java.awt.Color;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.HashSet;
7 import java.util.List;
8 import java.util.Set;
9 import java.util.TreeMap;
10
11 import ext.edu.ucsf.rbvi.strucviz2.StructureManager.ModelType;
12
13 /**
14  * This class provides the implementation for the ChimeraModel, ChimeraChain,
15  * and ChimeraResidue objects
16  * 
17  * @author scooter
18  * 
19  */
20 public class ChimeraModel implements ChimeraStructuralObject
21 {
22
23   private String name; // The name of this model
24
25   private ModelType type; // The type of the model
26
27   private int modelNumber; // The model number
28
29   private int subModelNumber; // The sub-model number
30
31   private Color modelColor = null; // The color of this model (from Chimera)
32
33   private Object userData = null; // User data associated with this model
34
35   private boolean selected = false; // The selected state of this model
36
37   private TreeMap<String, ChimeraChain> chainMap; // The list of chains
38
39   // private TreeMap<String, ChimeraResidue> residueMap; // The list of residues
40   private HashSet<ChimeraResidue> funcResidues; // List of functional residues
41
42   /**
43    * Constructor to create a model
44    * 
45    * @param name
46    *          the name of this model
47    * @param color
48    *          the model Color
49    * @param modelNumber
50    *          the model number
51    * @param subModelNumber
52    *          the sub-model number
53    */
54   public ChimeraModel(String name, ModelType type, int modelNumber,
55           int subModelNumber)
56   {
57     this.name = name;
58     this.type = type;
59     this.modelNumber = modelNumber;
60     this.subModelNumber = subModelNumber;
61
62     this.chainMap = new TreeMap<String, ChimeraChain>();
63     this.funcResidues = new HashSet<ChimeraResidue>();
64   }
65
66   /**
67    * Constructor to create a model from the Chimera input line
68    * 
69    * @param inputLine
70    *          Chimera input line from which to construct this model
71    */
72   // TODO: [Optional] How to distinguish between PDB and MODBASE?
73   // invoked when listing models: listm type molecule; lists level molecule
74   // line = model id #0 type Molecule name 1ert
75   public ChimeraModel(String inputLine)
76   {
77     this.name = ChimUtils.parseModelName(inputLine);
78     // TODO: [Optional] Write a separate method to get model type
79     if (name.startsWith("smiles"))
80     {
81       this.type = ModelType.SMILES;
82     }
83     else
84     {
85       this.type = ModelType.PDB_MODEL;
86     }
87     this.modelNumber = ChimUtils.parseModelNumber(inputLine)[0];
88     this.subModelNumber = ChimUtils.parseModelNumber(inputLine)[1];
89
90     this.chainMap = new TreeMap<String, ChimeraChain>();
91     this.funcResidues = new HashSet<ChimeraResidue>();
92   }
93
94   /**
95    * Add a residue to this model
96    * 
97    * @param residue
98    *          to add to the model
99    */
100   public void addResidue(ChimeraResidue residue)
101   {
102     residue.setChimeraModel(this);
103     // residueMap.put(residue.getIndex(), residue);
104     String chainId = residue.getChainId();
105     if (chainId != null)
106     {
107       addResidue(chainId, residue);
108     }
109     else
110     {
111       addResidue("_", residue);
112     }
113     // Put it in our map so that we can return it in order
114     // residueMap.put(residue.getIndex(), residue);
115   }
116
117   /**
118    * Add a residue to a chain in this model. If the chain associated with
119    * chainId doesn't exist, it will be created.
120    * 
121    * @param chainId
122    *          to add the residue to
123    * @param residue
124    *          to add to the chain
125    */
126   public void addResidue(String chainId, ChimeraResidue residue)
127   {
128     ChimeraChain chain = null;
129     if (!chainMap.containsKey(chainId))
130     {
131       chain = new ChimeraChain(this.modelNumber, this.subModelNumber,
132               chainId);
133       chain.setChimeraModel(this);
134       chainMap.put(chainId, chain);
135     }
136     else
137     {
138       chain = chainMap.get(chainId);
139     }
140     chain.addResidue(residue);
141   }
142
143   /**
144    * Get the ChimeraModel (required for ChimeraStructuralObject interface)
145    * 
146    * @return ChimeraModel
147    */
148   public ChimeraModel getChimeraModel()
149   {
150     return this;
151   }
152
153   /**
154    * Get the model color of this model
155    * 
156    * @return model color of this model
157    */
158   public Color getModelColor()
159   {
160     return this.modelColor;
161   }
162
163   /**
164    * Set the color of this model
165    * 
166    * @param color
167    *          Color of this model
168    */
169   public void setModelColor(Color color)
170   {
171     this.modelColor = color;
172   }
173
174   /**
175    * Return the name of this model
176    * 
177    * @return model name
178    */
179   public String getModelName()
180   {
181     return name;
182   }
183
184   /**
185    * Set the name of this model
186    * 
187    * @param name
188    *          model name
189    */
190   public void setModelName(String name)
191   {
192     this.name = name;
193   }
194
195   /**
196    * Get the model number of this model
197    * 
198    * @return integer model number
199    */
200   public int getModelNumber()
201   {
202     return modelNumber;
203   }
204
205   /**
206    * Set the model number of this model
207    * 
208    * @param modelNumber
209    *          integer model number
210    */
211   public void setModelNumber(int modelNumber)
212   {
213     this.modelNumber = modelNumber;
214   }
215
216   /**
217    * Get the sub-model number of this model
218    * 
219    * @return integer sub-model number
220    */
221   public int getSubModelNumber()
222   {
223     return subModelNumber;
224   }
225
226   /**
227    * Set the sub-model number of this model
228    * 
229    * @param subModelNumber
230    *          integer model number
231    */
232   public void setSubModelNumber(int subModelNumber)
233   {
234     this.subModelNumber = subModelNumber;
235   }
236
237   public ModelType getModelType()
238   {
239     return type;
240   }
241
242   public void setModelType(ModelType type)
243   {
244     this.type = type;
245   }
246
247   public HashSet<ChimeraResidue> getFuncResidues()
248   {
249     return funcResidues;
250   }
251
252   public void setFuncResidues(List<String> residues)
253   {
254     for (String residue : residues)
255     {
256       for (ChimeraChain chain : getChains())
257       {
258         if (residue.indexOf("-") > 0)
259         {
260           funcResidues.addAll(chain.getResidueRange(residue));
261         }
262         else
263         {
264           funcResidues.add(chain.getResidue(residue));
265         }
266       }
267     }
268   }
269
270   /**
271    * Get the user data for this model
272    * 
273    * @return user data
274    */
275   public Object getUserData()
276   {
277     return userData;
278   }
279
280   /**
281    * Set the user data for this model
282    * 
283    * @param data
284    *          user data to associate with this model
285    */
286   public void setUserData(Object data)
287   {
288     this.userData = data;
289   }
290
291   /**
292    * Return the selected state of this model
293    * 
294    * @return the selected state
295    */
296   public boolean isSelected()
297   {
298     return selected;
299   }
300
301   /**
302    * Set the selected state of this model
303    * 
304    * @param selected
305    *          a boolean to set the selected state to
306    */
307   public void setSelected(boolean selected)
308   {
309     this.selected = selected;
310   }
311
312   /**
313    * Return the chains in this model as a List
314    * 
315    * @return the chains in this model as a list
316    */
317   public List<ChimeraStructuralObject> getChildren()
318   {
319     return new ArrayList<ChimeraStructuralObject>(chainMap.values());
320   }
321
322   /**
323    * Return the chains in this model as a colleciton
324    * 
325    * @return the chains in this model
326    */
327   public Collection<ChimeraChain> getChains()
328   {
329     return chainMap.values();
330   }
331
332   /**
333    * Get the number of chains in this model
334    * 
335    * @return integer chain count
336    */
337   public int getChainCount()
338   {
339     return chainMap.size();
340   }
341
342   /**
343    * Get the list of chain names associated with this model
344    * 
345    * @return return the list of chain names for this model
346    */
347   public Collection<String> getChainNames()
348   {
349     return chainMap.keySet();
350   }
351
352   /**
353    * Get the residues associated with this model
354    * 
355    * @return the list of residues in this model
356    */
357   public Collection<ChimeraResidue> getResidues()
358   {
359     Collection<ChimeraResidue> residues = new ArrayList<ChimeraResidue>();
360     for (ChimeraChain chain : getChains())
361     {
362       residues.addAll(chain.getResidues());
363     }
364     return residues;
365   }
366
367   /**
368    * Get the number of residues in this model
369    * 
370    * @return integer residues count
371    */
372   public int getResidueCount()
373   {
374     int count = 0;
375     for (ChimeraChain chain : getChains())
376     {
377       count += chain.getResidueCount();
378     }
379     return count;
380   }
381
382   /**
383    * Get a specific chain from the model
384    * 
385    * @param chain
386    *          the ID of the chain to return
387    * @return ChimeraChain associated with the chain
388    */
389   public ChimeraChain getChain(String chain)
390   {
391     if (chainMap.containsKey(chain))
392     {
393       return chainMap.get(chain);
394     }
395     return null;
396   }
397
398   /**
399    * Return a specific residue based on its index
400    * 
401    * @param index
402    *          of the residue to return
403    * @return the residue associated with that index
404    */
405   public ChimeraResidue getResidue(String chainId, String index)
406   {
407     if (chainMap.containsKey(chainId))
408     {
409       return chainMap.get(chainId).getResidue(index);
410     }
411     return null;
412   }
413
414   /**
415    * Checks if this model has selected children.
416    */
417   public boolean hasSelectedChildren()
418   {
419     if (selected)
420     {
421       return true;
422     }
423     else
424     {
425       for (ChimeraChain chain : getChains())
426       {
427         if (chain.hasSelectedChildren())
428         {
429           return true;
430         }
431       }
432     }
433     return false;
434   }
435
436   /**
437    * Return the list of selected residues
438    * 
439    * @return all selected residues
440    */
441   public List<ChimeraResidue> getSelectedResidues()
442   {
443     List<ChimeraResidue> residueList = new ArrayList<ChimeraResidue>();
444     for (ChimeraChain chain : getChains())
445     {
446       if (selected)
447       {
448         residueList.addAll(chain.getSelectedResidues());
449       }
450       else
451       {
452         residueList.addAll(getResidues());
453       }
454     }
455     return residueList;
456   }
457
458   /**
459    * Return the Chimera specification for this model.
460    */
461   public String toSpec()
462   {
463     if (subModelNumber == 0)
464       return ("#" + modelNumber);
465     return ("#" + modelNumber + "." + subModelNumber);
466   }
467
468   /**
469    * Return a string representation for the model. Shorten if longer than 100
470    * characters.
471    */
472   public String toString()
473   {
474     String modelName = "";
475     // TODO: [Optional] Change cutoff for shortening model names in the
476     // structure naviagator dialog
477     if (getChainCount() > 0)
478     {
479       modelName = "Model " + toSpec() + " " + name + " (" + getChainCount()
480               + " chains, " + getResidueCount() + " residues)";
481     }
482     else if (getResidueCount() > 0)
483     {
484       modelName = "Model " + toSpec() + " " + name + " ("
485               + getResidueCount() + " residues)";
486     }
487     else
488     {
489       modelName = "Model " + toSpec() + " " + name + "";
490     }
491
492     Set<String> networkNames = new HashSet<String>();
493     Set<String> nodeNames = new HashSet<String>();
494     Set<String> edgeNames = new HashSet<String>();
495
496     String cytoName = " [";
497     if (networkNames.size() > 0)
498     {
499       if (networkNames.size() == 1)
500       {
501         cytoName += "Network {";
502       }
503       else if (networkNames.size() > 1)
504       {
505         cytoName += "Networks {";
506       }
507       for (String cName : networkNames)
508       {
509         cytoName += cName + ",";
510       }
511       cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
512     }
513     if (nodeNames.size() > 0)
514     {
515       if (nodeNames.size() == 1)
516       {
517         cytoName += "Node {";
518       }
519       else if (nodeNames.size() > 1)
520       {
521         cytoName += "Nodes {";
522       }
523       for (String cName : nodeNames)
524       {
525         cytoName += cName + ",";
526       }
527       cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
528     }
529     if (edgeNames.size() > 0)
530     {
531       if (edgeNames.size() == 1)
532       {
533         cytoName += "Edge {";
534       }
535       else if (edgeNames.size() > 1)
536       {
537         cytoName += "Edges {";
538       }
539       for (String cName : edgeNames)
540       {
541         cytoName += cName + ",";
542       }
543       cytoName = cytoName.substring(0, cytoName.length() - 1) + "}, ";
544     }
545     if (cytoName.endsWith(", "))
546     {
547       cytoName = cytoName.substring(0, cytoName.length() - 2);
548     }
549     cytoName += "]";
550     String nodeName = modelName + cytoName;
551     if (nodeName.length() > 100)
552     {
553       nodeName = nodeName.substring(0, 100) + "...";
554     }
555     return nodeName;
556   }
557 }