JAL-1397 propagate any consensus/conservation colourscheme state changes to the backg...
[jalview.git] / src / jalview / schemes / AnnotationColourGradient.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, 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 jalview.analysis.Conservation;
21 import jalview.datamodel.AlignmentAnnotation;
22 import jalview.datamodel.AnnotatedCollectionI;
23 import jalview.datamodel.GraphLine;
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.IdentityHashMap;
30 import java.util.Map;
31
32 public class AnnotationColourGradient extends ResidueColourScheme
33 {
34   public static final int NO_THRESHOLD = -1;
35
36   public static final int BELOW_THRESHOLD = 0;
37
38   public static final int ABOVE_THRESHOLD = 1;
39
40   public AlignmentAnnotation annotation;
41
42   int aboveAnnotationThreshold = -1;
43
44   public boolean thresholdIsMinMax = false;
45
46   GraphLine annotationThreshold;
47
48   float r1, g1, b1, rr, gg, bb, dr, dg, db;
49
50   ColourSchemeI colourScheme;
51
52   private boolean predefinedColours = false;
53
54   private boolean seqAssociated = false;
55
56   IdentityHashMap<SequenceI, AlignmentAnnotation> seqannot = null;
57
58   /**
59    * Creates a new AnnotationColourGradient object.
60    */
61   public AnnotationColourGradient(AlignmentAnnotation annotation,
62           ColourSchemeI originalColour, int aboveThreshold)
63   {
64     if (originalColour instanceof AnnotationColourGradient)
65     {
66       colourScheme = ((AnnotationColourGradient) originalColour).colourScheme;
67     }
68     else
69     {
70       colourScheme = originalColour;
71     }
72
73     this.annotation = annotation;
74
75     aboveAnnotationThreshold = aboveThreshold;
76
77     if (aboveThreshold != NO_THRESHOLD && annotation.threshold != null)
78     {
79       annotationThreshold = annotation.threshold;
80     }
81   }
82
83   /**
84    * Creates a new AnnotationColourGradient object.
85    */
86   public AnnotationColourGradient(AlignmentAnnotation annotation,
87           Color minColour, Color maxColour, int aboveThreshold)
88   {
89     this.annotation = annotation;
90
91     aboveAnnotationThreshold = aboveThreshold;
92
93     if (aboveThreshold != NO_THRESHOLD && annotation.threshold != null)
94     {
95       annotationThreshold = annotation.threshold;
96     }
97
98     r1 = minColour.getRed();
99     g1 = minColour.getGreen();
100     b1 = minColour.getBlue();
101
102     rr = maxColour.getRed() - r1;
103     gg = maxColour.getGreen() - g1;
104     bb = maxColour.getBlue() - b1;
105   }
106
107   @Override
108   public void alignmentChanged(AnnotatedCollectionI alignment,
109           Map<SequenceI, SequenceCollectionI> hiddenReps)
110   {
111     // TODO Auto-generated method stub
112     super.alignmentChanged(alignment, hiddenReps);
113
114     if (seqAssociated && annotation.getCalcId() != null)
115     {
116       if (seqannot != null)
117       {
118         seqannot.clear();
119       }
120       else
121       {
122         seqannot = new IdentityHashMap<SequenceI, AlignmentAnnotation>();
123       }
124       for (AlignmentAnnotation alan : alignment.findAnnotation(annotation
125               .getCalcId()))
126       {
127         if (alan.sequenceRef != null
128                 && (alan.label != null && annotation != null && alan.label
129                         .equals(annotation.label)))
130         {
131           seqannot.put(alan.sequenceRef, alan);
132         }
133       }
134     }
135   }
136
137   public String getAnnotation()
138   {
139     return annotation.label;
140   }
141
142   public int getAboveThreshold()
143   {
144     return aboveAnnotationThreshold;
145   }
146
147   public float getAnnotationThreshold()
148   {
149     if (annotationThreshold == null)
150     {
151       return 0;
152     }
153     else
154     {
155       return annotationThreshold.value;
156     }
157   }
158
159   public ColourSchemeI getBaseColour()
160   {
161     return colourScheme;
162   }
163
164   public Color getMinColour()
165   {
166     return new Color((int) r1, (int) g1, (int) b1);
167   }
168
169   public Color getMaxColour()
170   {
171     return new Color((int) (r1 + rr), (int) (g1 + gg), (int) (b1 + bb));
172   }
173
174   /**
175    * DOCUMENT ME!
176    * 
177    * @param n
178    *          DOCUMENT ME!
179    * 
180    * @return DOCUMENT ME!
181    */
182   public Color findColour(char c)
183   {
184     return Color.red;
185   }
186
187   /**
188    * DOCUMENT ME!
189    * 
190    * @param n
191    *          DOCUMENT ME!
192    * @param j
193    *          DOCUMENT ME!
194    * 
195    * @return DOCUMENT ME!
196    */
197   @Override
198   public Color findColour(char c, int j, SequenceI seq)
199   {
200     Color currentColour = Color.white;
201     AlignmentAnnotation annotation = (seqAssociated ? seqannot.get(seq)
202             : this.annotation);
203     if (annotation == null)
204     {
205       return currentColour;
206     }
207     if ((threshold == 0) || aboveThreshold(c, j))
208     {
209       if (j < annotation.annotations.length
210               && annotation.annotations[j] != null
211               && !jalview.util.Comparison.isGap(c))
212       {
213
214         if (predefinedColours)
215         {
216           if (annotation.annotations[j].colour != null)
217             return annotation.annotations[j].colour;
218           else
219             return currentColour;
220         }
221
222         if (aboveAnnotationThreshold == NO_THRESHOLD
223                 || (annotationThreshold != null
224                         && aboveAnnotationThreshold == ABOVE_THRESHOLD && annotation.annotations[j].value >= annotationThreshold.value)
225                 || (annotationThreshold != null
226                         && aboveAnnotationThreshold == BELOW_THRESHOLD && annotation.annotations[j].value <= annotationThreshold.value))
227         {
228
229           float range = 1f;
230           if (thresholdIsMinMax
231                   && annotation.threshold != null
232                   && aboveAnnotationThreshold == ABOVE_THRESHOLD
233                   && annotation.annotations[j].value >= annotation.threshold.value)
234           {
235             range = (annotation.annotations[j].value - annotation.threshold.value)
236                     / (annotation.graphMax - annotation.threshold.value);
237           }
238           else if (thresholdIsMinMax && annotation.threshold != null
239                   && aboveAnnotationThreshold == BELOW_THRESHOLD
240                   && annotation.annotations[j].value >= annotation.graphMin)
241           {
242             range = (annotation.annotations[j].value - annotation.graphMin)
243                     / (annotation.threshold.value - annotation.graphMin);
244           }
245           else
246           {
247             range = (annotation.annotations[j].value - annotation.graphMin)
248                     / (annotation.graphMax - annotation.graphMin);
249           }
250
251           if (colourScheme != null)
252           {
253             currentColour = colourScheme.findColour(c, j, seq);
254           }
255           else 
256           {
257             dr = rr * range + r1;
258             dg = gg * range + g1;
259             db = bb * range + b1;
260
261             currentColour = new Color((int) dr, (int) dg, (int) db);
262           }
263         }
264       }
265     }
266
267     if (conservationColouring)
268     {
269       currentColour = applyConservation(currentColour, j);
270     }
271
272     return currentColour;
273   }
274
275   public boolean isPredefinedColours()
276   {
277     return predefinedColours;
278   }
279
280   public void setPredefinedColours(boolean predefinedColours)
281   {
282     this.predefinedColours = predefinedColours;
283   }
284
285   public boolean isSeqAssociated()
286   {
287     return seqAssociated;
288   }
289
290   public void setSeqAssociated(boolean sassoc)
291   {
292     seqAssociated = sassoc;
293   }
294   @Override
295   public void setConsensus(Hashtable[] consensus)
296   {
297     if (colourScheme!=null)
298     {
299       colourScheme.setConsensus(consensus);
300     }
301   }
302   @Override
303   public void setConservation(Conservation cons)
304   {
305     if (colourScheme!=null)
306     {
307       colourScheme.setConservation(cons);
308     }
309   }
310   @Override
311   public void setConservationInc(int i)
312   {
313     if (colourScheme!=null)
314     {
315       colourScheme.setConservationInc(i);
316     }
317   }
318 }