Merge branch 'feature/JAL-3127_seqidChainshading' into merge/JAL-3127
[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,
221               200 - 10 * col,
222               150 + 10 * col);
223       assertEquals(result, expected, "for column " + col);
224     }
225   
226     /*
227      * now make 6-10 the span of the colour range
228      * (annotation value == column number in this test)
229      */
230     testee.setThresholdIsMinMax(true);
231     for (int col = 0; col < WIDTH; col++)
232     {
233       /*
234        * colours for values > threshold are graduated
235        * range is 6-10 so steps of 100/5 = 20
236        */
237       int factor = col - THRESHOLD_FIVE;
238       Color expected = col <= 5 ? Color.white
239               : new Color(50 + 20 * factor,
240               200 - 20 * factor,
241               150 + 20 * factor);
242       Color result = testee.findColour('a', col, seq);
243       assertEquals(result, expected, "for column " + col);
244     }
245   }
246
247   /**
248    * Test the 'colour below threshold' case
249    */
250   @Test(groups = "Functional")
251   public void testFindColour_belowThreshold()
252   {
253     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
254             minColour, maxColour, AnnotationColourGradient.BELOW_THRESHOLD);
255     testee = (AnnotationColourGradient) testee.getInstance(null, al);
256   
257     for (int col = 0; col < WIDTH; col++)
258     {
259       Color result = testee.findColour('a', col, seq);
260       Color expected = col >= 5 ? Color.white
261               : new Color(50 + 10 * col,
262               200 - 10 * col, 150 + 10 * col);
263       assertEquals(result, expected, "for column " + col);
264     }
265   
266     /*
267      * now make 0-5 the span of the colour range
268      * (annotation value == column number in this test)
269      */
270     testee.setThresholdIsMinMax(true);
271     for (int col = 0; col < WIDTH; col++)
272     {
273       /*
274        * colours for values < threshold are graduated
275        * range is 0-5 so steps of 100/5 = 20
276        */
277       Color expected = col >= 5 ? Color.white
278               : new Color(50 + 20 * col,
279               200 - 20 * col, 150 + 20 * col);
280       Color result = testee.findColour('a', col, seq);
281       assertEquals(result, expected, "for column " + col);
282     }
283   }
284
285   @Test(groups = "Functional")
286   public void testFindColour_noThreshold()
287   {
288     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
289             minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
290     testee = (AnnotationColourGradient) testee.getInstance(null, al);
291
292     for (int col = 0; col < WIDTH; col++)
293     {
294       Color result = testee.findColour('a', col, seq);
295       /*
296        * column <n> is n/10 of the way from minCol to maxCol
297        */
298       Color expected = new Color(50 + 10 * col, 200 - 10 * col,
299               150 + 10 * col);
300       assertEquals(result, expected, "for column " + col);
301     }
302   }
303
304   @Test(groups = "Functional")
305   public void testFindColour_originalColours()
306   {
307     AnnotationColourGradient testee = new AnnotationColourGradient(ann,
308             minColour, maxColour, AnnotationColourGradient.NO_THRESHOLD);
309     testee = (AnnotationColourGradient) testee.getInstance(null, al);
310
311     /*
312      * flag corresponding to 'use original colours' checkbox
313      * - just use the individual annotation colours
314      */
315     testee.setPredefinedColours(true);
316
317     /*
318      * the annotation colour is returned, except for column 0 where it is
319      * black - in this case the colour scheme colour overrides it
320      */
321     for (int col = 0; col < WIDTH; col++)
322     {
323       int hue = col * 20;
324       Color c = col == 0 ? minColour : new Color(hue, hue, hue);
325       assertEquals(testee.findColour('a', col, seq), c, "for column " + col);
326     }
327   }
328 }