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