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