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