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