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