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.assertTrue;
26 import static org.testng.AssertJUnit.fail;
28 import jalview.datamodel.SequenceFeature;
29 import jalview.gui.JvOptionPane;
30 import jalview.util.ColorUtils;
31 import jalview.util.Format;
33 import java.awt.Color;
35 import org.testng.annotations.BeforeClass;
36 import org.testng.annotations.Test;
38 public class FeatureColourTest
41 @BeforeClass(alwaysRun = true)
42 public void setUpJvOptionPane()
44 JvOptionPane.setInteractiveMode(false);
45 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
48 @Test(groups = { "Functional" })
49 public void testCopyConstructor()
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());
63 fc = new FeatureColour(Color.gray, Color.black, 10f, 20f);
64 fc.setAboveThreshold(true);
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());
79 fc = new FeatureColour();
80 fc.setColourByLabel(true);
81 fc1 = new FeatureColour(fc);
82 assertTrue(fc1.isColourByLabel());
83 assertFalse(fc1.isGraduatedColour());
86 @Test(groups = { "Functional" })
87 public void testIsColored_simpleColour()
89 FeatureColour fc = new FeatureColour(Color.RED);
91 .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
94 @Test(groups = { "Functional" })
95 public void testIsColored_colourByLabel()
97 FeatureColour fc = new FeatureColour();
98 fc.setColourByLabel(true);
100 .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
103 @Test(groups = { "Functional" })
104 public void testIsColored_aboveThreshold()
106 // graduated colour range from score 20 to 100
107 FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f,
110 // score 0 is adjusted to bottom of range
111 SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f,
113 assertTrue(fc.isColored(sf));
114 assertEquals(Color.WHITE, fc.getColor(sf));
116 // score 120 is adjusted to top of range
117 sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
118 sf.getFeatureGroup(), 120f);
119 assertEquals(Color.BLACK, fc.getColor(sf));
121 // value below threshold is still rendered
122 // setting threshold has no effect yet...
123 fc.setThreshold(60f);
124 sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
125 sf.getFeatureGroup(), 36f);
126 assertTrue(fc.isColored(sf));
127 assertEquals(new Color(204, 204, 204), fc.getColor(sf));
129 // now apply threshold:
130 fc.setAboveThreshold(true);
131 assertFalse(fc.isColored(sf));
132 // colour is still returned though ?!?
133 assertEquals(new Color(204, 204, 204), fc.getColor(sf));
135 sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
136 sf.getFeatureGroup(), 84f);
137 // above threshold now
138 assertTrue(fc.isColored(sf));
139 assertEquals(new Color(51, 51, 51), fc.getColor(sf));
142 @Test(groups = { "Functional" })
143 public void testGetColor_simpleColour()
145 FeatureColour fc = new FeatureColour(Color.RED);
146 assertEquals(Color.RED,
147 fc.getColor(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
150 @Test(groups = { "Functional" })
151 public void testGetColor_colourByLabel()
153 FeatureColour fc = new FeatureColour();
154 fc.setColourByLabel(true);
155 SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 1f,
157 Color expected = ColorUtils.createColourFromName("desc");
158 assertEquals(expected, fc.getColor(sf));
161 @Test(groups = { "Functional" })
162 public void testGetColor_Graduated()
164 // graduated colour from score 0 to 100, gray(128, 128, 128) to red(255, 0,
166 FeatureColour fc = new FeatureColour(Color.GRAY, Color.RED, 0f, 100f);
167 // feature score is 75 which is 3/4 of the way from GRAY to RED
168 SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 75f,
170 // the colour gradient is computed in float values from 0-1 (where 1 == 255)
171 float red = 128 / 255f + 3 / 4f * (255 - 128) / 255f;
172 float green = 128 / 255f + 3 / 4f * (0 - 128) / 255f;
173 float blue = 128 / 255f + 3 / 4f * (0 - 128) / 255f;
174 Color expected = new Color(red, green, blue);
175 assertEquals(expected, fc.getColor(sf));
178 @Test(groups = { "Functional" })
179 public void testGetColor_belowThreshold()
181 // gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0)
182 FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f,
184 SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f,
186 fc.setThreshold(100f); // ignore for now
187 assertTrue(fc.isColored(sf));
188 assertEquals(new Color(204, 204, 204), fc.getColor(sf));
190 fc.setAboveThreshold(true); // feature lies below threshold
191 assertFalse(fc.isColored(sf));
192 assertEquals(new Color(204, 204, 204), fc.getColor(sf));
196 * Test output of feature colours to Jalview features file format
198 @Test(groups = { "Functional" })
199 public void testToJalviewFormat()
202 * plain colour - to RGB hex code
204 FeatureColour fc = new FeatureColour(Color.RED);
205 String redHex = Format.getHexString(Color.RED);
206 String hexColour = redHex;
207 assertEquals("domain\t" + hexColour, fc.toJalviewFormat("domain"));
210 * colour by label (no threshold)
212 fc = new FeatureColour();
213 fc.setColourByLabel(true);
214 assertEquals("domain\tlabel", fc.toJalviewFormat("domain"));
217 * colour by label (autoscaled) (an odd state you can reach by selecting
218 * 'above threshold', then deselecting 'threshold is min/max' then 'colour
221 fc.setAutoScaled(true);
222 assertEquals("domain\tlabel", fc.toJalviewFormat("domain"));
225 * colour by label (above threshold) (min/max values are output though not
226 * used by this scheme)
228 fc.setAutoScaled(false);
229 fc.setThreshold(12.5f);
230 fc.setAboveThreshold(true);
231 assertEquals("domain\tlabel|||0.0|0.0|above|12.5",
232 fc.toJalviewFormat("domain"));
235 * colour by label (below threshold)
237 fc.setBelowThreshold(true);
238 assertEquals("domain\tlabel|||0.0|0.0|below|12.5",
239 fc.toJalviewFormat("domain"));
242 * graduated colour, no threshold
244 fc = new FeatureColour(Color.GREEN, Color.RED, 12f, 25f);
245 String greenHex = Format.getHexString(Color.GREEN);
246 String expected = String.format("domain\t%s|%s|abso|12.0|25.0|none",
248 assertEquals(expected, fc.toJalviewFormat("domain"));
251 * colour ranges over the actual score ranges (not min/max)
253 fc.setAutoScaled(true);
254 expected = String.format("domain\t%s|%s|12.0|25.0|none", greenHex,
256 assertEquals(expected, fc.toJalviewFormat("domain"));
259 * graduated colour below threshold
261 fc.setThreshold(12.5f);
262 fc.setBelowThreshold(true);
263 expected = String.format("domain\t%s|%s|12.0|25.0|below|12.5",
265 assertEquals(expected, fc.toJalviewFormat("domain"));
268 * graduated colour above threshold
270 fc.setThreshold(12.5f);
271 fc.setAboveThreshold(true);
272 fc.setAutoScaled(false);
273 expected = String.format("domain\t%s|%s|abso|12.0|25.0|above|12.5",
275 assertEquals(expected, fc.toJalviewFormat("domain"));
279 * Test parsing of feature colours from Jalview features file format
281 @Test(groups = { "Functional" })
282 public void testParseJalviewFeatureColour()
285 * simple colour by name
287 FeatureColour fc = FeatureColour.parseJalviewFeatureColour("red");
288 assertTrue(fc.isSimpleColour());
289 assertEquals(Color.RED, fc.getColour());
292 * simple colour by hex code
294 fc = FeatureColour.parseJalviewFeatureColour(Format
295 .getHexString(Color.RED));
296 assertTrue(fc.isSimpleColour());
297 assertEquals(Color.RED, fc.getColour());
300 * simple colour by rgb triplet
302 fc = FeatureColour.parseJalviewFeatureColour("255,0,0");
303 assertTrue(fc.isSimpleColour());
304 assertEquals(Color.RED, fc.getColour());
311 fc = FeatureColour.parseJalviewFeatureColour("oops");
312 fail("expected exception");
313 } catch (IllegalArgumentException e)
315 assertEquals("Invalid colour descriptor: oops", e.getMessage());
319 * colour by label (no threshold)
321 fc = FeatureColour.parseJalviewFeatureColour("label");
322 assertTrue(fc.isColourByLabel());
323 assertFalse(fc.hasThreshold());
326 * colour by label (with threshold)
329 .parseJalviewFeatureColour("label|||0.0|0.0|above|12.0");
330 assertTrue(fc.isColourByLabel());
331 assertTrue(fc.isAboveThreshold());
332 assertEquals(12.0f, fc.getThreshold());
335 * graduated colour (by name) (no threshold)
337 fc = FeatureColour.parseJalviewFeatureColour("red|green|10.0|20.0");
338 assertTrue(fc.isGraduatedColour());
339 assertFalse(fc.hasThreshold());
340 assertEquals(Color.RED, fc.getMinColour());
341 assertEquals(Color.GREEN, fc.getMaxColour());
342 assertEquals(10f, fc.getMin());
343 assertEquals(20f, fc.getMax());
344 assertTrue(fc.isAutoScaled());
347 * graduated colour (by hex code) (above threshold)
349 String descriptor = String.format("%s|%s|10.0|20.0|above|15",
350 Format.getHexString(Color.RED),
351 Format.getHexString(Color.GREEN));
352 fc = FeatureColour.parseJalviewFeatureColour(descriptor);
353 assertTrue(fc.isGraduatedColour());
354 assertTrue(fc.hasThreshold());
355 assertTrue(fc.isAboveThreshold());
356 assertEquals(15f, fc.getThreshold());
357 assertEquals(Color.RED, fc.getMinColour());
358 assertEquals(Color.GREEN, fc.getMaxColour());
359 assertEquals(10f, fc.getMin());
360 assertEquals(20f, fc.getMax());
361 assertTrue(fc.isAutoScaled());
364 * graduated colour (by RGB triplet) (below threshold), absolute scale
366 descriptor = String.format("255,0,0|0,255,0|abso|10.0|20.0|below|15");
367 fc = FeatureColour.parseJalviewFeatureColour(descriptor);
368 assertTrue(fc.isGraduatedColour());
369 assertFalse(fc.isAutoScaled());
370 assertTrue(fc.hasThreshold());
371 assertTrue(fc.isBelowThreshold());
372 assertEquals(15f, fc.getThreshold());
373 assertEquals(Color.RED, fc.getMinColour());
374 assertEquals(Color.GREEN, fc.getMaxColour());
375 assertEquals(10f, fc.getMin());
376 assertEquals(20f, fc.getMax());
379 .format("blue|255,0,255|absolute|20.0|95.0|below|66.0");
380 fc = FeatureColour.parseJalviewFeatureColour(descriptor);
381 assertTrue(fc.isGraduatedColour());