JAL-1596 first REST interface coded
[jalview.git] / src / jalview / ext / rbvi / chimera / ChimeraCommands.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.ext.rbvi.chimera;
22
23 import jalview.api.FeatureRenderer;
24 import jalview.api.SequenceRenderer;
25 import jalview.datamodel.AlignmentI;
26 import jalview.datamodel.SequenceI;
27 import jalview.structure.StructureMapping;
28 import jalview.structure.StructureMappingcommandSet;
29 import jalview.structure.StructureSelectionManager;
30
31 import java.awt.Color;
32 import java.util.ArrayList;
33 import java.util.LinkedHashMap;
34 import java.util.Map;
35
36 /**
37  * Routines for generating Chimera commands for Jalview/Chimera binding
38  * 
39  * @author JimP
40  * 
41  */
42 public class ChimeraCommands
43 {
44
45   /**
46    * utility to construct the commands to colour chains by the given alignment
47    * for passing to Chimera
48    * 
49    * @returns Object[] { Object[] { <model being coloured>,
50    * 
51    */
52   public static StructureMappingcommandSet[] getColourBySequenceCommand(
53           StructureSelectionManager ssm, String[] files,
54           SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
55           AlignmentI alignment)
56   {
57
58     ArrayList<StructureMappingcommandSet> cset = new ArrayList<StructureMappingcommandSet>();
59
60     /*
61      * Map of { colour, positionSpecs}
62      */
63     Map<String, StringBuilder> colranges = new LinkedHashMap<String, StringBuilder>();
64     for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
65     {
66       StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
67
68       if (mapping == null || mapping.length < 1)
69       {
70         continue;
71       }
72
73       int startPos = -1, lastPos = -1, startModel = -1, lastModel = -1;
74       String lastChain = "";
75       Color lastCol = null;
76       for (int s = 0; s < sequence[pdbfnum].length; s++)
77       {
78         for (int sp, m = 0; m < mapping.length; m++)
79         {
80           if (mapping[m].getSequence() == sequence[pdbfnum][s]
81                   && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1)
82           {
83             SequenceI asp = alignment.getSequenceAt(sp);
84             for (int r = 0; r < asp.getLength(); r++)
85             {
86               // no mapping to gaps in sequence
87               if (jalview.util.Comparison.isGap(asp.getCharAt(r)))
88               {
89                 continue;
90               }
91               int pos = mapping[m].getPDBResNum(asp.findPosition(r));
92
93               if (pos < 1 || pos == lastPos)
94               {
95                 continue;
96               }
97
98               Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r);
99
100               if (fr != null)
101               {
102                 col = fr.findFeatureColour(col, sequence[pdbfnum][s], r);
103               }
104               if (lastCol != col || lastPos + 1 != pos
105                       || pdbfnum != lastModel
106                       || !mapping[m].getChain().equals(lastChain))
107               {
108                 if (lastCol != null)
109                 {
110                   addColourRange(colranges, lastCol,startModel,startPos,lastPos,lastChain); 
111                 }
112                 lastCol = null;
113                 startPos = pos;
114                 startModel = pdbfnum;
115               }
116               lastCol = col;
117               lastPos = pos;
118               lastModel = pdbfnum;
119               lastChain = mapping[m].getChain();
120             }
121             // final colour range
122             if (lastCol != null)
123             {
124               addColourRange(colranges, lastCol,startModel,startPos,lastPos,lastChain); 
125             }
126             break;
127           }
128         }
129       }
130       // Finally, add the command set ready to be returned.
131       StringBuilder coms = new StringBuilder(256);
132       for (String cr:colranges.keySet())
133       {
134         coms.append("color #"+cr+" "+colranges.get(cr)+";");
135       }
136       cset.add(new StructureMappingcommandSet(ChimeraCommands.class,
137               files[pdbfnum], new String[] { coms.toString() }));
138     }
139     return cset.toArray(new StructureMappingcommandSet[cset.size()]);
140   }
141
142   /**
143    * Helper method to record a range of positions of the same colour.
144    * 
145    * @param colranges
146    * @param colour
147    * @param model
148    * @param startPos
149    * @param endPos
150    * @param chain
151    */
152   private static void addColourRange(Map<String, StringBuilder> colranges,
153           Color colour, int model,
154           int startPos, int endPos, String chain)
155   {
156     String colstring = ((colour.getRed()< 16) ? "0":"")+Integer.toHexString(colour.getRed())
157             + ((colour.getGreen()< 16) ? "0":"")+Integer.toHexString(colour.getGreen())
158             + ((colour.getBlue()< 16) ? "0":"")+Integer.toHexString(colour.getBlue());
159     StringBuilder currange = colranges.get(colstring);
160     if (currange == null)
161     {
162       colranges.put(colstring, currange = new StringBuilder(256));
163     }
164     if (currange.length() > 0)
165     {
166       currange.append("|");
167     }
168     currange.append("#" + model + ":" + ((startPos==endPos) ? startPos : startPos + "-"
169             + endPos) + "." + chain);
170   }
171
172 }