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