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