JAL-1065 JAL-1066 - use direct object reference rather then index into alignment
[jalview.git] / src / jalview / schemes / ResidueColourScheme.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
10  * 
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.schemes;
19
20 import jalview.analysis.AAFrequency;
21 import jalview.analysis.Conservation;
22 import jalview.datamodel.SequenceI;
23
24 import java.awt.Color;
25 import java.util.Hashtable;
26
27 /**
28  * DOCUMENT ME!
29  * 
30  * @author $author$
31  * @version $Revision$
32  */
33 public class ResidueColourScheme implements ColourSchemeI
34 {
35
36   boolean conservationColouring = false;
37
38   Color[] colors = null;
39
40   int threshold = 0;
41
42   /* Set when threshold colouring to either pid_gaps or pid_nogaps */
43   protected String ignoreGaps = AAFrequency.PID_GAPS;
44
45   /** Consenus as a hashtable array */
46   Hashtable[] consensus;
47
48   /** Conservation string as a char array */
49   char[] conservation;
50
51   int conservationLength = 0;
52
53   /** DOCUMENT ME!! */
54   int inc = 30;
55
56   /**
57    * Creates a new ResidueColourScheme object.
58    * 
59    * @param colors
60    *          DOCUMENT ME!
61    * @param threshold
62    *          DOCUMENT ME!
63    */
64   public ResidueColourScheme(Color[] colours, int threshold)
65   {
66     this.colors = colours;
67     this.threshold = threshold;
68   }
69
70   /**
71    * Creates a new ResidueColourScheme object.
72    */
73   public ResidueColourScheme()
74   {
75   }
76
77   /**
78    * Find a colour without an index in a sequence
79    */
80   public Color findColour(char c)
81   {
82     return colors == null ? Color.white
83             : colors[ResidueProperties.aaIndex[c]];
84   }
85
86   @Override
87   public Color findColour(char c, int j, SequenceI seq)
88   {
89     Color currentColour;
90
91     if ((threshold == 0) || aboveThreshold(c, j))
92     {
93       currentColour = colors[ResidueProperties.aaIndex[c]];
94     }
95     else
96     {
97       currentColour = Color.white;
98     }
99
100     if (conservationColouring)
101     {
102       currentColour = applyConservation(currentColour, j);
103     }
104
105     return currentColour;
106   }
107
108   /**
109    * Get the percentage threshold for this colour scheme
110    * 
111    * @return Returns the percentage threshold
112    */
113   public int getThreshold()
114   {
115     return threshold;
116   }
117
118   /**
119    * DOCUMENT ME!
120    * 
121    * @param ct
122    *          DOCUMENT ME!
123    */
124   public void setThreshold(int ct, boolean ignoreGaps)
125   {
126     threshold = ct;
127     if (ignoreGaps)
128     {
129       this.ignoreGaps = AAFrequency.PID_NOGAPS;
130     }
131     else
132     {
133       this.ignoreGaps = AAFrequency.PID_GAPS;
134     }
135   }
136
137   /**
138    * DOCUMENT ME!
139    * 
140    * @param s
141    *          DOCUMENT ME!
142    * @param j
143    *          DOCUMENT ME!
144    * 
145    * @return DOCUMENT ME!
146    */
147   public boolean aboveThreshold(char c, int j)
148   {
149     if ('a' <= c && c <= 'z')
150     {
151       // TO UPPERCASE !!!
152       // Faster than toUpperCase
153       c -= ('a' - 'A');
154     }
155
156     if (consensus == null || consensus.length < j || consensus[j] == null)
157     {
158       return false;
159     }
160
161     if ((((Integer) consensus[j].get(AAFrequency.MAXCOUNT)).intValue() != -1)
162             && consensus[j].contains(String.valueOf(c)))
163     {
164       if (((Float) consensus[j].get(ignoreGaps)).floatValue() >= threshold)
165       {
166         return true;
167       }
168     }
169
170     return false;
171   }
172
173   public boolean conservationApplied()
174   {
175     return conservationColouring;
176   }
177
178   public void setConservationInc(int i)
179   {
180     inc = i;
181   }
182
183   public int getConservationInc()
184   {
185     return inc;
186   }
187
188   /**
189    * DOCUMENT ME!
190    * 
191    * @param consensus
192    *          DOCUMENT ME!
193    */
194   public void setConsensus(Hashtable[] consensus)
195   {
196     if (consensus == null)
197     {
198       return;
199     }
200
201     this.consensus = consensus;
202   }
203
204   public void setConservation(Conservation cons)
205   {
206     if (cons == null)
207     {
208       conservationColouring = false;
209       conservation = null;
210     }
211     else
212     {
213       conservationColouring = true;
214       int i, iSize = cons.getConsSequence().getLength();
215       conservation = new char[iSize];
216       for (i = 0; i < iSize; i++)
217       {
218         conservation[i] = cons.getConsSequence().getCharAt(i);
219       }
220       conservationLength = conservation.length;
221     }
222
223   }
224
225   /**
226    * DOCUMENT ME!
227    * 
228    * @param s
229    *          DOCUMENT ME!
230    * @param i
231    *          DOCUMENT ME!
232    * 
233    * @return DOCUMENT ME!
234    */
235
236   Color applyConservation(Color currentColour, int i)
237   {
238
239     if ((conservationLength > i) && (conservation[i] != '*')
240             && (conservation[i] != '+'))
241     {
242       if (jalview.util.Comparison.isGap(conservation[i]))
243       {
244         currentColour = Color.white;
245       }
246       else
247       {
248         float t = 11 - (conservation[i] - '0');
249         if (t == 0)
250         {
251           return Color.white;
252         }
253
254         int red = currentColour.getRed();
255         int green = currentColour.getGreen();
256         int blue = currentColour.getBlue();
257
258         int dr = 255 - red;
259         int dg = 255 - green;
260         int db = 255 - blue;
261
262         dr *= t / 10f;
263         dg *= t / 10f;
264         db *= t / 10f;
265
266         red += (inc / 20f) * dr;
267         green += (inc / 20f) * dg;
268         blue += (inc / 20f) * db;
269
270         if (red > 255 || green > 255 || blue > 255)
271         {
272           currentColour = Color.white;
273         }
274         else
275         {
276           currentColour = new Color(red, green, blue);
277         }
278       }
279     }
280     return currentColour;
281   }
282
283 }