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