JAL-2189 format tests
[jalview.git] / test / jalview / schemes / FeatureColourTest.java
1 package jalview.schemes;
2
3 import static org.testng.AssertJUnit.assertEquals;
4 import static org.testng.AssertJUnit.assertFalse;
5 import static org.testng.AssertJUnit.assertTrue;
6 import static org.testng.AssertJUnit.fail;
7
8 import jalview.datamodel.SequenceFeature;
9 import jalview.util.Format;
10
11 import java.awt.Color;
12
13 import org.testng.annotations.Test;
14
15 public class FeatureColourTest
16 {
17   @Test(groups = { "Functional" })
18   public void testCopyConstructor()
19   {
20     /*
21      * plain colour
22      */
23     FeatureColour fc = new FeatureColour(Color.RED);
24     FeatureColour fc1 = new FeatureColour(fc);
25     assertTrue(fc1.getColour().equals(Color.RED));
26     assertFalse(fc1.isGraduatedColour());
27     assertFalse(fc1.isColourByLabel());
28
29     /*
30      * min-max colour
31      */
32     fc = new FeatureColour(Color.gray, Color.black, 10f, 20f);
33     fc.setAboveThreshold(true);
34     fc.setThreshold(12f);
35     fc1 = new FeatureColour(fc);
36     assertTrue(fc1.isGraduatedColour());
37     assertFalse(fc1.isColourByLabel());
38     assertTrue(fc1.isAboveThreshold());
39     assertEquals(12f, fc1.getThreshold());
40     assertEquals(Color.gray, fc1.getMinColour());
41     assertEquals(Color.black, fc1.getMaxColour());
42     assertEquals(10f, fc1.getMin());
43     assertEquals(20f, fc1.getMax());
44
45     /*
46      * colour by label
47      */
48     fc = new FeatureColour();
49     fc.setColourByLabel(true);
50     fc1 = new FeatureColour(fc);
51     assertTrue(fc1.isColourByLabel());
52     assertFalse(fc1.isGraduatedColour());
53   }
54
55   @Test(groups = { "Functional" })
56   public void testIsColored_simpleColour()
57   {
58     FeatureColour fc = new FeatureColour(Color.RED);
59     assertTrue(fc.isColored(new SequenceFeature()));
60   }
61
62   @Test(groups = { "Functional" })
63   public void testIsColored_colourByLabel()
64   {
65     FeatureColour fc = new FeatureColour();
66     fc.setColourByLabel(true);
67     assertTrue(fc.isColored(new SequenceFeature()));
68   }
69
70   @Test(groups = { "Functional" })
71   public void testIsColored_aboveThreshold()
72   {
73     // graduated colour range from score 20 to 100
74     FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f,
75             100f);
76
77     // score 0 is adjusted to bottom of range
78     SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f,
79             null);
80     assertTrue(fc.isColored(sf));
81     assertEquals(Color.WHITE, fc.getColor(sf));
82
83     // score 120 is adjusted to top of range
84     sf.setScore(120f);
85     assertEquals(Color.BLACK, fc.getColor(sf));
86
87     // value below threshold is still rendered
88     // setting threshold has no effect yet...
89     fc.setThreshold(60f);
90     sf.setScore(36f);
91     assertTrue(fc.isColored(sf));
92     assertEquals(new Color(204, 204, 204), fc.getColor(sf));
93
94     // now apply threshold:
95     fc.setAboveThreshold(true);
96     assertFalse(fc.isColored(sf));
97     // colour is still returned though ?!?
98     assertEquals(new Color(204, 204, 204), fc.getColor(sf));
99
100     sf.setScore(84); // above threshold now
101     assertTrue(fc.isColored(sf));
102     assertEquals(new Color(51, 51, 51), fc.getColor(sf));
103   }
104
105   @Test(groups = { "Functional" })
106   public void testGetColor_simpleColour()
107   {
108     FeatureColour fc = new FeatureColour(Color.RED);
109     assertEquals(Color.RED, fc.getColor(new SequenceFeature()));
110   }
111
112   @Test(groups = { "Functional" })
113   public void testGetColor_colourByLabel()
114   {
115     FeatureColour fc = new FeatureColour();
116     fc.setColourByLabel(true);
117     SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 1f,
118             null);
119     Color expected = UserColourScheme.createColourFromName("desc");
120     assertEquals(expected, fc.getColor(sf));
121   }
122
123   @Test(groups = { "Functional" })
124   public void testGetColor_Graduated()
125   {
126     // graduated colour from score 0 to 100, gray(128, 128, 128) to red(255, 0,
127     // 0)
128     FeatureColour fc = new FeatureColour(Color.GRAY, Color.RED, 0f, 100f);
129     // feature score is 75 which is 3/4 of the way from GRAY to RED
130     SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 75f,
131             null);
132     // the colour gradient is computed in float values from 0-1 (where 1 == 255)
133     float red = 128 / 255f + 3 / 4f * (255 - 128) / 255f;
134     float green = 128 / 255f + 3 / 4f * (0 - 128) / 255f;
135     float blue = 128 / 255f + 3 / 4f * (0 - 128) / 255f;
136     Color expected = new Color(red, green, blue);
137     assertEquals(expected, fc.getColor(sf));
138   }
139
140   @Test(groups = { "Functional" })
141   public void testGetColor_belowThreshold()
142   {
143     // gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0)
144     FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f,
145             150f);
146     SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f,
147             null);
148     fc.setThreshold(100f); // ignore for now
149     assertTrue(fc.isColored(sf));
150     assertEquals(new Color(204, 204, 204), fc.getColor(sf));
151
152     fc.setAboveThreshold(true); // feature lies below threshold
153     assertFalse(fc.isColored(sf));
154     assertEquals(new Color(204, 204, 204), fc.getColor(sf));
155   }
156
157   /**
158    * Test output of feature colours to Jalview features file format
159    */
160   @Test(groups = { "Functional" })
161   public void testToJalviewFormat()
162   {
163     /*
164      * plain colour - to RGB hex code
165      */
166     FeatureColour fc = new FeatureColour(Color.RED);
167     String redHex = Format.getHexString(Color.RED);
168     String hexColour = redHex;
169     assertEquals("domain\t" + hexColour, fc.toJalviewFormat("domain"));
170
171     /*
172      * colour by label (no threshold)
173      */
174     fc = new FeatureColour();
175     fc.setColourByLabel(true);
176     assertEquals("domain\tlabel", fc.toJalviewFormat("domain"));
177
178     /*
179      * colour by label (autoscaled) (an odd state you can reach by selecting
180      * 'above threshold', then deselecting 'threshold is min/max' then 'colour
181      * by label')
182      */
183     fc.setAutoScaled(true);
184     assertEquals("domain\tlabel", fc.toJalviewFormat("domain"));
185
186     /*
187      * colour by label (above threshold) (min/max values are output though not
188      * used by this scheme)
189      */
190     fc.setAutoScaled(false);
191     fc.setThreshold(12.5f);
192     fc.setAboveThreshold(true);
193     assertEquals("domain\tlabel|||0.0|0.0|above|12.5",
194             fc.toJalviewFormat("domain"));
195
196     /*
197      * colour by label (below threshold)
198      */
199     fc.setBelowThreshold(true);
200     assertEquals("domain\tlabel|||0.0|0.0|below|12.5",
201             fc.toJalviewFormat("domain"));
202
203     /*
204      * graduated colour, no threshold
205      */
206     fc = new FeatureColour(Color.GREEN, Color.RED, 12f, 25f);
207     String greenHex = Format.getHexString(Color.GREEN);
208     String expected = String.format("domain\t%s|%s|abso|12.0|25.0|none",
209             greenHex, redHex);
210     assertEquals(expected, fc.toJalviewFormat("domain"));
211
212     /*
213      * colour ranges over the actual score ranges (not min/max)
214      */
215     fc.setAutoScaled(true);
216     expected = String.format("domain\t%s|%s|12.0|25.0|none", greenHex,
217             redHex);
218     assertEquals(expected, fc.toJalviewFormat("domain"));
219
220     /*
221      * graduated colour below threshold
222      */
223     fc.setThreshold(12.5f);
224     fc.setBelowThreshold(true);
225     expected = String.format("domain\t%s|%s|12.0|25.0|below|12.5",
226             greenHex, redHex);
227     assertEquals(expected, fc.toJalviewFormat("domain"));
228
229     /*
230      * graduated colour above threshold
231      */
232     fc.setThreshold(12.5f);
233     fc.setAboveThreshold(true);
234     fc.setAutoScaled(false);
235     expected = String.format("domain\t%s|%s|abso|12.0|25.0|above|12.5",
236             greenHex, redHex);
237     assertEquals(expected, fc.toJalviewFormat("domain"));
238   }
239
240   /**
241    * Test parsing of feature colours from Jalview features file format
242    */
243   @Test(groups = { "Functional" })
244   public void testParseJalviewFeatureColour()
245   {
246     /*
247      * simple colour by name
248      */
249     FeatureColour fc = FeatureColour.parseJalviewFeatureColour("red");
250     assertTrue(fc.isSimpleColour());
251     assertEquals(Color.RED, fc.getColour());
252
253     /*
254      * simple colour by hex code
255      */
256     fc = FeatureColour.parseJalviewFeatureColour(Format
257             .getHexString(Color.RED));
258     assertTrue(fc.isSimpleColour());
259     assertEquals(Color.RED, fc.getColour());
260
261     /*
262      * simple colour by rgb triplet
263      */
264     fc = FeatureColour.parseJalviewFeatureColour("255,0,0");
265     assertTrue(fc.isSimpleColour());
266     assertEquals(Color.RED, fc.getColour());
267
268     /*
269      * malformed colour
270      */
271     try
272     {
273       fc = FeatureColour.parseJalviewFeatureColour("oops");
274       fail("expected exception");
275     } catch (IllegalArgumentException e)
276     {
277       assertEquals("Invalid colour descriptor: oops", e.getMessage());
278     }
279
280     /*
281      * colour by label (no threshold)
282      */
283     fc = FeatureColour.parseJalviewFeatureColour("label");
284     assertTrue(fc.isColourByLabel());
285     assertFalse(fc.hasThreshold());
286
287     /*
288      * colour by label (with threshold)
289      */
290     fc = FeatureColour
291             .parseJalviewFeatureColour("label|||0.0|0.0|above|12.0");
292     assertTrue(fc.isColourByLabel());
293     assertTrue(fc.isAboveThreshold());
294     assertEquals(12.0f, fc.getThreshold());
295
296     /*
297      * graduated colour (by name) (no threshold)
298      */
299     fc = FeatureColour.parseJalviewFeatureColour("red|green|10.0|20.0");
300     assertTrue(fc.isGraduatedColour());
301     assertFalse(fc.hasThreshold());
302     assertEquals(Color.RED, fc.getMinColour());
303     assertEquals(Color.GREEN, fc.getMaxColour());
304     assertEquals(10f, fc.getMin());
305     assertEquals(20f, fc.getMax());
306     assertTrue(fc.isAutoScaled());
307
308     /*
309      * graduated colour (by hex code) (above threshold)
310      */
311     String descriptor = String.format("%s|%s|10.0|20.0|above|15",
312             Format.getHexString(Color.RED),
313             Format.getHexString(Color.GREEN));
314     fc = FeatureColour.parseJalviewFeatureColour(descriptor);
315     assertTrue(fc.isGraduatedColour());
316     assertTrue(fc.hasThreshold());
317     assertTrue(fc.isAboveThreshold());
318     assertEquals(15f, fc.getThreshold());
319     assertEquals(Color.RED, fc.getMinColour());
320     assertEquals(Color.GREEN, fc.getMaxColour());
321     assertEquals(10f, fc.getMin());
322     assertEquals(20f, fc.getMax());
323     assertTrue(fc.isAutoScaled());
324
325     /*
326      * graduated colour (by RGB triplet) (below threshold), absolute scale
327      */
328     descriptor = String.format("255,0,0|0,255,0|abso|10.0|20.0|below|15");
329     fc = FeatureColour.parseJalviewFeatureColour(descriptor);
330     assertTrue(fc.isGraduatedColour());
331     assertFalse(fc.isAutoScaled());
332     assertTrue(fc.hasThreshold());
333     assertTrue(fc.isBelowThreshold());
334     assertEquals(15f, fc.getThreshold());
335     assertEquals(Color.RED, fc.getMinColour());
336     assertEquals(Color.GREEN, fc.getMaxColour());
337     assertEquals(10f, fc.getMin());
338     assertEquals(20f, fc.getMax());
339
340     descriptor = String
341             .format("blue|255,0,255|absolute|20.0|95.0|below|66.0");
342     fc = FeatureColour.parseJalviewFeatureColour(descriptor);
343     assertTrue(fc.isGraduatedColour());
344   }
345 }