Clover icon

Coverage Report

  1. Project Clover database Wed Nov 6 2024 14:47:21 GMT
  2. Package ext.edu.ucsf.rbvi.strucviz2

File ChimUtils.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart0.png
59% of files have more coverage

Code metrics

180
356
24
1
1,045
776
149
0.42
14.83
24
6.21

Classes

Class Line # Actions
ChimUtils 47 356 149
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /* vim: set ts=2: */
2    /**
3    * Copyright (c) 2006 The Regents of the University of California.
4    * All rights reserved.
5    *
6    * Redistribution and use in source and binary forms, with or without
7    * modification, are permitted provided that the following conditions
8    * are met:
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,
18    * grant P41-RR01081.
19    *
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.
31    *
32    */
33    package ext.edu.ucsf.rbvi.strucviz2;
34   
35    import java.awt.Color;
36    import java.util.ArrayList;
37    import java.util.HashMap;
38    import java.util.List;
39    import java.util.Locale;
40    import java.util.Map;
41   
42    import org.slf4j.Logger;
43    import org.slf4j.LoggerFactory;
44   
45    import ext.edu.ucsf.rbvi.strucviz2.StructureManager.ModelType;
46   
 
47    public abstract class ChimUtils
48    {
49   
50    private static Logger logger = LoggerFactory.getLogger(ChimUtils.class);
51   
52    static int MAX_SUB_MODELS = 1000;
53   
54    public static final HashMap<String, String> aaNames;
55   
56    public static String RESIDUE_ATTR = "ChimeraResidue";
57   
58    public static String RINALYZER_ATTR = "RINalyzerResidue";
59   
60    public static String DEFAULT_STRUCTURE_KEY = "pdbFileName";
61   
62    /**
63    * Parse the model number returned by Chimera and return the int value
64    */
65    // invoked by the ChimeraModel constructor
66    // line = model id #0 type Molecule name 1ert
 
67  0 toggle public static int[] parseModelNumber(String inputLine)
68    {
69  0 int hash = inputLine.indexOf('#');
70  0 int space = inputLine.indexOf(' ', hash);
71  0 int decimal = inputLine.substring(hash + 1, space).indexOf('.');
72    // model number is between hash+1 and space
73  0 int modelNumber = -1;
74  0 int subModelNumber = 0;
75  0 try
76    {
77  0 if (decimal > 0)
78    {
79  0 subModelNumber = Integer
80    .parseInt(inputLine.substring(decimal + hash + 2, space));
81  0 space = decimal + hash + 1;
82    }
83  0 modelNumber = Integer.parseInt(inputLine.substring(hash + 1, space));
84    } catch (Exception e)
85    {
86  0 logger.warn("Unexpected return from Chimera: " + inputLine, e);
87    }
88  0 return new int[] { modelNumber, subModelNumber };
89    }
90   
91    /**
92    * Parse the model number returned by Chimera and return the int value
93    */
94    // invoked by openModel in ChimeraManager
95    // line: #1, chain A: hiv-1 protease
96    // line: Model 0 (filename)
 
97  0 toggle public static int[] parseOpenedModelNumber(String inputLine)
98    {
99  0 int hash = inputLine.indexOf('#');
100  0 int space = -1;
101  0 if (hash == (-1))
102    {
103  0 hash = inputLine.indexOf("Model");
104  0 if (hash >= 0)
105    {
106  0 hash = hash + 5;
107    }
108  0 space = inputLine.indexOf(' ', hash + 1);
109    }
110    else
111    {
112  0 space = inputLine.indexOf(',', hash);
113    }
114   
115  0 int decimal = inputLine.substring(hash + 1, space).indexOf('.');
116    // model number is between hash+1 and space
117  0 int modelNumber = -1;
118  0 int subModelNumber = 0;
119  0 try
120    {
121  0 if (decimal > 0)
122    {
123  0 subModelNumber = Integer
124    .parseInt(inputLine.substring(decimal + hash + 2, space));
125  0 space = decimal + hash + 1;
126    }
127  0 modelNumber = Integer.parseInt(inputLine.substring(hash + 1, space));
128    } catch (Exception e)
129    {
130  0 logger.warn("Unexpected return from Chimera: " + inputLine, e);
131    }
132  0 return new int[] { modelNumber, subModelNumber };
133    }
134   
135    /**
136    * Parse the model identifier returned by Chimera and return the String value
137    */
138    // invoked by the ChimeraModel constructor
139    // line = model id #0 type Molecule name 1ert
 
140  0 toggle public static String parseModelName(String inputLine)
141    {
142  0 int start = inputLine.indexOf("name ");
143  0 if (start < 0)
144    {
145  0 return null;
146    }
147    // Might get a quoted string (don't understand why, but there you have it)
148  0 if (inputLine.startsWith("\"", start + 5))
149    {
150  0 start += 6; // Skip over the first quote
151  0 int end = inputLine.lastIndexOf('"');
152  0 if (end >= 1)
153    {
154  0 return inputLine.substring(start, end);
155    }
156    else
157    {
158  0 return inputLine.substring(start);
159    }
160    }
161    else
162    {
163  0 return inputLine.substring(start + 5);
164    }
165    }
166   
 
167  0 toggle public static Color parseModelColor(String inputLine)
168    {
169  0 try
170    {
171  0 int colorStart = inputLine.indexOf("color ");
172  0 String colorString = inputLine.substring(colorStart + 6);
173  0 String[] rgbStrings = colorString.split(",");
174  0 float[] rgbValues = new float[4];
175  0 for (int i = 0; i < rgbStrings.length; i++)
176    {
177  0 Float f = Float.valueOf(rgbStrings[i]);
178  0 rgbValues[i] = f.floatValue();
179    }
180  0 if (rgbStrings.length == 4)
181    {
182  0 return new Color(rgbValues[0], rgbValues[1], rgbValues[2],
183    rgbValues[3]);
184    }
185    else
186    {
187  0 return new Color(rgbValues[0], rgbValues[1], rgbValues[2]);
188    }
189    } catch (Exception ex)
190    {
191  0 logger.warn("Unexpected return from Chimera: " + inputLine, ex);
192    }
193  0 return Color.white;
194    }
195   
196    /**
197    * Create the key to use for forming the model/submodel key into the modelHash
198    *
199    * @param model
200    * the model number
201    * @param subModel
202    * the submodel number
203    * @return the model key as an Integer
204    */
 
205  0 toggle public static Integer makeModelKey(int model, int subModel)
206    {
207  0 return Integer.valueOf(model * MAX_SUB_MODELS + subModel);
208    }
209   
210    // invoked by the getResdiue (parseConnectivityReplies in
211    // CreateStructureNetworkTask)
212    // atomSpec = #0:1.A or #1:96.B@N
 
213  0 toggle public static ChimeraModel getModel(String atomSpec,
214    ChimeraManager chimeraManager)
215    {
216    // System.out.println("getting model for "+atomSpec);
217  0 String[] split = atomSpec.split(":");
218    // No model specified....
219  0 if (split[0].length() == 0)
220    {
221  0 logger.info("Unexpected return from Chimera: " + atomSpec);
222  0 return null;
223    }
224    // System.out.println("model = "+split[0].substring(1));
225  0 int model = 0;
226  0 int submodel = 0;
227  0 try
228    {
229  0 String[] subSplit = split[0].substring(1).split("\\.");
230  0 if (subSplit.length > 0)
231    {
232  0 model = Integer.parseInt(subSplit[0]);
233    }
234    else
235    {
236  0 model = Integer.parseInt(split[0].substring(1));
237    }
238   
239  0 if (subSplit.length > 1)
240    {
241  0 submodel = Integer.parseInt(subSplit[1]);
242    }
243    } catch (Exception e)
244    {
245    // ignore
246  0 logger.warn("Unexpected return from Chimera: " + atomSpec, e);
247    }
248  0 return chimeraManager.getChimeraModel(model, submodel);
249    }
250   
251    // invoked by the parseConnectivityReplies in CreateStructureNetworkTask
252    // atomSpec = #0:1.A or #1:96.B@N
 
253  0 toggle public static ChimeraResidue getResidue(String atomSpec,
254    ChimeraManager chimeraManager)
255    {
256    // System.out.println("Getting residue from: "+atomSpec);
257  0 ChimeraModel model = getModel(atomSpec, chimeraManager); // Get the model
258  0 if (model == null)
259    {
260  0 model = chimeraManager.getChimeraModel();
261    }
262  0 return getResidue(atomSpec, model);
263    }
264   
265    // invoked by the getResdiue (parseConnectivityReplies in
266    // CreateStructureNetworkTask)
267    // atomSpec = #0:1.A or #1:96.B@N
 
268  0 toggle public static ChimeraResidue getResidue(String atomSpec,
269    ChimeraModel model)
270    {
271    // System.out.println("Getting residue from: "+atomSpec);
272  0 String[] split = atomSpec.split(":|@");
273   
274    // Split into residue and chain
275  0 String[] residueChain = split[1].split("\\.");
276   
277  0 if (residueChain[0].length() == 0)
278    {
279  0 logger.info("Unexpected return from Chimera: " + atomSpec);
280  0 return null;
281    }
282   
283  0 if (residueChain.length == 2 && residueChain[1].length() > 0)
284    {
285  0 ChimeraChain chain = model.getChain(residueChain[1]);
286  0 return chain.getResidue(residueChain[0]);
287    }
288  0 return model.getResidue("_", residueChain[0]);
289    }
290   
 
291  0 toggle public static ChimeraChain getChain(String atomSpec, ChimeraModel model)
292    {
293  0 String[] split = atomSpec.split(":|@");
294   
295    // Split into residue and chain
296  0 String[] residueChain = split[1].split("\\.");
297  0 if (residueChain.length == 1)
298    {
299  0 logger.info("Unexpected return from Chimera: " + atomSpec);
300  0 return null;
301    }
302  0 return model.getChain(residueChain[1]);
303    }
304   
 
305  0 toggle public static String getAtomName(String atomSpec)
306    {
307  0 String[] split = atomSpec.split("@");
308  0 if (split.length > 1)
309    {
310  0 return split[1];
311    }
312  0 return atomSpec;
313    }
314   
 
315  0 toggle public static boolean isBackbone(String atom)
316    {
317  0 if (atom.equals("C") || atom.equals("CA") || atom.equals("N")
318    || atom.equals("O") || atom.equals("H"))
319    {
320  0 return true;
321    }
322  0 return false;
323    }
324   
 
325  0 toggle public static String getIntSubtype(String node, String atom)
326    {
327  0 String[] split = node.split("#| ");
328  0 String resType = "";
329  0 if (split.length == 2)
330    {
331  0 resType = split[0].trim().toUpperCase(Locale.ROOT);
332    }
333  0 else if (split.length == 3)
334    {
335  0 resType = split[1].trim().toUpperCase(Locale.ROOT);
336    }
337  0 if (resType.equalsIgnoreCase("HOH") || resType.equalsIgnoreCase("WAT"))
338    {
339  0 return "water";
340    }
341  0 else if (aaNames.containsKey(resType))
342    {
343  0 if (atom.equals("C") || atom.equals("CA") || atom.equals("N")
344    || atom.equals("O") || atom.equals("H"))
345    {
346  0 return "mc";
347    }
348    else
349    {
350  0 return "sc";
351    }
352    }
353    else
354    {
355  0 return "other";
356    }
357    }
358   
 
359  0 toggle public static String[] getResKeyParts(String resKey)
360    {
361    // [pdbID[.modelNo]#][residueID][.chainID]
362    // pdbID := 4-character code | "URL" | "path"
363  0 String[] resKeyParts = new String[4];
364  0 String[] split = resKey.split("#");
365  0 String resChain = null;
366    // if no "#" then it is either only a pdb id or a residue or a chain
367  0 if (split.length == 1)
368    {
369    // pdb id without model
370  0 if (resKey.length() == 4 && resKey.indexOf("\\.") < 0)
371    {
372  0 parseModelID(resKey, resKeyParts);
373    }
374    // pdb link or file
375  0 else if (resKey.startsWith("\""))
376    {
377  0 parseModelID(resKey, resKeyParts);
378    }
379    // chain and residue or model and number
380    else
381    {
382  0 String[] splitSplit = resKey.split("\\.");
383  0 if (splitSplit.length == 1)
384    {
385    // only a chain or a residue
386  0 resChain = resKey;
387    }
388    else
389    {
390  0 try
391    {
392    // pdb with a model
393  0 Integer.parseInt(splitSplit[1]);
394  0 parseModelID(resKey, resKeyParts);
395    } catch (NumberFormatException ex)
396    {
397    // residue and chain
398  0 resChain = resKey;
399    }
400    }
401    }
402    }
403  0 else if (split.length == 2)
404    {
405    // model and residue+chain
406  0 parseModelID(split[0], resKeyParts);
407  0 resChain = split[1];
408    }
409    else
410    {
411    // model string with "#"
412    // TODO: [Optional] Are there more possibilities?
413  0 parseModelID(resKey.substring(0, resKey.lastIndexOf("#")),
414    resKeyParts);
415  0 resChain = resKey.substring(resKey.lastIndexOf("#") + 1,
416    resKey.length());
417    }
418  0 if (resChain != null)
419    {
420    // System.out.println(resChain);
421  0 String[] resChainSplit = resChain.split("\\.");
422  0 if (resChainSplit.length == 1)
423    {
424    // TODO: [Optional] Find a better way to distinguish between chain and
425    // residue
426    // if only one character and not an int, probably a chain
427  0 if (resChainSplit[0].length() == 1)
428    {
429  0 try
430    {
431  0 Integer.parseInt(resChainSplit[0]);
432  0 resKeyParts[3] = resChainSplit[0];
433    } catch (NumberFormatException ex)
434    {
435  0 resKeyParts[2] = resChainSplit[0];
436    }
437    }
438    else
439    {
440  0 resKeyParts[3] = resChainSplit[0];
441    }
442    }
443  0 else if (resChainSplit.length == 2)
444    {
445  0 resKeyParts[2] = resChainSplit[0];
446  0 resKeyParts[3] = resChainSplit[1];
447    }
448    else
449    {
450    // too many dots?
451  0 logger.info("Could not parse residue identifier: " + resKey);
452    }
453    }
454    // String print = "";
455    // for (int i = 0; i < resKeyParts.length; i++) {
456    // if (resKeyParts[i] == null) {
457    // print += i + ": null\t";
458    // } else {
459    // print += i + ": " + resKeyParts[i] + ";";
460    // }
461    // }
462    // System.out.println(print);
463  0 return resKeyParts;
464    }
465   
 
466  0 toggle public static void parseModelID(String modelID, String[] resKeyParts)
467    {
468  0 if (modelID.startsWith("\""))
469    {
470  0 if (modelID.endsWith("\""))
471    {
472  0 resKeyParts[0] = modelID.substring(1, modelID.length() - 1);
473  0 return;
474    }
475    else
476    {
477  0 try
478    {
479  0 Integer.parseInt(modelID.substring(modelID.lastIndexOf("\"") + 2,
480    modelID.length()));
481  0 resKeyParts[0] = modelID.substring(0,
482    modelID.lastIndexOf("\"") - 1);
483  0 resKeyParts[1] = modelID.substring(modelID.lastIndexOf("\"") + 2,
484    modelID.length());
485    } catch (NumberFormatException ex)
486    {
487  0 resKeyParts[0] = modelID.substring(1);
488    }
489    }
490    }
491    else
492    {
493  0 String[] modelIDNo = modelID.split("\\.");
494  0 if (modelIDNo.length == 1)
495    {
496  0 resKeyParts[0] = modelIDNo[0];
497    }
498  0 else if (modelIDNo.length == 2)
499    {
500  0 try
501    {
502  0 Integer.parseInt(modelIDNo[1]);
503  0 resKeyParts[0] = modelIDNo[0];
504  0 resKeyParts[1] = modelIDNo[1];
505    } catch (NumberFormatException ex)
506    {
507  0 resKeyParts[0] = modelID;
508    }
509    }
510    else
511    {
512    // length > 1, so we probably have a file name with "." in it
513  0 logger.info("Could not parse model identifier: " + modelID);
514  0 resKeyParts[0] = modelID;
515    }
516    }
517    }
518   
519    /**
520    * This method takes a Cytoscape attribute specification
521    * ([structure#][residue][.chainID]) and returns the lowest-level object
522    * referenced by the spec. For example, if the spec is "1tkk", this method
523    * will return a ChimeraModel. If the spec is ".A", it will return a
524    * ChimeraChain, etc.
525    *
526    * @param attrSpec
527    * the specification string
528    * @param chimeraManager
529    * the Chimera object we're currently using
530    * @return a ChimeraStructuralObject of the lowest type
531    */
 
532  0 toggle public static ChimeraStructuralObject fromAttributeOld(String attrSpec,
533    ChimeraManager chimeraManager)
534    {
535  0 if (attrSpec == null || attrSpec.indexOf(',') > 0
536    || attrSpec.indexOf('-') > 0)
537    {
538    // No support for either lists or ranges
539  0 logger.warn("No support for identifier: " + attrSpec);
540  0 return null;
541    }
542   
543  0 String residue = null;
544  0 String model = null;
545  0 String chain = null;
546   
547  0 ChimeraModel chimeraModel = null;
548  0 ChimeraChain chimeraChain = null;
549  0 ChimeraResidue chimeraResidue = null;
550   
551    // System.out.println("Getting object from attribute: "+attrSpec);
552  0 try
553    {
554  0 String[] split = attrSpec.split("#");
555  0 String resChain = null;
556  0 if (split.length == 1)
557    {
558    // no model
559  0 resChain = split[0];
560    }
561  0 else if (split.length == 2)
562    {
563    // model and rest
564  0 model = split[0];
565  0 resChain = split[1];
566    }
567    else
568    {
569    // model string with "#"
570  0 model = attrSpec.substring(0, attrSpec.lastIndexOf("#"));
571  0 resChain = attrSpec.substring(attrSpec.lastIndexOf("#") + 1,
572    attrSpec.length());
573    }
574  0 if (resChain != null)
575    {
576  0 String[] resChainSplit = resChain.split("\\.");
577  0 if (resChainSplit.length == 1)
578    {
579  0 residue = resChainSplit[0];
580    }
581  0 else if (resChainSplit.length == 2)
582    {
583  0 residue = resChainSplit[0];
584  0 chain = resChainSplit[1];
585    }
586    else
587    {
588    // too many dots?
589  0 logger.warn("No support for identifier: " + attrSpec);
590    }
591    }
592   
593    // if (split.length == 1) {
594    // // No model
595    // residue = split[0];
596    // } else if (split.length == 3) {
597    // // We have all three
598    // model = split[0];
599    // residue = split[1];
600    // chain = split[2];
601    // } else if (split.length == 2 && attrSpec.indexOf('#') > 0) {
602    // // Model and Residue
603    // model = split[0];
604    // residue = split[1];
605    // } else {
606    // // Residue and Chain
607    // residue = split[0];
608    // chain = split[1];
609    // }
610   
611    // System.out.println("model = " + model + " chain = " + chain +
612    // " residue = " + residue);
613  0 if (model != null)
614    {
615  0 List<ChimeraModel> models = chimeraManager.getChimeraModels(model,
616    ModelType.PDB_MODEL);
617  0 if (models.size() == 1)
618    {
619  0 chimeraModel = models.get(0);
620    }
621    else
622    {
623  0 try
624    {
625  0 chimeraModel = chimeraManager
626    .getChimeraModel(Integer.valueOf(model), 0);
627    } catch (NumberFormatException ex)
628    {
629    // ignore
630    }
631    }
632    }
633  0 if (chimeraModel == null)
634    {
635  0 chimeraModel = chimeraManager.getChimeraModel();
636    }
637    // System.out.println("ChimeraModel = " + chimeraModel);
638   
639  0 if (chain != null)
640    {
641  0 chimeraChain = chimeraModel.getChain(chain);
642    // System.out.println("ChimeraChain = " + chimeraChain);
643    }
644  0 if (residue != null)
645    {
646  0 if (chimeraChain != null)
647    {
648  0 chimeraResidue = chimeraChain.getResidue(residue);
649    }
650    else
651    {
652  0 chimeraResidue = chimeraModel.getResidue("_", residue);
653    }
654    // System.out.println("ChimeraResidue = " + chimeraResidue);
655    }
656   
657  0 if (chimeraResidue != null)
658    {
659  0 return chimeraResidue;
660    }
661   
662  0 if (chimeraChain != null)
663    {
664  0 return chimeraChain;
665    }
666   
667  0 if (chimeraModel != null)
668    {
669  0 return chimeraModel;
670    }
671   
672    } catch (Exception ex)
673    {
674  0 logger.warn("Could not parse residue identifier: " + attrSpec, ex);
675    }
676  0 return null;
677    }
678   
 
679  0 toggle public static ChimeraStructuralObject fromAttribute(String attrSpec,
680    ChimeraManager chimeraManager)
681    {
682    // TODO: Make sure it is OK to remove this: || attrSpec.indexOf('-') > 0
683  0 if (attrSpec == null || attrSpec.indexOf(',') > 0)
684    {
685    // No support for either lists or ranges
686    // System.out.println("No support for identifier: " + attrSpec);
687  0 logger.warn("No support for identifier: " + attrSpec);
688  0 return null;
689    }
690  0 String[] modelIDNoResChain = getResKeyParts(attrSpec);
691   
692  0 ChimeraModel chimeraModel = null;
693  0 ChimeraChain chimeraChain = null;
694  0 ChimeraResidue chimeraResidue = null;
695   
696    // System.out.println("Getting object from attribute: "+attrSpec);
697  0 try
698    {
699  0 if (modelIDNoResChain[0] != null)
700    {
701  0 String modelID = modelIDNoResChain[0];
702  0 List<ChimeraModel> models = chimeraManager.getChimeraModels(modelID,
703    ModelType.PDB_MODEL);
704  0 if (models.size() == 1)
705    { // usual case with only one model
706  0 chimeraModel = models.get(0);
707    }
708  0 else if (models.size() > 1 && modelIDNoResChain[1] != null)
709    {
710    // there are several submodels
711  0 try
712    {
713  0 int modelNo = Integer.valueOf(modelIDNoResChain[1]);
714  0 for (ChimeraModel model : models)
715    {
716  0 if (model.getSubModelNumber() == modelNo)
717    {
718  0 chimeraModel = model;
719  0 break;
720    }
721    }
722    } catch (NumberFormatException ex)
723    {
724    // ignore
725    }
726    }
727    else
728    {
729    // TODO: [Optional] What is this doing?
730  0 try
731    {
732  0 chimeraModel = chimeraManager
733    .getChimeraModel(Integer.valueOf(modelID), 0);
734    } catch (NumberFormatException ex)
735    {
736    // ignore
737    }
738    }
739    }
740  0 if (chimeraModel == null)
741    {
742    // TODO: [Optional] Find a better way to handle this case
743    // If no model can be matched, continue
744    // System.out.println("No matching model could be find for " +
745    // attrSpec);
746  0 return null;
747    // chimeraModel = chimeraManager.getChimeraModel();
748    // logger.warn("No matching model could be find for " + attrSpec +
749    // ". Trying with "
750    // + chimeraModel.toSpec());
751    }
752    // System.out.println("ChimeraModel = " + chimeraModel);
753   
754  0 if (modelIDNoResChain[3] != null)
755    {
756  0 chimeraChain = chimeraModel.getChain(modelIDNoResChain[3]);
757    // System.out.println("ChimeraChain = " + chimeraChain);
758    }
759  0 if (modelIDNoResChain[2] != null)
760    {
761  0 String residue = modelIDNoResChain[2];
762  0 if (chimeraChain != null)
763    {
764  0 chimeraResidue = chimeraChain.getResidue(residue);
765    }
766  0 else if (chimeraModel.getChain("_") != null)
767    {
768  0 chimeraResidue = chimeraModel.getResidue("_", residue);
769    }
770  0 else if (chimeraModel.getChainCount() == 1)
771    {
772  0 chimeraResidue = chimeraModel.getResidue(
773    chimeraModel.getChainNames().iterator().next(), residue);
774    }
775    // System.out.println("ChimeraResidue = " + chimeraResidue);
776    }
777   
778  0 if (chimeraResidue != null)
779    {
780  0 return chimeraResidue;
781    }
782   
783  0 if (chimeraChain != null)
784    {
785  0 return chimeraChain;
786    }
787   
788  0 if (chimeraModel != null)
789    {
790  0 return chimeraModel;
791    }
792   
793    } catch (Exception ex)
794    {
795    // System.out.println("Could not parse chimera identifier: " +
796    // attrSpec+"("+ex.getMessage()+")");
797  0 logger.warn("Could not parse chimera identifier: " + attrSpec, ex);
798    }
799  0 return null;
800    }
801   
802    /**
803    * Search for structure references in the residue list
804    *
805    * @param residueList
806    * the list of residues
807    * @return a concatenated list of structures encoded in the list
808    */
 
809  0 toggle public static String findStructures(String residueList)
810    {
811  0 if (residueList == null)
812    {
813  0 return null;
814    }
815  0 String[] residues = residueList.split(",");
816  0 Map<String, String> structureNameMap = new HashMap<String, String>();
817  0 for (int i = 0; i < residues.length; i++)
818    {
819  0 String[] components = residues[i].split("#");
820  0 if (components.length > 1)
821    {
822  0 structureNameMap.put(components[0], components[1]);
823    }
824    }
825  0 if (structureNameMap.isEmpty())
826    {
827  0 return null;
828    }
829   
830  0 String structure = null;
831  0 for (String struct : structureNameMap.keySet())
832    {
833  0 if (structure == null)
834    {
835  0 structure = new String();
836    }
837    else
838    {
839  0 structure = structure.concat(",");
840    }
841  0 structure = structure.concat(struct);
842    }
843  0 return structure;
844    }
845   
846    // invoked by openStructures in StructureManager
 
847  0 toggle public static List<String> parseFuncRes(List<String> residueNames,
848    String modelName)
849    {
850  0 List<String> resRanges = new ArrayList<String>();
851  0 for (int i = 0; i < residueNames.size(); i++)
852    {
853  0 String residue = residueNames.get(i);
854    // Parse out the structure, if there is one
855  0 String[] components = residue.split("#");
856  0 if (components.length > 1 && !modelName.equals(components[0]))
857    {
858  0 continue;
859    }
860  0 else if (components.length > 1)
861    {
862  0 residue = components[1];
863    }
864  0 else if (components.length == 1)
865    {
866  0 residue = components[0];
867    }
868    // Check to see if we have a range-spec
869  0 String resRange = "";
870  0 if (residue == null || residue.equals("") || residue.length() == 0)
871    {
872  0 continue;
873    }
874  0 String[] range = residue.split("-", 2);
875  0 String chain = null;
876  0 for (int res = 0; res < range.length; res++)
877    {
878  0 if (res == 1)
879    {
880  0 resRange = resRange.concat("-");
881  0 if (chain != null && range[res].indexOf('.') == -1)
882    {
883  0 range[res] = range[res].concat("." + chain);
884    }
885    }
886   
887  0 if (res == 0 && range.length >= 2 && range[res].indexOf('.') > 0)
888    {
889    // This is a range spec with the leading residue containing a chain
890    // spec
891  0 String[] resChain = range[res].split("\\.");
892  0 chain = resChain[1];
893  0 range[res] = resChain[0];
894    }
895    // Fix weird SFLD syntax...
896  0 if (range[res].indexOf('|') > 0
897    && Character.isDigit(range[res].charAt(0)))
898    {
899  0 int offset = range[res].indexOf('|');
900  0 String str = range[res].substring(offset + 1)
901    + range[res].substring(0, offset);
902  0 range[res] = str;
903    }
904   
905    // Convert to legal atom-spec
906  0 if (Character.isDigit(range[res].charAt(0)))
907    {
908  0 resRange = resRange.concat(range[res]);
909    }
910  0 else if (Character.isDigit(range[res].charAt(1)))
911    {
912  0 resRange = resRange.concat(range[res].substring(1));
913    }
914  0 else if (range[res].charAt(0) == '.')
915    {
916    // Do we have a chain spec?
917  0 resRange = resRange.concat(range[res]);
918    }
919    else
920    {
921  0 resRange = resRange.concat(range[res].substring(3));
922    }
923    }
924  0 if (!resRanges.contains(resRange))
925    {
926  0 resRanges.add(resRange);
927    }
928    }
929  0 return resRanges;
930    }
931   
 
932  0 toggle static
933    {
934  0 aaNames = new HashMap<String, String>();
935  0 aaNames.put("ALA", "A Ala Alanine N[C@@H](C)C(O)=O");
936  0 aaNames.put("ARG", "R Arg Arginine N[C@@H](CCCNC(N)=N)C(O)=O");
937  0 aaNames.put("ASN", "N Asn Asparagine N[C@@H](CC(N)=O)C(O)=O");
938  0 aaNames.put("ASP", "D Asp Aspartic_acid N[C@@H](CC(O)=O)C(O)=O");
939  0 aaNames.put("CYS", "C Cys Cysteine N[C@@H](CS)C(O)=O");
940  0 aaNames.put("GLN", "Q Gln Glutamine N[C@H](C(O)=O)CCC(N)=O");
941  0 aaNames.put("GLU", "E Glu Glumatic_acid N[C@H](C(O)=O)CCC(O)=O");
942  0 aaNames.put("GLY", "G Gly Glycine NCC(O)=O");
943  0 aaNames.put("HIS", "H His Histidine N[C@@H](CC1=CN=CN1)C(O)=O");
944  0 aaNames.put("ILE", "I Ile Isoleucine N[C@]([C@H](C)CC)([H])C(O)=O");
945  0 aaNames.put("LEU", "L Leu Leucine N[C@](CC(C)C)([H])C(O)=O");
946  0 aaNames.put("LYS", "K Lys Lysine N[C@](CCCCN)([H])C(O)=O");
947  0 aaNames.put("DLY", "K Dly D-Lysine NCCCC[C@@H](N)C(O)=O");
948  0 aaNames.put("MET", "M Met Methionine N[C@](CCSC)([H])C(O)=O");
949  0 aaNames.put("PHE",
950    "F Phe Phenylalanine N[C@](CC1=CC=CC=C1)([H])C(O)=O");
951  0 aaNames.put("PRO", "P Pro Proline OC([C@@]1([H])NCCC1)=O");
952  0 aaNames.put("SER", "S Ser Serine OC[C@](C(O)=O)([H])N");
953  0 aaNames.put("THR", "T Thr Threonine O[C@H](C)[C@](C(O)=O)([H])N");
954  0 aaNames.put("TRP",
955    "W Trp Tryptophan N[C@@]([H])(CC1=CN([H])C2=C1C=CC=C2)C(O)=O");
956  0 aaNames.put("TYR", "Y Tyr Tyrosine N[C@@](C(O)=O)([H])CC1=CC=C(O)C=C1");
957  0 aaNames.put("VAL", "V Val Valine N[C@@](C(O)=O)([H])C(C)C");
958  0 aaNames.put("ASX", "B Asx Aspartic_acid_or_Asparagine");
959  0 aaNames.put("GLX", "Z Glx Glutamine_or_Glutamic_acid");
960  0 aaNames.put("XAA", "X Xaa Any_or_unknown_amino_acid");
961  0 aaNames.put("HOH", "HOH HOH Water [H]O[H]");
962    }
963   
964    /**
965    * Convert the amino acid type to a full name
966    *
967    * @param aaType
968    * the residue type to convert
969    * @return the full name of the residue
970    */
 
971  0 toggle public static String toFullName(String aaType)
972    {
973  0 if (!aaNames.containsKey(aaType))
974    {
975  0 return aaType;
976    }
977  0 String[] ids = aaNames.get(aaType).split(" ");
978  0 return ids[2].replace('_', ' ');
979    }
980   
981    /**
982    * Convert the amino acid type to a single letter
983    *
984    * @param aaType
985    * the residue type to convert
986    * @return the single letter representation of the residue
987    */
 
988  0 toggle public static String toSingleLetter(String aaType)
989    {
990  0 if (!aaNames.containsKey(aaType))
991    {
992  0 return aaType;
993    }
994  0 String[] ids = aaNames.get(aaType).split(" ");
995  0 return ids[0];
996    }
997   
998    /**
999    * Convert the amino acid type to three letters
1000    *
1001    * @param aaType
1002    * the residue type to convert
1003    * @return the three letter representation of the residue
1004    */
 
1005  0 toggle public static String toThreeLetter(String aaType)
1006    {
1007  0 if (!aaNames.containsKey(aaType))
1008    {
1009  0 return aaType;
1010    }
1011  0 String[] ids = aaNames.get(aaType).split(" ");
1012  0 return ids[1];
1013    }
1014   
1015    /**
1016    * Convert the amino acid type to its SMILES string
1017    *
1018    * @param aaType
1019    * the residue type to convert
1020    * @return the SMILES representation of the residue
1021    */
 
1022  0 toggle public static String toSMILES(String aaType)
1023    {
1024  0 if (!aaNames.containsKey(aaType))
1025    {
1026  0 return null;
1027    }
1028  0 String[] ids = aaNames.get(aaType).split(" ");
1029  0 if (ids.length < 4)
1030    {
1031  0 return null;
1032    }
1033  0 return ids[3];
1034    }
1035   
 
1036  0 toggle public static String getAlignName(ChimeraStructuralObject chimObj)
1037    {
1038  0 String name = chimObj.getChimeraModel().toString();
1039  0 if (chimObj instanceof ChimeraChain)
1040    {
1041  0 name = ((ChimeraChain) chimObj).toString() + " [" + name + "]";
1042    }
1043  0 return name;
1044    }
1045    }