JAL-1517 fix copyright for 2.8.2
[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   @Override
200   public void setConservationApplied(boolean conservationApplied)
201   {
202     conservationColouring = conservationApplied;
203   }
204
205   public void setConservationInc(int i)
206   {
207     inc = i;
208   }
209
210   public int getConservationInc()
211   {
212     return inc;
213   }
214
215   /**
216    * DOCUMENT ME!
217    * 
218    * @param consensus
219    *          DOCUMENT ME!
220    */
221   public void setConsensus(Hashtable[] consensus)
222   {
223     if (consensus == null)
224     {
225       return;
226     }
227
228     this.consensus = consensus;
229   }
230
231   public void setConservation(Conservation cons)
232   {
233     if (cons == null)
234     {
235       conservationColouring = false;
236       conservation = null;
237     }
238     else
239     {
240       conservationColouring = true;
241       int i, iSize = cons.getConsSequence().getLength();
242       conservation = new char[iSize];
243       for (i = 0; i < iSize; i++)
244       {
245         conservation[i] = cons.getConsSequence().getCharAt(i);
246       }
247       conservationLength = conservation.length;
248     }
249
250   }
251
252   /**
253    * DOCUMENT ME!
254    * 
255    * @param s
256    *          DOCUMENT ME!
257    * @param i
258    *          DOCUMENT ME!
259    * 
260    * @return DOCUMENT ME!
261    */
262
263   Color applyConservation(Color currentColour, int i)
264   {
265
266     if ((conservationLength > i) && (conservation[i] != '*')
267             && (conservation[i] != '+'))
268     {
269       if (jalview.util.Comparison.isGap(conservation[i]))
270       {
271         currentColour = Color.white;
272       }
273       else
274       {
275         float t = 11 - (conservation[i] - '0');
276         if (t == 0)
277         {
278           return Color.white;
279         }
280
281         int red = currentColour.getRed();
282         int green = currentColour.getGreen();
283         int blue = currentColour.getBlue();
284
285         int dr = 255 - red;
286         int dg = 255 - green;
287         int db = 255 - blue;
288
289         dr *= t / 10f;
290         dg *= t / 10f;
291         db *= t / 10f;
292
293         red += (inc / 20f) * dr;
294         green += (inc / 20f) * dg;
295         blue += (inc / 20f) * db;
296
297         if (red > 255 || green > 255 || blue > 255)
298         {
299           currentColour = Color.white;
300         }
301         else
302         {
303           currentColour = new Color(red, green, blue);
304         }
305       }
306     }
307     return currentColour;
308   }
309
310   @Override
311   public void alignmentChanged(AnnotatedCollectionI alignment,
312           Map<SequenceI, SequenceCollectionI> hiddenReps)
313   {
314   }
315
316   @Override
317   public ColourSchemeI applyTo(AnnotatedCollectionI sg,
318           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
319   {
320     try {
321       return getClass().newInstance();
322     }
323     catch (Exception q)
324     {
325       throw new Error("Serious implementation error: cannot duplicate colourscheme "+getClass().getName(), q);
326     }
327   }
328 }