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