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