X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=test%2Fjalview%2Frenderer%2Fseqfeatures%2FFeatureColourFinderTest.java;fp=test%2Fjalview%2Frenderer%2Fseqfeatures%2FFeatureColourFinderTest.java;h=59566edf45215b76f47b97d06df28e6e74a099e0;hb=d5bcc3830eab04e6db816e1c2ad8fce1dc189612;hp=0000000000000000000000000000000000000000;hpb=3ebdd4e28382e38a181aae1eed71549f603f9025;p=jalview.git diff --git a/test/jalview/renderer/seqfeatures/FeatureColourFinderTest.java b/test/jalview/renderer/seqfeatures/FeatureColourFinderTest.java new file mode 100644 index 0000000..59566ed --- /dev/null +++ b/test/jalview/renderer/seqfeatures/FeatureColourFinderTest.java @@ -0,0 +1,448 @@ +package jalview.renderer.seqfeatures; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import jalview.api.FeatureColourI; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.gui.AlignFrame; +import jalview.gui.AlignViewport; +import jalview.gui.FeatureRenderer; +import jalview.io.DataSourceType; +import jalview.io.FileLoader; +import jalview.schemes.FeatureColour; + +import java.awt.Color; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +/** + * Unit tests for feature colour determination, including but not limited to + * + */ +public class FeatureColourFinderTest +{ + private AlignViewport av; + + private SequenceI seq; + + private FeatureColourFinder finder; + + private AlignFrame af; + + private FeatureRenderer fr; + + @BeforeTest(alwaysRun = true) + public void setUp() + { + // aligned column 8 is sequence position 6 + String s = ">s1\nABCDE---FGHIJKLMNOPQRSTUVWXYZ\n"; + af = new FileLoader().LoadFileWaitTillLoaded(s, + DataSourceType.PASTE); + av = af.getViewport(); + seq = av.getAlignment().getSequenceAt(0); + fr = af.getFeatureRenderer(); + finder = new FeatureColourFinder(fr); + } + + /** + * Clear down any sequence features before each test (not as easy as it + * sounds...) + */ + @BeforeMethod(alwaysRun = true) + public void setUpBeforeTest() + { + SequenceFeature[] sfs = seq.getSequenceFeatures(); + if (sfs != null) + { + for (SequenceFeature sf : sfs) + { + seq.deleteFeature(sf); + } + } + fr.findAllFeatures(true); + + /* + * reset all feature groups to visible + */ + for (String group : fr.getGroups(false)) + { + fr.setGroupVisibility(group, true); + } + + fr.clearRenderOrder(); + av.setShowSequenceFeatures(true); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_noFeatures() + { + av.setShowSequenceFeatures(false); + Color c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.blue); + + av.setShowSequenceFeatures(true); + c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.blue); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_noFeaturesShown() + { + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, + Float.NaN, "MetalGroup")); + fr.featuresAdded(); + av.setShowSequenceFeatures(false); + Color c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.blue); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_singleFeatureAtPosition() + { + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, + Float.NaN, "MetalGroup")); + fr.setColour("Metal", new FeatureColour(Color.red)); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + Color c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.red); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_gapPosition() + { + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, 0f, + null)); + fr.setColour("Metal", new FeatureColour(Color.red)); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + Color c = finder.findFeatureColour(null, seq, 6); + assertEquals(c, Color.white); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_multipleFeaturesAtPositionNoTransparency() + { + /* + * featuresAdded -> FeatureRendererModel.updateRenderOrder which adds any + * new features 'on top' (but reverses the order of any added features) + */ + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, + Float.NaN, "MetalGroup")); + FeatureColour red = new FeatureColour(Color.red); + fr.setColour("Metal", red); + fr.featuresAdded(); + seq.addSequenceFeature(new SequenceFeature("Domain", "Domain", 4, 15, + Float.NaN, "DomainGroup")); + FeatureColour green = new FeatureColour(Color.green); + fr.setColour("Domain", green); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + + /* + * expect Domain (green) to be rendered above Metal (red) + */ + Color c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.green); + + /* + * now promote Metal above Domain + * - currently no way other than mimicking reordering of + * table in Feature Settings + */ + Object[][] data = new Object[2][]; + data[0] = new Object[] { "Metal", red, true }; + data[1] = new Object[] { "Domain", green, true }; + fr.setFeaturePriority(data); + c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.red); + + /* + * ..and turn off display of Metal + */ + data[0][2] = false; + fr.setFeaturePriority(data); + c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.green); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_singleFeatureNotAtPosition() + { + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 8, 12, + Float.NaN, "MetalGroup")); + fr.setColour("Metal", new FeatureColour(Color.red)); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + // column 2 = sequence position 3 + Color c = finder.findFeatureColour(Color.blue, seq, 2); + assertEquals(c, Color.blue); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_featureTypeNotDisplayed() + { + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, + Float.NaN, "MetalGroup")); + FeatureColour red = new FeatureColour(Color.red); + fr.setColour("Metal", red); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + Color c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.red); + + /* + * turn off display of Metal - is this the easiest way to do it?? + */ + Object[][] data = new Object[1][]; + data[0] = new Object[] { "Metal", red, false }; + fr.setFeaturePriority(data); + c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.blue); + + /* + * turn display of Metal back on + */ + data[0] = new Object[] { "Metal", red, true }; + fr.setFeaturePriority(data); + c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.red); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_featureGroupNotDisplayed() + { + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, + Float.NaN, "MetalGroup")); + FeatureColour red = new FeatureColour(Color.red); + fr.setColour("Metal", red); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + Color c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.red); + + /* + * turn off display of MetalGroup + */ + fr.setGroupVisibility("MetalGroup", false); + c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.blue); + + /* + * turn display of MetalGroup back on + */ + fr.setGroupVisibility("MetalGroup", true); + c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.red); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_contactFeature() + { + /* + * currently contact feature == type "Disulphide Bond" or "Disulfide Bond" !! + */ + seq.addSequenceFeature(new SequenceFeature("Disulphide Bond", + "Contact", 2, 12, Float.NaN, "Disulphide")); + fr.setColour("Disulphide Bond", new FeatureColour(Color.red)); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + + /* + * Contact positions are residues 2 and 12 + * which are columns 1 and 14 + * positions in between don't count for a contact feature! + */ + Color c = finder.findFeatureColour(Color.blue, seq, 10); + assertEquals(c, Color.blue); + c = finder.findFeatureColour(Color.blue, seq, 8); + assertEquals(c, Color.blue); + c = finder.findFeatureColour(Color.blue, seq, 1); + assertEquals(c, Color.red); + c = finder.findFeatureColour(Color.blue, seq, 14); + assertEquals(c, Color.red); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_graduatedFeatureColour() + { + seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2, + 2, 0f, "KdGroup")); + seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4, + 4, 5f, "KdGroup")); + seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7, + 7, 10f, "KdGroup")); + + /* + * graduated colour from 0 to 10 + */ + Color min = new Color(100, 50, 150); + Color max = new Color(200, 0, 100); + FeatureColourI fc = new FeatureColour(min, max, 0, 10); + fr.setColour("kd", fc); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + + /* + * position 2, column 1, score 0 - minimum colour in range + */ + Color c = finder.findFeatureColour(Color.blue, seq, 1); + assertEquals(c, min); + + /* + * position 7, column 9, score 10 - maximum colour in range + */ + c = finder.findFeatureColour(Color.blue, seq, 9); + assertEquals(c, max); + + /* + * position 4, column 3, score 5 - half way from min to max + */ + c = finder.findFeatureColour(Color.blue, seq, 3); + assertEquals(c, new Color(150, 25, 125)); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_transparencySingleFeature() + { + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, + Float.NaN, "MetalGroup")); + FeatureColour red = new FeatureColour(Color.red); + fr.setColour("Metal", red); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + + /* + * the FeatureSettings transparency slider has range 0-70 which + * corresponds to a transparency value of 1 - 0.3 + * A value of 0.4 gives a combination of + * 0.4 * red(255, 0, 0) + 0.6 * cyan(0, 255, 255) = (102, 153, 153) + */ + fr.setTransparency(0.4f); + Color c = finder.findFeatureColour(Color.cyan, seq, 10); + assertEquals(c, new Color(102, 153, 153)); + } + + @Test(groups = "Functional") + public void testFindFeatureColour_transparencyTwoFeatures() + { + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, + Float.NaN, "MetalGroup")); + FeatureColour red = new FeatureColour(Color.red); + fr.setColour("Metal", red); + fr.featuresAdded(); + seq.addSequenceFeature(new SequenceFeature("Domain", "Domain", 4, 15, + Float.NaN, "DomainGroup")); + FeatureColour green = new FeatureColour(Color.green); + fr.setColour("Domain", green); + fr.featuresAdded(); + av.setShowSequenceFeatures(true); + + /* + * Domain (green) rendered above Metal (red) above background (cyan) + * 1) 0.6 * red(255, 0, 0) + 0.4 * cyan(0, 255, 255) = (153, 102, 102) + * 2) 0.6* green(0, 255, 0) + 0.4 * (153, 102, 102) = (61, 194, 41) rounded + */ + fr.setTransparency(0.6f); + Color c = finder.findFeatureColour(Color.cyan, seq, 10); + assertEquals(c, new Color(61, 194, 41)); + + /* + * now promote Metal above Domain + * - currently no way other than mimicking reordering of + * table in Feature Settings + * Metal (red) rendered above Domain (green) above background (cyan) + * 1) 0.6 * green(0, 255, 0) + 0.4 * cyan(0, 255, 255) = (0, 255, 102) + * 2) 0.6* red(255, 0, 0) + 0.4 * (0, 255, 102) = (153, 102, 41) rounded + */ + Object[][] data = new Object[2][]; + data[0] = new Object[] { "Metal", red, true }; + data[1] = new Object[] { "Domain", green, true }; + fr.setFeaturePriority(data); + c = finder.findFeatureColour(Color.cyan, seq, 10); + assertEquals(c, new Color(153, 102, 41)); + + /* + * ..and turn off display of Metal + * Domain (green) above background (pink) + * 0.6 * green(0, 255, 0) + 0.4 * pink(255, 175, 175) = (102, 223, 70) + */ + data[0][2] = false; + fr.setFeaturePriority(data); + c = finder.findFeatureColour(Color.pink, seq, 10); + assertEquals(c, new Color(102, 223, 70)); + } + + @Test(groups = "Functional") + public void testNoFeaturesDisplayed() + { + /* + * no features on alignment to render + */ + assertTrue(finder.noFeaturesDisplayed()); + + /* + * add a feature + * it will be automatically set visible but we leave + * the viewport configured not to show features + */ + av.setShowSequenceFeatures(false); + seq.addSequenceFeature(new SequenceFeature("Metal", "Metal", 2, 12, + Float.NaN, "MetalGroup")); + FeatureColour red = new FeatureColour(Color.red); + fr.setColour("Metal", red); + fr.featuresAdded(); + assertTrue(finder.noFeaturesDisplayed()); + + /* + * turn on feature display + */ + av.setShowSequenceFeatures(true); + assertFalse(finder.noFeaturesDisplayed()); + + /* + * turn off display of Metal + */ + Object[][] data = new Object[1][]; + data[0] = new Object[] { "Metal", red, false }; + fr.setFeaturePriority(data); + assertTrue(finder.noFeaturesDisplayed()); + + /* + * turn display of Metal back on + */ + fr.setVisible("Metal"); + assertFalse(finder.noFeaturesDisplayed()); + + /* + * turn off MetalGroup - has no effect here since the group of a + * sequence feature instance is independent of its type + */ + fr.setGroupVisibility("MetalGroup", false); + assertFalse(finder.noFeaturesDisplayed()); + + /* + * a finder with no feature renderer + */ + FeatureColourFinder finder2 = new FeatureColourFinder(null); + assertTrue(finder2.noFeaturesDisplayed()); + } +}