2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.schemes;
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertNull;
26 import static org.testng.AssertJUnit.assertTrue;
27 import static org.testng.AssertJUnit.fail;
29 import jalview.datamodel.SequenceFeature;
30 import jalview.gui.JvOptionPane;
31 import jalview.util.ColorUtils;
32 import jalview.util.Format;
34 import java.awt.Color;
36 import org.testng.annotations.BeforeClass;
37 import org.testng.annotations.Test;
39 public class FeatureColourTest
42 @BeforeClass(alwaysRun = true)
43 public void setUpJvOptionPane()
45 JvOptionPane.setInteractiveMode(false);
46 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
49 @Test(groups = { "Functional" })
50 public void testCopyConstructor()
55 FeatureColour fc = new FeatureColour(Color.RED);
56 FeatureColour fc1 = new FeatureColour(fc);
57 assertTrue(fc1.getColour().equals(Color.RED));
58 assertFalse(fc1.isGraduatedColour());
59 assertFalse(fc1.isColourByLabel());
64 fc = new FeatureColour(Color.gray, Color.black, 10f, 20f);
65 fc.setAboveThreshold(true);
67 fc1 = new FeatureColour(fc);
68 assertTrue(fc1.isGraduatedColour());
69 assertFalse(fc1.isColourByLabel());
70 assertTrue(fc1.isAboveThreshold());
71 assertEquals(12f, fc1.getThreshold());
72 assertEquals(Color.gray, fc1.getMinColour());
73 assertEquals(Color.black, fc1.getMaxColour());
74 assertEquals(10f, fc1.getMin());
75 assertEquals(20f, fc1.getMax());
80 fc = new FeatureColour();
81 fc.setColourByLabel(true);
82 fc1 = new FeatureColour(fc);
83 assertTrue(fc1.isColourByLabel());
84 assertFalse(fc1.isGraduatedColour());
87 @Test(groups = { "Functional" })
88 public void testGetColor_simpleColour()
90 FeatureColour fc = new FeatureColour(Color.RED);
91 assertEquals(Color.RED,
92 fc.getColor(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
95 @Test(groups = { "Functional" })
96 public void testGetColor_colourByLabel()
98 FeatureColour fc = new FeatureColour();
99 fc.setColourByLabel(true);
100 SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 1f,
102 Color expected = ColorUtils.createColourFromName("desc");
103 assertEquals(expected, fc.getColor(sf));
106 @Test(groups = { "Functional" })
107 public void testGetColor_Graduated()
109 // graduated colour from score 0 to 100, gray(128, 128, 128) to red(255, 0,
111 FeatureColour fc = new FeatureColour(Color.GRAY, Color.RED, 0f, 100f);
112 // feature score is 75 which is 3/4 of the way from GRAY to RED
113 SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 75f,
115 // the colour gradient is computed in float values from 0-1 (where 1 == 255)
116 float red = 128 / 255f + 3 / 4f * (255 - 128) / 255f;
117 float green = 128 / 255f + 3 / 4f * (0 - 128) / 255f;
118 float blue = 128 / 255f + 3 / 4f * (0 - 128) / 255f;
119 Color expected = new Color(red, green, blue);
120 assertEquals(expected, fc.getColor(sf));
123 @Test(groups = { "Functional" })
124 public void testGetColor_aboveBelowThreshold()
126 // gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0)
127 FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f,
129 SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f,
133 * feature with score of Float.NaN is always assigned minimum colour
135 SequenceFeature sf2 = new SequenceFeature("type", "desc", 0, 20,
138 fc.setThreshold(100f); // ignore for now
139 assertEquals(new Color(204, 204, 204), fc.getColor(sf));
140 assertEquals(Color.white, fc.getColor(sf2));
142 fc.setAboveThreshold(true); // feature lies below threshold
143 assertNull(fc.getColor(sf));
144 assertEquals(Color.white, fc.getColor(sf2));
146 fc.setBelowThreshold(true);
147 fc.setThreshold(70f);
148 assertNull(fc.getColor(sf)); // feature score == threshold - hidden
149 assertEquals(Color.white, fc.getColor(sf2));
150 fc.setThreshold(69f);
151 assertNull(fc.getColor(sf)); // feature score > threshold - hidden
152 assertEquals(Color.white, fc.getColor(sf2));
156 * Test output of feature colours to Jalview features file format
158 @Test(groups = { "Functional" })
159 public void testToJalviewFormat()
162 * plain colour - to RGB hex code
164 FeatureColour fc = new FeatureColour(Color.RED);
165 String redHex = Format.getHexString(Color.RED);
166 String hexColour = redHex;
167 assertEquals("domain\t" + hexColour, fc.toJalviewFormat("domain"));
170 * colour by label (no threshold)
172 fc = new FeatureColour();
173 fc.setColourByLabel(true);
174 assertEquals("domain\tlabel", fc.toJalviewFormat("domain"));
177 * colour by label (autoscaled) (an odd state you can reach by selecting
178 * 'above threshold', then deselecting 'threshold is min/max' then 'colour
181 fc.setAutoScaled(true);
182 assertEquals("domain\tlabel", fc.toJalviewFormat("domain"));
185 * colour by label (above threshold) (min/max values are output though not
186 * used by this scheme)
188 fc.setAutoScaled(false);
189 fc.setThreshold(12.5f);
190 fc.setAboveThreshold(true);
191 assertEquals("domain\tlabel|||0.0|0.0|above|12.5",
192 fc.toJalviewFormat("domain"));
195 * colour by label (below threshold)
197 fc.setBelowThreshold(true);
198 assertEquals("domain\tlabel|||0.0|0.0|below|12.5",
199 fc.toJalviewFormat("domain"));
202 * graduated colour, no threshold
204 fc = new FeatureColour(Color.GREEN, Color.RED, 12f, 25f);
205 String greenHex = Format.getHexString(Color.GREEN);
206 String expected = String.format("domain\t%s|%s|abso|12.0|25.0|none",
208 assertEquals(expected, fc.toJalviewFormat("domain"));
211 * colour ranges over the actual score ranges (not min/max)
213 fc.setAutoScaled(true);
214 expected = String.format("domain\t%s|%s|12.0|25.0|none", greenHex,
216 assertEquals(expected, fc.toJalviewFormat("domain"));
219 * graduated colour below threshold
221 fc.setThreshold(12.5f);
222 fc.setBelowThreshold(true);
223 expected = String.format("domain\t%s|%s|12.0|25.0|below|12.5",
225 assertEquals(expected, fc.toJalviewFormat("domain"));
228 * graduated colour above threshold
230 fc.setThreshold(12.5f);
231 fc.setAboveThreshold(true);
232 fc.setAutoScaled(false);
233 expected = String.format("domain\t%s|%s|abso|12.0|25.0|above|12.5",
235 assertEquals(expected, fc.toJalviewFormat("domain"));
239 * Test parsing of feature colours from Jalview features file format
241 @Test(groups = { "Functional" })
242 public void testParseJalviewFeatureColour()
245 * simple colour by name
247 FeatureColour fc = FeatureColour.parseJalviewFeatureColour("red");
248 assertTrue(fc.isSimpleColour());
249 assertEquals(Color.RED, fc.getColour());
252 * simple colour by hex code
254 fc = FeatureColour.parseJalviewFeatureColour(Format
255 .getHexString(Color.RED));
256 assertTrue(fc.isSimpleColour());
257 assertEquals(Color.RED, fc.getColour());
260 * simple colour by rgb triplet
262 fc = FeatureColour.parseJalviewFeatureColour("255,0,0");
263 assertTrue(fc.isSimpleColour());
264 assertEquals(Color.RED, fc.getColour());
271 fc = FeatureColour.parseJalviewFeatureColour("oops");
272 fail("expected exception");
273 } catch (IllegalArgumentException e)
275 assertEquals("Invalid colour descriptor: oops", e.getMessage());
279 * colour by label (no threshold)
281 fc = FeatureColour.parseJalviewFeatureColour("label");
282 assertTrue(fc.isColourByLabel());
283 assertFalse(fc.hasThreshold());
286 * colour by label (with threshold)
289 .parseJalviewFeatureColour("label|||0.0|0.0|above|12.0");
290 assertTrue(fc.isColourByLabel());
291 assertTrue(fc.isAboveThreshold());
292 assertEquals(12.0f, fc.getThreshold());
295 * graduated colour (by name) (no threshold)
297 fc = FeatureColour.parseJalviewFeatureColour("red|green|10.0|20.0");
298 assertTrue(fc.isGraduatedColour());
299 assertFalse(fc.hasThreshold());
300 assertEquals(Color.RED, fc.getMinColour());
301 assertEquals(Color.GREEN, fc.getMaxColour());
302 assertEquals(10f, fc.getMin());
303 assertEquals(20f, fc.getMax());
304 assertTrue(fc.isAutoScaled());
307 * graduated colour (by hex code) (above threshold)
309 String descriptor = String.format("%s|%s|10.0|20.0|above|15",
310 Format.getHexString(Color.RED),
311 Format.getHexString(Color.GREEN));
312 fc = FeatureColour.parseJalviewFeatureColour(descriptor);
313 assertTrue(fc.isGraduatedColour());
314 assertTrue(fc.hasThreshold());
315 assertTrue(fc.isAboveThreshold());
316 assertEquals(15f, fc.getThreshold());
317 assertEquals(Color.RED, fc.getMinColour());
318 assertEquals(Color.GREEN, fc.getMaxColour());
319 assertEquals(10f, fc.getMin());
320 assertEquals(20f, fc.getMax());
321 assertTrue(fc.isAutoScaled());
324 * graduated colour (by RGB triplet) (below threshold), absolute scale
326 descriptor = String.format("255,0,0|0,255,0|abso|10.0|20.0|below|15");
327 fc = FeatureColour.parseJalviewFeatureColour(descriptor);
328 assertTrue(fc.isGraduatedColour());
329 assertFalse(fc.isAutoScaled());
330 assertTrue(fc.hasThreshold());
331 assertTrue(fc.isBelowThreshold());
332 assertEquals(15f, fc.getThreshold());
333 assertEquals(Color.RED, fc.getMinColour());
334 assertEquals(Color.GREEN, fc.getMaxColour());
335 assertEquals(10f, fc.getMin());
336 assertEquals(20f, fc.getMax());
339 .format("blue|255,0,255|absolute|20.0|95.0|below|66.0");
340 fc = FeatureColour.parseJalviewFeatureColour(descriptor);
341 assertTrue(fc.isGraduatedColour());