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.util.ArrayList;
36 import java.util.List;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
40 import org.slf4j.LoggerFactory;
43 * This class provides the implementation for the ChimeraResidue, object
49 public class ChimeraResidue implements ChimeraStructuralObject,
50 Comparable<ChimeraResidue>
54 public static final int SINGLE_LETTER = 0; // Display residues as a single
57 public static final int THREE_LETTER = 1; // Display residues as three letters
59 public static final int FULL_NAME = 2; // Display full residue names
61 private String type; // Residue type
63 private String index; // Residue index
65 private String chainId; // ChainID for this residue
67 private int modelNumber; // model number for this residue
69 private int subModelNumber; // sub-model number for this residue
71 protected int residueNumber;
73 protected String insertionCode;
75 private ChimeraModel chimeraModel; // ChimeraModel the residue is part of
77 private Object userData; // user data to associate with this residue
79 // public static HashMap<String, String> aaNames = null; // a map of amino
82 private static int displayType = THREE_LETTER; // the current display type
84 private boolean selected = false; // the selection state
87 * Constructor to create a new ChimeraResidue
92 * the index of the residue
94 * the model number this residue is part of
96 public ChimeraResidue(String type, String index, int modelNumber)
98 this(type, index, modelNumber, 0);
102 * Constructor to create a new ChimeraResidue
107 * the index of the residue
109 * the model number this residue is part of
110 * @param subModelNumber
111 * the sub-model number this residue is part of
113 public ChimeraResidue(String type, String index, int modelNumber,
118 this.modelNumber = modelNumber;
119 this.subModelNumber = subModelNumber;
120 splitInsertionCode(this.index);
121 // if (aaNames == null) {
127 * Constructor to create a new ChimeraResidue from an input line
129 * @param chimeraInputLine
130 * a Chimera residue description
132 // invoked when listing (selected) residues: listr spec #0; lists level
134 // Line: residue id #0:37.A type MET
135 public ChimeraResidue(String chimeraInputLine)
138 String[] split1 = chimeraInputLine.split(":");
140 // First half has model number -- get the number
141 int numberOffset = split1[0].indexOf('#');
142 String model = split1[0].substring(numberOffset + 1);
143 int decimalOffset = model.indexOf('.'); // Do we have a sub-model?
146 this.subModelNumber = 0;
147 if (decimalOffset > 0)
149 this.subModelNumber = Integer.parseInt(model
150 .substring(decimalOffset + 1));
151 this.modelNumber = Integer.parseInt(model.substring(0,
156 this.modelNumber = Integer.parseInt(model);
158 } catch (Exception e)
160 LoggerFactory.getLogger(ChimeraResidue.class).error(
161 "Unexpected return from Chimera: " + model);
162 this.modelNumber = -1;
165 // Second half has residue info: index & type
166 String[] rTokens = split1[1].split(" ");
167 this.type = rTokens[2];
169 String[] iTokens = rTokens[0].split("\\.");
170 if (iTokens.length > 0)
172 this.index = iTokens[0];
174 // Careful, might or might not have a chainID
175 if (iTokens.length > 1)
176 this.chainId = iTokens[1];
181 this.index = rTokens[0];
183 splitInsertionCode(this.index);
187 * Set the selected state for this residue
190 * the selection state to set
192 public void setSelected(boolean selected)
194 this.selected = selected;
198 * Return the selected state of this residue
200 * @return the selected state
202 public boolean isSelected()
208 * Return an array made up of this residue (required for
209 * ChimeraStructuralObject interface
211 * @return a List with this residue as its sole member
213 public List<ChimeraStructuralObject> getChildren()
215 List<ChimeraStructuralObject> v = new ArrayList<ChimeraStructuralObject>();
221 * Return the string representation of this residue as follows:
222 * "<i>residue_name</i> <i>index</i>" where <i>residue_name</i> could be
223 * either the single letter, three letter, or full name representation of the
226 * @return the string representation
228 public String displayName()
234 * Return the string representation of this residue as follows:
235 * "<i>residue_name</i> <i>index</i>" where <i>residue_name</i> could be
236 * either the single letter, three letter, or full name representation of the
239 * @return the string representation
241 public String toString()
243 if (displayType == FULL_NAME)
245 return (ChimUtils.toFullName(type) + " " + index);
247 else if (displayType == SINGLE_LETTER)
249 return (ChimUtils.toSingleLetter(type) + " " + index);
251 else if (displayType == THREE_LETTER)
253 return (ChimUtils.toThreeLetter(type) + " " + index);
257 return (type + " " + index);
262 * Return the Chimera specification for this Residue
264 * @return Chimera specification
266 public String toSpec()
268 if (!chainId.equals("_"))
269 return ("#" + modelNumber + ":" + index + "." + chainId);
271 return ("#" + modelNumber + ":" + index + ".");
275 * Get the index of this residue
277 * @return residue index
279 public String getIndex()
285 * Get the chainID for this residue
287 * @return String value of the chainId
289 public String getChainId()
295 * Get the type for this residue
297 * @return residue type
299 public String getType()
305 * Get the model number for this residue
307 * @return the model number
309 public int getModelNumber()
311 return this.modelNumber;
315 * Get the sub-model number for this residue
317 * @return the sub-model number
319 public int getSubModelNumber()
321 return this.subModelNumber;
325 * Get the model this residue is part of
327 * @return the ChimeraModel
329 public ChimeraModel getChimeraModel()
331 return this.chimeraModel;
335 * Set the model this residue is part of
337 * @param chimeraModel
338 * the ChimeraModel this model is part of
340 public void setChimeraModel(ChimeraModel chimeraModel)
342 this.chimeraModel = chimeraModel;
346 * Get the user data for this residue
350 public Object getUserData()
356 * Set the user data for this Residue
359 * the user data to associate with this residue
361 public void setUserData(Object data)
363 this.userData = data;
366 public int compareTo(ChimeraResidue c2)
368 if (residueNumber < c2.residueNumber)
370 else if (residueNumber == c2.residueNumber)
372 if (insertionCode == null && c2.insertionCode == null)
374 else if (insertionCode == null)
376 else if (c2.insertionCode == null)
378 return (insertionCode.compareTo(c2.insertionCode));
383 public void splitInsertionCode(String residue)
385 // OK, split the index into number and insertion code
386 Pattern p = Pattern.compile("(\\d*)([A-Z]?)");
387 Matcher m = p.matcher(residue);
390 this.residueNumber = Integer.parseInt(m.group(1));
391 if (m.groupCount() > 1)
392 this.insertionCode = m.group(2);
394 this.insertionCode = null;
398 /**********************************************
400 *********************************************/
403 * Initialize the residue names
405 // private static void initNames() {
406 // // Create our residue name table
407 // aaNames = new HashMap<String, String>();
408 // aaNames.put("ALA", "A Ala Alanine N[C@@H](C)C(O)=O");
409 // aaNames.put("ARG", "R Arg Arginine N[C@@H](CCCNC(N)=N)C(O)=O");
410 // aaNames.put("ASN", "N Asn Asparagine N[C@@H](CC(N)=O)C(O)=O");
411 // aaNames.put("ASP", "D Asp Aspartic_acid N[C@@H](CC(O)=O)C(O)=O");
412 // aaNames.put("CYS", "C Cys Cysteine N[C@@H](CS)C(O)=O");
413 // aaNames.put("GLN", "Q Gln Glutamine N[C@H](C(O)=O)CCC(N)=O");
414 // aaNames.put("GLU", "E Glu Glumatic_acid N[C@H](C(O)=O)CCC(O)=O");
415 // aaNames.put("GLY", "G Gly Glycine NCC(O)=O");
416 // aaNames.put("HIS", "H His Histidine N[C@@H](CC1=CN=CN1)C(O)=O");
417 // aaNames.put("ILE", "I Ile Isoleucine N[C@]([C@H](C)CC)([H])C(O)=O");
418 // aaNames.put("LEU", "L Leu Leucine N[C@](CC(C)C)([H])C(O)=O");
419 // aaNames.put("LYS", "K Lys Lysine N[C@](CCCCN)([H])C(O)=O");
420 // aaNames.put("DLY", "K Dly D-Lysine NCCCC[C@@H](N)C(O)=O");
421 // aaNames.put("MET", "M Met Methionine N[C@](CCSC)([H])C(O)=O");
422 // aaNames.put("PHE", "F Phe Phenylalanine N[C@](CC1=CC=CC=C1)([H])C(O)=O");
423 // aaNames.put("PRO", "P Pro Proline OC([C@@]1([H])NCCC1)=O");
424 // aaNames.put("SER", "S Ser Serine OC[C@](C(O)=O)([H])N");
425 // aaNames.put("THR", "T Thr Threonine O[C@H](C)[C@](C(O)=O)([H])N");
426 // aaNames.put("TRP",
427 // "W Trp Tryptophan N[C@@]([H])(CC1=CN([H])C2=C1C=CC=C2)C(O)=O");
428 // aaNames.put("TYR", "Y Tyr Tyrosine N[C@@](C(O)=O)([H])CC1=CC=C(O)C=C1");
429 // aaNames.put("VAL", "V Val Valine N[C@@](C(O)=O)([H])C(C)C");
430 // aaNames.put("ASX", "B Asx Aspartic_acid_or_Asparagine");
431 // aaNames.put("GLX", "Z Glx Glutamine_or_Glutamic_acid");
432 // aaNames.put("XAA", "X Xaa Any_or_unknown_amino_acid");
433 // aaNames.put("HOH", "HOH HOH Water [H]O[H]");
437 * Set the display type.
442 public static void setDisplayType(int type)
447 public static int getDisplayType()
452 public boolean hasSelectedChildren()