X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=test%2Fjalview%2Frenderer%2Fseqfeatures%2FFeatureRendererTest.java;h=da7cadabdc2ed49198b74ae9fd81134ba6c07915;hb=77b160b053c41a5d5c95bf1bbc0fbd066435f70d;hp=3d4809742544ec27d322a05091d822ff24a0633e;hpb=b7cb4c78d9d787e918c9d88f917a41642dd90a7a;p=jalview.git diff --git a/test/jalview/renderer/seqfeatures/FeatureRendererTest.java b/test/jalview/renderer/seqfeatures/FeatureRendererTest.java index 3d48097..da7cada 100644 --- a/test/jalview/renderer/seqfeatures/FeatureRendererTest.java +++ b/test/jalview/renderer/seqfeatures/FeatureRendererTest.java @@ -2,20 +2,27 @@ package jalview.renderer.seqfeatures; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import jalview.api.AlignViewportI; import jalview.api.FeatureColourI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.datamodel.features.FeatureMatcher; +import jalview.datamodel.features.FeatureMatcherSet; +import jalview.datamodel.features.FeatureMatcherSetI; import jalview.gui.AlignFrame; import jalview.io.DataSourceType; import jalview.io.FileLoader; import jalview.schemes.FeatureColour; +import jalview.util.matcher.Condition; +import jalview.viewmodel.seqfeatures.FeatureRendererModel.FeatureSettingsBean; import java.awt.Color; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -61,9 +68,8 @@ public class FeatureRendererTest seqs.get(2).addSequenceFeature( new SequenceFeature("Pfam", "Desc", 14, 22, 2f, "RfamGroup")); // bug in findAllFeatures - group not checked for a known feature type - seqs.get(2).addSequenceFeature( - new SequenceFeature("Rfam", "Desc", 5, 9, Float.NaN, - "RfamGroup")); + seqs.get(2).addSequenceFeature(new SequenceFeature("Rfam", "Desc", 5, 9, + Float.NaN, "RfamGroup")); // existing feature type with null group seqs.get(3).addSequenceFeature( new SequenceFeature("Rfam", "Desc", 5, 9, Float.NaN, null)); @@ -116,13 +122,14 @@ public class FeatureRendererTest * change render order (todo: an easier way) * nb here last comes first in the data array */ - Object[][] data = new Object[3][]; + FeatureSettingsBean[] data = new FeatureSettingsBean[3]; FeatureColourI colour = new FeatureColour(Color.RED); - data[0] = new Object[] { "Rfam", colour, true }; - data[1] = new Object[] { "Pfam", colour, false }; - data[2] = new Object[] { "Scop", colour, false }; + data[0] = new FeatureSettingsBean("Rfam", colour, null, true); + data[1] = new FeatureSettingsBean("Pfam", colour, null, false); + data[2] = new FeatureSettingsBean("Scop", colour, null, false); fr.setFeaturePriority(data); - assertEquals(fr.getRenderOrder(), Arrays.asList("Scop", "Pfam", "Rfam")); + assertEquals(fr.getRenderOrder(), + Arrays.asList("Scop", "Pfam", "Rfam")); assertEquals(fr.getDisplayedFeatureTypes(), Arrays.asList("Rfam")); /* @@ -217,12 +224,13 @@ public class FeatureRendererTest /* * make "Type2" not displayed */ - Object[][] data = new Object[4][]; FeatureColourI colour = new FeatureColour(Color.RED); - data[0] = new Object[] { "Type1", colour, true }; - data[1] = new Object[] { "Type2", colour, false }; - data[2] = new Object[] { "Type3", colour, true }; - data[3] = new Object[] { "Disulphide Bond", colour, true }; + FeatureSettingsBean[] data = new FeatureSettingsBean[4]; + data[0] = new FeatureSettingsBean("Type1", colour, null, true); + data[1] = new FeatureSettingsBean("Type2", colour, null, false); + data[2] = new FeatureSettingsBean("Type3", colour, null, true); + data[3] = new FeatureSettingsBean("Disulphide Bond", colour, null, + true); fr.setFeaturePriority(data); features = fr.findFeaturesAtColumn(seq, 15); @@ -252,6 +260,37 @@ public class FeatureRendererTest features = fr.findFeaturesAtColumn(seq, 5); assertEquals(features.size(), 1); assertTrue(features.contains(sf8)); + + /* + * give "Type3" features a graduated colour scheme + * - first with no threshold + */ + FeatureColourI gc = new FeatureColour(Color.yellow, Color.red, null, 0f, + 10f); + fr.getFeatureColours().put("Type3", gc); + features = fr.findFeaturesAtColumn(seq, 8); + assertTrue(features.contains(sf4)); + // now with threshold > 2f - feature score of 1f is excluded + gc.setAboveThreshold(true); + gc.setThreshold(2f); + features = fr.findFeaturesAtColumn(seq, 8); + assertFalse(features.contains(sf4)); + + /* + * make "Type3" graduated colour by attribute "AF" + * - first with no attribute held - feature should be excluded + */ + gc.setAttributeName("AF"); + features = fr.findFeaturesAtColumn(seq, 8); + assertFalse(features.contains(sf4)); + // now with the attribute above threshold - should be included + sf4.setValue("AF", "2.4"); + features = fr.findFeaturesAtColumn(seq, 8); + assertTrue(features.contains(sf4)); + // now with the attribute below threshold - should be excluded + sf4.setValue("AF", "1.4"); + features = fr.findFeaturesAtColumn(seq, 8); + assertFalse(features.contains(sf4)); } @Test(groups = "Functional") @@ -264,7 +303,7 @@ public class FeatureRendererTest FeatureRenderer fr = new FeatureRenderer(av); List features = new ArrayList<>(); - fr.filterFeaturesForDisplay(features, null); // empty list, does nothing + fr.filterFeaturesForDisplay(features); // empty list, does nothing SequenceI seq = av.getAlignment().getSequenceAt(0); SequenceFeature sf1 = new SequenceFeature("Cath", "", 6, 8, Float.NaN, @@ -297,7 +336,7 @@ public class FeatureRendererTest * filter out duplicate (co-located) features * note: which gets removed is not guaranteed */ - fr.filterFeaturesForDisplay(features, new FeatureColour(Color.blue)); + fr.filterFeaturesForDisplay(features); assertEquals(features.size(), 3); assertTrue(features.contains(sf1) || features.contains(sf4)); assertFalse(features.contains(sf1) && features.contains(sf4)); @@ -306,64 +345,174 @@ public class FeatureRendererTest assertTrue(features.contains(sf5)); /* - * hide group 3 - sf3 is removed, sf2 is retained + * hide groups 2 and 3 makes no difference to this method */ + fr.setGroupVisibility("group2", false); fr.setGroupVisibility("group3", false); features = seq.getSequenceFeatures(); - fr.filterFeaturesForDisplay(features, new FeatureColour(Color.blue)); + fr.filterFeaturesForDisplay(features); assertEquals(features.size(), 3); assertTrue(features.contains(sf1) || features.contains(sf4)); assertFalse(features.contains(sf1) && features.contains(sf4)); - assertTrue(features.contains(sf2)); - assertFalse(features.contains(sf3)); + assertTrue(features.contains(sf2) || features.contains(sf3)); + assertFalse(features.contains(sf2) && features.contains(sf3)); assertTrue(features.contains(sf5)); /* - * hide group 2, show group 3 - sf2 is removed, sf3 is retained + * no filtering if transparency is applied */ - fr.setGroupVisibility("group2", false); - fr.setGroupVisibility("group3", true); + fr.setTransparency(0.5f); features = seq.getSequenceFeatures(); - fr.filterFeaturesForDisplay(features, null); - assertEquals(features.size(), 3); - assertTrue(features.contains(sf1) || features.contains(sf4)); - assertFalse(features.contains(sf1) && features.contains(sf4)); - assertFalse(features.contains(sf2)); - assertTrue(features.contains(sf3)); - assertTrue(features.contains(sf5)); + fr.filterFeaturesForDisplay(features); + assertEquals(features.size(), 5); + } + + @Test(groups = "Functional") + public void testGetColour() + { + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(">s1\nABCD\n", + DataSourceType.PASTE); + AlignViewportI av = af.getViewport(); + FeatureRenderer fr = new FeatureRenderer(av); /* - * no filtering of co-located features with graduated colour scheme - * filterFeaturesForDisplay does _not_ check colour threshold - * sf2 is removed as its group is hidden + * simple colour, feature type and group displayed */ - features = seq.getSequenceFeatures(); - fr.filterFeaturesForDisplay(features, new FeatureColour(Color.black, - Color.white, 0f, 1f)); - assertEquals(features.size(), 4); - assertFalse(features.contains(sf2)); + FeatureColourI fc = new FeatureColour(Color.red); + fr.getFeatureColours().put("Cath", fc); + SequenceFeature sf1 = new SequenceFeature("Cath", "", 6, 8, Float.NaN, + "group1"); + assertEquals(fr.getColour(sf1), Color.red); /* - * co-located features with colour by label - * should not get filtered + * hide feature type, then unhide + * - feature type visibility should not affect the result */ - features = seq.getSequenceFeatures(); - FeatureColour fc = new FeatureColour(Color.black); - fc.setColourByLabel(true); - fr.filterFeaturesForDisplay(features, fc); - assertEquals(features.size(), 4); - assertTrue(features.contains(sf1)); - assertTrue(features.contains(sf3)); - assertTrue(features.contains(sf4)); - assertTrue(features.contains(sf5)); + FeatureSettingsBean[] data = new FeatureSettingsBean[1]; + data[0] = new FeatureSettingsBean("Cath", fc, null, false); + fr.setFeaturePriority(data); + assertEquals(fr.getColour(sf1), Color.red); + data[0] = new FeatureSettingsBean("Cath", fc, null, true); + fr.setFeaturePriority(data); + assertEquals(fr.getColour(sf1), Color.red); /* - * no filtering if transparency is applied + * hide feature group, then unhide */ - fr.setTransparency(0.5f); - features = seq.getSequenceFeatures(); - fr.setGroupVisibility("group2", true); - fr.filterFeaturesForDisplay(features, new FeatureColour(Color.RED)); - assertEquals(features.size(), 5); + fr.setGroupVisibility("group1", false); + assertNull(fr.getColour(sf1)); + fr.setGroupVisibility("group1", true); + assertEquals(fr.getColour(sf1), Color.red); + + /* + * graduated colour by score, no threshold, no score + * + */ + FeatureColourI gc = new FeatureColour(Color.yellow, Color.red, + Color.green, 1f, 11f); + fr.getFeatureColours().put("Cath", gc); + assertEquals(fr.getColour(sf1), Color.green); + + /* + * graduated colour by score, no threshold, with score value + */ + SequenceFeature sf2 = new SequenceFeature("Cath", "", 6, 8, 6f, + "group1"); + // score 6 is half way from yellow(255, 255, 0) to red(255, 0, 0) + Color expected = new Color(255, 128, 0); + assertEquals(fr.getColour(sf2), expected); + + /* + * above threshold, score is above threshold - no change + */ + gc.setAboveThreshold(true); + gc.setThreshold(5f); + assertEquals(fr.getColour(sf2), expected); + + /* + * threshold is min-max; now score 6 is 1/6 of the way from 5 to 11 + * or from yellow(255, 255, 0) to red(255, 0, 0) + */ + gc = new FeatureColour(Color.yellow, Color.red, Color.green, 5f, 11f); + fr.getFeatureColours().put("Cath", gc); + gc.setAutoScaled(false); // this does little other than save a checkbox setting! + assertEquals(fr.getColour(sf2), new Color(255, 213, 0)); + + /* + * feature score is below threshold - no colour + */ + gc.setAboveThreshold(true); + gc.setThreshold(7f); + assertNull(fr.getColour(sf2)); + + /* + * feature score is above threshold - no colour + */ + gc.setBelowThreshold(true); + gc.setThreshold(3f); + assertNull(fr.getColour(sf2)); + + /* + * colour by feature attribute value + * first with no value held + */ + gc = new FeatureColour(Color.yellow, Color.red, Color.green, 1f, 11f); + fr.getFeatureColours().put("Cath", gc); + gc.setAttributeName("AF"); + assertEquals(fr.getColour(sf2), Color.green); + + // with non-numeric attribute value + sf2.setValue("AF", "Five"); + assertEquals(fr.getColour(sf2), Color.green); + + // with numeric attribute value + sf2.setValue("AF", "6"); + assertEquals(fr.getColour(sf2), expected); + + // with numeric value outwith threshold + gc.setAboveThreshold(true); + gc.setThreshold(10f); + assertNull(fr.getColour(sf2)); + + // with filter on AF < 4 + gc.setAboveThreshold(false); + assertEquals(fr.getColour(sf2), expected); + FeatureMatcherSetI filter = new FeatureMatcherSet(); + filter.and(FeatureMatcher.byAttribute(Condition.LT, "4.0", "AF")); + fr.setFeatureFilter("Cath", filter); + assertNull(fr.getColour(sf2)); + + // with filter on 'Consequence contains missense' + filter = new FeatureMatcherSet(); + filter.and(FeatureMatcher.byAttribute(Condition.Contains, "missense", + "Consequence")); + fr.setFeatureFilter("Cath", filter); + // if feature has no Consequence attribute, no colour + assertNull(fr.getColour(sf2)); + // if attribute does not match filter, no colour + sf2.setValue("Consequence", "Synonymous"); + assertNull(fr.getColour(sf2)); + // attribute matches filter + sf2.setValue("Consequence", "Missense variant"); + assertEquals(fr.getColour(sf2), expected); + + // with filter on CSQ:Feature contains "ENST01234" + filter = new FeatureMatcherSet(); + filter.and(FeatureMatcher.byAttribute(Condition.Matches, "ENST01234", + "CSQ", "Feature")); + fr.setFeatureFilter("Cath", filter); + // if feature has no CSQ data, no colour + assertNull(fr.getColour(sf2)); + // if CSQ data does not include Feature, no colour + Map csqData = new HashMap<>(); + csqData.put("BIOTYPE", "Transcript"); + sf2.setValue("CSQ", csqData); + assertNull(fr.getColour(sf2)); + // if attribute does not match filter, no colour + csqData.put("Feature", "ENST9876"); + assertNull(fr.getColour(sf2)); + // attribute matches filter + csqData.put("Feature", "ENST01234"); + assertEquals(fr.getColour(sf2), expected); } }