JAL-1114 - refactor methods handling Vectors and Hashtables to Lists and Maps, and...
[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, J Engelhardt, LM Lui, 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.AnnotatedCollectionI;
23 import jalview.datamodel.SequenceCollectionI;
24 import jalview.datamodel.SequenceI;
25
26 import java.awt.Color;
27 import java.util.Hashtable;
28 import java.util.Map;
29
30 /**
31  * DOCUMENT ME!
32  * 
33  * @author $author$
34  * @version $Revision$
35  */
36 public class ResidueColourScheme implements ColourSchemeI
37 {
38
39   boolean conservationColouring = false;
40
41   Color[] colors = null;
42
43   int threshold = 0;
44
45   /* Set when threshold colouring to either pid_gaps or pid_nogaps */
46   protected String ignoreGaps = AAFrequency.PID_GAPS;
47
48   /** Consenus as a hashtable array */
49   Hashtable[] consensus;
50
51   /** Conservation string as a char array */
52   char[] conservation;
53
54   int conservationLength = 0;
55
56   /** DOCUMENT ME!! */
57   int inc = 30;
58
59   /**
60    * Creates a new ResidueColourScheme object.
61    * 
62    * @param colors
63    *          DOCUMENT ME!
64    * @param threshold
65    *          DOCUMENT ME!
66    */
67   public ResidueColourScheme(Color[] colours, int threshold)
68   {
69     this.colors = colours;
70     this.threshold = threshold;
71   }
72
73   /**
74    * Creates a new ResidueColourScheme object.
75    */
76   public ResidueColourScheme()
77   {
78   }
79
80   /**
81    * Find a colour without an index in a sequence
82    */
83   public Color findColour(char c)
84   {
85     return colors == null ? Color.white
86             : colors[ResidueProperties.aaIndex[c]];
87   }
88
89   @Override
90   public Color findColour(char c, int j, SequenceI seq)
91   {
92     Color currentColour;
93
94     if ((threshold == 0) || aboveThreshold(c, j))
95     {
96       currentColour = colors[ResidueProperties.aaIndex[c]];
97     }
98     else
99     {
100       currentColour = Color.white;
101     }
102
103     if (conservationColouring)
104     {
105       currentColour = applyConservation(currentColour, j);
106     }
107
108     return currentColour;
109   }
110   /**
111    * Get the percentage threshold for this colour scheme
112    * 
113    * @return Returns the percentage threshold
114    */
115   public int getThreshold()
116   {
117     return threshold;
118   }
119
120   /**
121    * DOCUMENT ME!
122    * 
123    * @param ct
124    *          DOCUMENT ME!
125    */
126   public void setThreshold(int ct, boolean ignoreGaps)
127   {
128     threshold = ct;
129     if (ignoreGaps)
130     {
131       this.ignoreGaps = AAFrequency.PID_NOGAPS;
132     }
133     else
134     {
135       this.ignoreGaps = AAFrequency.PID_GAPS;
136     }
137   }
138
139   /**
140    * DOCUMENT ME!
141    * 
142    * @param s
143    *          DOCUMENT ME!
144    * @param j
145    *          DOCUMENT ME!
146    * 
147    * @return DOCUMENT ME!
148    */
149   public boolean aboveThreshold(char c, int j)
150   {
151     if ('a' <= c && c <= 'z')
152     {
153       // TO UPPERCASE !!!
154       // Faster than toUpperCase
155       c -= ('a' - 'A');
156     }
157
158     if (consensus == null || consensus.length < j || consensus[j] == null)
159     {
160       return false;
161     }
162
163     if ((((Integer) consensus[j].get(AAFrequency.MAXCOUNT)).intValue() != -1)
164             && consensus[j].contains(String.valueOf(c)))
165     {
166       if (((Float) consensus[j].get(ignoreGaps)).floatValue() >= threshold)
167       {
168         return true;
169       }
170     }
171
172     return false;
173   }
174
175   public boolean conservationApplied()
176   {
177     return conservationColouring;
178   }
179
180   public void setConservationInc(int i)
181   {
182     inc = i;
183   }
184
185   public int getConservationInc()
186   {
187     return inc;
188   }
189
190   /**
191    * DOCUMENT ME!
192    * 
193    * @param consensus
194    *          DOCUMENT ME!
195    */
196   public void setConsensus(Hashtable[] consensus)
197   {
198     if (consensus == null)
199     {
200       return;
201     }
202
203     this.consensus = consensus;
204   }
205
206   public void setConservation(Conservation cons)
207   {
208     if (cons == null)
209     {
210       conservationColouring = false;
211       conservation = null;
212     }
213     else
214     {
215       conservationColouring = true;
216       int i, iSize = cons.getConsSequence().getLength();
217       conservation = new char[iSize];
218       for (i = 0; i < iSize; i++)
219       {
220         conservation[i] = cons.getConsSequence().getCharAt(i);
221       }
222       conservationLength = conservation.length;
223     }
224
225   }
226
227   /**
228    * DOCUMENT ME!
229    * 
230    * @param s
231    *          DOCUMENT ME!
232    * @param i
233    *          DOCUMENT ME!
234    * 
235    * @return DOCUMENT ME!
236    */
237
238   Color applyConservation(Color currentColour, int i)
239   {
240
241     if ((conservationLength > i) && (conservation[i] != '*')
242             && (conservation[i] != '+'))
243     {
244       if (jalview.util.Comparison.isGap(conservation[i]))
245       {
246         currentColour = Color.white;
247       }
248       else
249       {
250         float t = 11 - (conservation[i] - '0');
251         if (t == 0)
252         {
253           return Color.white;
254         }
255
256         int red = currentColour.getRed();
257         int green = currentColour.getGreen();
258         int blue = currentColour.getBlue();
259
260         int dr = 255 - red;
261         int dg = 255 - green;
262         int db = 255 - blue;
263
264         dr *= t / 10f;
265         dg *= t / 10f;
266         db *= t / 10f;
267
268         red += (inc / 20f) * dr;
269         green += (inc / 20f) * dg;
270         blue += (inc / 20f) * db;
271
272         if (red > 255 || green > 255 || blue > 255)
273         {
274           currentColour = Color.white;
275         }
276         else
277         {
278           currentColour = new Color(red, green, blue);
279         }
280       }
281     }
282     return currentColour;
283   }
284
285   @Override
286   public void alignmentChanged(AnnotatedCollectionI alignment,
287           Map<SequenceI, SequenceCollectionI> hiddenReps)
288   {
289   }
290
291 }