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