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