/* * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.schemes; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.fail; import jalview.datamodel.SequenceFeature; import jalview.gui.JvOptionPane; import jalview.util.ColorUtils; import jalview.util.Format; import java.awt.Color; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FeatureColourTest { @BeforeClass(alwaysRun = true) public void setUpJvOptionPane() { JvOptionPane.setInteractiveMode(false); JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); } @Test(groups = { "Functional" }) public void testCopyConstructor() { /* * plain colour */ FeatureColour fc = new FeatureColour(Color.RED); FeatureColour fc1 = new FeatureColour(fc); assertTrue(fc1.getColour().equals(Color.RED)); assertFalse(fc1.isGraduatedColour()); assertFalse(fc1.isColourByLabel()); /* * min-max colour */ fc = new FeatureColour(Color.gray, Color.black, 10f, 20f); fc.setAboveThreshold(true); fc.setThreshold(12f); fc1 = new FeatureColour(fc); assertTrue(fc1.isGraduatedColour()); assertFalse(fc1.isColourByLabel()); assertTrue(fc1.isAboveThreshold()); assertEquals(12f, fc1.getThreshold()); assertEquals(Color.gray, fc1.getMinColour()); assertEquals(Color.black, fc1.getMaxColour()); assertEquals(10f, fc1.getMin()); assertEquals(20f, fc1.getMax()); /* * colour by label */ fc = new FeatureColour(); fc.setColourByLabel(true); fc1 = new FeatureColour(fc); assertTrue(fc1.isColourByLabel()); assertFalse(fc1.isGraduatedColour()); } @Test(groups = { "Functional" }) public void testIsColored_simpleColour() { FeatureColour fc = new FeatureColour(Color.RED); assertTrue(fc .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null))); } @Test(groups = { "Functional" }) public void testIsColored_colourByLabel() { FeatureColour fc = new FeatureColour(); fc.setColourByLabel(true); assertTrue(fc .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null))); } @Test(groups = { "Functional" }) public void testIsColored_aboveThreshold() { // graduated colour range from score 20 to 100 FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f, 100f); // score 0 is adjusted to bottom of range SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f, null); assertTrue(fc.isColored(sf)); assertEquals(Color.WHITE, fc.getColor(sf)); // score 120 is adjusted to top of range sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(), sf.getFeatureGroup(), 120f); assertEquals(Color.BLACK, fc.getColor(sf)); // value below threshold is still rendered // setting threshold has no effect yet... fc.setThreshold(60f); sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(), sf.getFeatureGroup(), 36f); assertTrue(fc.isColored(sf)); assertEquals(new Color(204, 204, 204), fc.getColor(sf)); // now apply threshold: fc.setAboveThreshold(true); assertFalse(fc.isColored(sf)); // colour is still returned though ?!? assertEquals(new Color(204, 204, 204), fc.getColor(sf)); sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(), sf.getFeatureGroup(), 84f); // above threshold now assertTrue(fc.isColored(sf)); assertEquals(new Color(51, 51, 51), fc.getColor(sf)); } @Test(groups = { "Functional" }) public void testGetColor_simpleColour() { FeatureColour fc = new FeatureColour(Color.RED); assertEquals(Color.RED, fc.getColor(new SequenceFeature("Cath", "", 1, 2, 0f, null))); } @Test(groups = { "Functional" }) public void testGetColor_colourByLabel() { FeatureColour fc = new FeatureColour(); fc.setColourByLabel(true); SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 1f, null); Color expected = ColorUtils.createColourFromName("desc"); assertEquals(expected, fc.getColor(sf)); } @Test(groups = { "Functional" }) public void testGetColor_Graduated() { // graduated colour from score 0 to 100, gray(128, 128, 128) to red(255, 0, // 0) FeatureColour fc = new FeatureColour(Color.GRAY, Color.RED, 0f, 100f); // feature score is 75 which is 3/4 of the way from GRAY to RED SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 75f, null); // the colour gradient is computed in float values from 0-1 (where 1 == 255) float red = 128 / 255f + 3 / 4f * (255 - 128) / 255f; float green = 128 / 255f + 3 / 4f * (0 - 128) / 255f; float blue = 128 / 255f + 3 / 4f * (0 - 128) / 255f; Color expected = new Color(red, green, blue); assertEquals(expected, fc.getColor(sf)); } @Test(groups = { "Functional" }) public void testGetColor_belowThreshold() { // gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0) FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f, 150f); SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f, null); fc.setThreshold(100f); // ignore for now assertTrue(fc.isColored(sf)); assertEquals(new Color(204, 204, 204), fc.getColor(sf)); fc.setAboveThreshold(true); // feature lies below threshold assertFalse(fc.isColored(sf)); assertEquals(new Color(204, 204, 204), fc.getColor(sf)); } /** * Test output of feature colours to Jalview features file format */ @Test(groups = { "Functional" }) public void testToJalviewFormat() { /* * plain colour - to RGB hex code */ FeatureColour fc = new FeatureColour(Color.RED); String redHex = Format.getHexString(Color.RED); String hexColour = redHex; assertEquals("domain\t" + hexColour, fc.toJalviewFormat("domain")); /* * colour by label (no threshold) */ fc = new FeatureColour(); fc.setColourByLabel(true); assertEquals("domain\tlabel", fc.toJalviewFormat("domain")); /* * colour by label (autoscaled) (an odd state you can reach by selecting * 'above threshold', then deselecting 'threshold is min/max' then 'colour * by label') */ fc.setAutoScaled(true); assertEquals("domain\tlabel", fc.toJalviewFormat("domain")); /* * colour by label (above threshold) (min/max values are output though not * used by this scheme) */ fc.setAutoScaled(false); fc.setThreshold(12.5f); fc.setAboveThreshold(true); assertEquals("domain\tlabel|||0.0|0.0|above|12.5", fc.toJalviewFormat("domain")); /* * colour by label (below threshold) */ fc.setBelowThreshold(true); assertEquals("domain\tlabel|||0.0|0.0|below|12.5", fc.toJalviewFormat("domain")); /* * graduated colour, no threshold */ fc = new FeatureColour(Color.GREEN, Color.RED, 12f, 25f); String greenHex = Format.getHexString(Color.GREEN); String expected = String.format("domain\t%s|%s|abso|12.0|25.0|none", greenHex, redHex); assertEquals(expected, fc.toJalviewFormat("domain")); /* * colour ranges over the actual score ranges (not min/max) */ fc.setAutoScaled(true); expected = String.format("domain\t%s|%s|12.0|25.0|none", greenHex, redHex); assertEquals(expected, fc.toJalviewFormat("domain")); /* * graduated colour below threshold */ fc.setThreshold(12.5f); fc.setBelowThreshold(true); expected = String.format("domain\t%s|%s|12.0|25.0|below|12.5", greenHex, redHex); assertEquals(expected, fc.toJalviewFormat("domain")); /* * graduated colour above threshold */ fc.setThreshold(12.5f); fc.setAboveThreshold(true); fc.setAutoScaled(false); expected = String.format("domain\t%s|%s|abso|12.0|25.0|above|12.5", greenHex, redHex); assertEquals(expected, fc.toJalviewFormat("domain")); } /** * Test parsing of feature colours from Jalview features file format */ @Test(groups = { "Functional" }) public void testParseJalviewFeatureColour() { /* * simple colour by name */ FeatureColour fc = FeatureColour.parseJalviewFeatureColour("red"); assertTrue(fc.isSimpleColour()); assertEquals(Color.RED, fc.getColour()); /* * simple colour by hex code */ fc = FeatureColour.parseJalviewFeatureColour(Format .getHexString(Color.RED)); assertTrue(fc.isSimpleColour()); assertEquals(Color.RED, fc.getColour()); /* * simple colour by rgb triplet */ fc = FeatureColour.parseJalviewFeatureColour("255,0,0"); assertTrue(fc.isSimpleColour()); assertEquals(Color.RED, fc.getColour()); /* * malformed colour */ try { fc = FeatureColour.parseJalviewFeatureColour("oops"); fail("expected exception"); } catch (IllegalArgumentException e) { assertEquals("Invalid colour descriptor: oops", e.getMessage()); } /* * colour by label (no threshold) */ fc = FeatureColour.parseJalviewFeatureColour("label"); assertTrue(fc.isColourByLabel()); assertFalse(fc.hasThreshold()); /* * colour by label (with threshold) */ fc = FeatureColour .parseJalviewFeatureColour("label|||0.0|0.0|above|12.0"); assertTrue(fc.isColourByLabel()); assertTrue(fc.isAboveThreshold()); assertEquals(12.0f, fc.getThreshold()); /* * graduated colour (by name) (no threshold) */ fc = FeatureColour.parseJalviewFeatureColour("red|green|10.0|20.0"); assertTrue(fc.isGraduatedColour()); assertFalse(fc.hasThreshold()); assertEquals(Color.RED, fc.getMinColour()); assertEquals(Color.GREEN, fc.getMaxColour()); assertEquals(10f, fc.getMin()); assertEquals(20f, fc.getMax()); assertTrue(fc.isAutoScaled()); /* * graduated colour (by hex code) (above threshold) */ String descriptor = String.format("%s|%s|10.0|20.0|above|15", Format.getHexString(Color.RED), Format.getHexString(Color.GREEN)); fc = FeatureColour.parseJalviewFeatureColour(descriptor); assertTrue(fc.isGraduatedColour()); assertTrue(fc.hasThreshold()); assertTrue(fc.isAboveThreshold()); assertEquals(15f, fc.getThreshold()); assertEquals(Color.RED, fc.getMinColour()); assertEquals(Color.GREEN, fc.getMaxColour()); assertEquals(10f, fc.getMin()); assertEquals(20f, fc.getMax()); assertTrue(fc.isAutoScaled()); /* * graduated colour (by RGB triplet) (below threshold), absolute scale */ descriptor = String.format("255,0,0|0,255,0|abso|10.0|20.0|below|15"); fc = FeatureColour.parseJalviewFeatureColour(descriptor); assertTrue(fc.isGraduatedColour()); assertFalse(fc.isAutoScaled()); assertTrue(fc.hasThreshold()); assertTrue(fc.isBelowThreshold()); assertEquals(15f, fc.getThreshold()); assertEquals(Color.RED, fc.getMinColour()); assertEquals(Color.GREEN, fc.getMaxColour()); assertEquals(10f, fc.getMin()); assertEquals(20f, fc.getMax()); descriptor = String .format("blue|255,0,255|absolute|20.0|95.0|below|66.0"); fc = FeatureColour.parseJalviewFeatureColour(descriptor); assertTrue(fc.isGraduatedColour()); } }