3c49ec2e6371098035436881c0873ed4fc0018bf
[jalview.git] / test / jalview / schemes / AnnotationColourGradientTest.java
1 package jalview.schemes;
2
3 import static org.testng.Assert.assertEquals;
4
5 import jalview.datamodel.Alignment;
6 import jalview.datamodel.AlignmentAnnotation;
7 import jalview.datamodel.AlignmentI;
8 import jalview.datamodel.Annotation;
9 import jalview.datamodel.GraphLine;
10 import jalview.datamodel.Sequence;
11 import jalview.datamodel.SequenceI;
12
13 import java.awt.Color;
14
15 import org.testng.annotations.BeforeClass;
16 import org.testng.annotations.Test;
17
18 public class AnnotationColourGradientTest
19 {
20   final static int WIDTH = 11;
21
22   final static int THRESHOLD_FIVE = 5;
23
24   private AlignmentAnnotation ann;
25
26   private SequenceI seq;
27
28   private AlignmentI al;
29
30   Color minColour = new Color(50, 200, 150);
31
32   Color maxColour = new Color(150, 100, 250);
33
34   /**
35    * Setup creates an annotation over 11 columns with values 0-10 and threshold
36    * 5
37    */
38   @BeforeClass(alwaysRun = true)
39   public void setUp()
40   {
41     Annotation[] anns = new Annotation[WIDTH];
42     /*
43      * set annotations with values 0-10, graded colours
44      */
45     for (int col = 0; col < WIDTH; col++)
46     {
47       int hue = col * 20;
48       Color colour = new Color(hue, hue, hue);
49       anns[col] = new Annotation("a", "a", 'a', col, colour);
50     }
51
52     seq = new Sequence("Seq", "");
53     al = new Alignment(new SequenceI[] { seq });
54
55     /*
56      * AlignmentAnnotation constructor works out min-max range
57      */
58     ann = new AlignmentAnnotation("", "", anns);
59     ann.setThreshold(new GraphLine(THRESHOLD_FIVE, "", Color.RED));
60     seq.addAlignmentAnnotation(ann);
61   }
62
63   @Test(groups = "Functional")
64   public void testShadeCalculation_noThreshold()
65   {
66     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
67             minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
68     for (int col = 0; col < WIDTH; col++)
69     {
70       Color result = testee.shadeCalculation(ann, col);
71       /*
72        * column <n> is n/10 of the way from minCol to maxCol
73        */
74       Color expected = new Color(50 + 10 * col, 200 - 10 * col,
75               150 + 10 * col);
76       assertEquals(result, expected, "for column " + col);
77     }
78   }
79
80   /**
81    * Test the 'colour above threshold' case
82    */
83   @Test(groups = "Functional")
84   public void testShadeCalculation_aboveThreshold()
85   {
86     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
87             minColour, maxColour, AnnotationColourGradient.ABOVE_THRESHOLD);
88     for (int col = 0; col < WIDTH; col++)
89     {
90       Color result = testee.shadeCalculation(ann, col);
91       /*
92        * colour is derived regardless of the threshold value 
93        * (the renderer will suppress colouring if above/below threshold)
94        */
95       Color expected = new Color(50 + 10 * col, 200 - 10 * col,
96               150 + 10 * col);
97       assertEquals(result, expected, "for column " + col);
98     }
99
100     /*
101      * now make 6-10 the span of the colour range
102      * (annotation value == column number in this test)
103      */
104     testee.setThresholdIsMinMax(true);
105     for (int col = 0; col < THRESHOLD_FIVE; col++)
106     {
107       /*
108        * colours below the threshold are computed as before
109        */
110       Color expected = new Color(50 + 10 * col, 200 - 10 * col,
111               150 + 10 * col);
112       Color result = testee.shadeCalculation(ann, col);
113       assertEquals(result, expected, "for column " + col);
114     }
115     for (int col = THRESHOLD_FIVE; col < WIDTH; col++)
116     {
117       /*
118        * colours for values >= threshold are graduated
119        * range is 6-10 so steps of 100/5 = 20
120        */
121       int factor = col - THRESHOLD_FIVE;
122       Color expected = new Color(50 + 20 * factor, 200 - 20 * factor,
123               150 + 20 * factor);
124       Color result = testee.shadeCalculation(ann, col);
125       assertEquals(result, expected, "for column " + col);
126     }
127
128     /*
129      * test for boundary case threshold == graphMax (JAL-3206)
130      */
131     float thresh = ann.threshold.value;
132     ann.threshold.value = ann.graphMax;
133     Color result = testee.shadeCalculation(ann, WIDTH - 1);
134     assertEquals(result, maxColour);
135     testee.setThresholdIsMinMax(false);
136     result = testee.shadeCalculation(ann, WIDTH - 1);
137     assertEquals(result, maxColour);
138     ann.threshold.value = thresh; // reset
139   }
140
141   /**
142    * Test the 'colour below threshold' case
143    */
144   @Test(groups = "Functional")
145   public void testShadeCalculation_belowThreshold()
146   {
147     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
148             minColour, maxColour, AnnotationColourGradient.BELOW_THRESHOLD);
149
150     for (int col = 0; col < WIDTH; col++)
151     {
152       Color result = testee.shadeCalculation(ann, col);
153       /*
154        * colour is derived regardless of the threshold value 
155        * (the renderer will suppress colouring if above/below threshold)
156        */
157       Color expected = new Color(50 + 10 * col, 200 - 10 * col,
158               150 + 10 * col);
159       assertEquals(result, expected, "for column " + col);
160     }
161
162     /*
163      * now make 0-5 the span of the colour range
164      * (annotation value == column number in this test)
165      */
166     testee.setThresholdIsMinMax(true);
167     for (int col = THRESHOLD_FIVE + 1; col < WIDTH; col++)
168     {
169       /*
170        * colours above the threshold are computed as before
171        */
172       Color expected = new Color(50 + 10 * col, 200 - 10 * col,
173               150 + 10 * col);
174       Color result = testee.shadeCalculation(ann, col);
175       assertEquals(result, expected, "for column " + col);
176     }
177
178     for (int col = 0; col <= THRESHOLD_FIVE; col++)
179     {
180       /*
181        * colours for values <= threshold are graduated
182        * range is 0-5 so steps of 100/5 = 20
183        */
184       Color expected = new Color(50 + 20 * col, 200 - 20 * col,
185               150 + 20 * col);
186       Color result = testee.shadeCalculation(ann, col);
187       assertEquals(result, expected, "for column " + col);
188     }
189
190     /*
191      * test for boundary case threshold == graphMin (JAL-3206)
192      */
193     float thresh = ann.threshold.value;
194     ann.threshold.value = ann.graphMin;
195     Color result = testee.shadeCalculation(ann, 0);
196     assertEquals(result, minColour);
197     testee.setThresholdIsMinMax(false);
198     result = testee.shadeCalculation(ann, 0);
199     assertEquals(result, minColour);
200     ann.threshold.value = thresh; // reset
201   }
202
203   /**
204    * Test the 'colour above threshold' case
205    */
206   @Test(groups = "Functional")
207   public void testFindColour_aboveThreshold()
208   {
209     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
210             minColour, maxColour, AnnotationColourGradient.ABOVE_THRESHOLD);
211     testee = (AnnotationColourGradient) testee.getInstance(null, al);
212
213     for (int col = 0; col < WIDTH; col++)
214     {
215       Color result = testee.findColour('a', col, seq);
216       /*
217        * expect white at or below threshold of 5
218        */
219       Color expected = col <= 5 ? Color.white
220               : new Color(50 + 10 * col, 200 - 10 * col, 150 + 10 * col);
221       assertEquals(result, expected, "for column " + col);
222     }
223
224     /*
225      * now make 6-10 the span of the colour range
226      * (annotation value == column number in this test)
227      */
228     testee.setThresholdIsMinMax(true);
229     for (int col = 0; col < WIDTH; col++)
230     {
231       /*
232        * colours for values > threshold are graduated
233        * range is 6-10 so steps of 100/5 = 20
234        */
235       int factor = col - THRESHOLD_FIVE;
236       Color expected = col <= 5 ? Color.white
237               : new Color(50 + 20 * factor, 200 - 20 * factor,
238                       150 + 20 * factor);
239       Color result = testee.findColour('a', col, seq);
240       assertEquals(result, expected, "for column " + col);
241     }
242   }
243
244   /**
245    * Test the 'colour below threshold' case
246    */
247   @Test(groups = "Functional")
248   public void testFindColour_belowThreshold()
249   {
250     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
251             minColour, maxColour, AnnotationColourGradient.BELOW_THRESHOLD);
252     testee = (AnnotationColourGradient) testee.getInstance(null, al);
253
254     for (int col = 0; col < WIDTH; col++)
255     {
256       Color result = testee.findColour('a', col, seq);
257       Color expected = col >= 5 ? Color.white
258               : new Color(50 + 10 * col, 200 - 10 * col, 150 + 10 * col);
259       assertEquals(result, expected, "for column " + col);
260     }
261
262     /*
263      * now make 0-5 the span of the colour range
264      * (annotation value == column number in this test)
265      */
266     testee.setThresholdIsMinMax(true);
267     for (int col = 0; col < WIDTH; col++)
268     {
269       /*
270        * colours for values < threshold are graduated
271        * range is 0-5 so steps of 100/5 = 20
272        */
273       Color expected = col >= 5 ? Color.white
274               : new Color(50 + 20 * col, 200 - 20 * col, 150 + 20 * col);
275       Color result = testee.findColour('a', col, seq);
276       assertEquals(result, expected, "for column " + col);
277     }
278   }
279
280   @Test(groups = "Functional")
281   public void testFindColour_noThreshold()
282   {
283     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
284             minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
285     testee = (AnnotationColourGradient) testee.getInstance(null, al);
286
287     for (int col = 0; col < WIDTH; col++)
288     {
289       Color result = testee.findColour('a', col, seq);
290       /*
291        * column <n> is n/10 of the way from minCol to maxCol
292        */
293       Color expected = new Color(50 + 10 * col, 200 - 10 * col,
294               150 + 10 * col);
295       assertEquals(result, expected, "for column " + col);
296     }
297   }
298
299   @Test(groups = "Functional")
300   public void testFindColour_originalColours()
301   {
302     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
303             minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
304     testee = (AnnotationColourGradient) testee.getInstance(null, al);
305
306     /*
307      * flag corresponding to 'use original colours' checkbox
308      * - just use the individual annotation colours
309      */
310     testee.setPredefinedColours(true);
311
312     /*
313      * the annotation colour is returned, except for column 0 where it is
314      * black - in this case the colour scheme colour overrides it
315      */
316     for (int col = 0; col < WIDTH; col++)
317     {
318       int hue = col * 20;
319       Color c = col == 0 ? minColour : new Color(hue, hue, hue);
320       assertEquals(testee.findColour('a', col, seq), c,
321               "for column " + col);
322     }
323   }
324 }