X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=test%2Fjalview%2Frenderer%2Fseqfeatures%2FFeatureRendererTest.java;h=53f98c354e622e669e21a655c22656838061d9a6;hb=8337a127bde90beb39c52fb971d0facf6f5b2362;hp=73ae9d7912169dfa9aacdbd2863924590a04f73a;hpb=1a34e43f7fb8e6d4f559026c6f0a207893124c6d;p=jalview.git diff --git a/test/jalview/renderer/seqfeatures/FeatureRendererTest.java b/test/jalview/renderer/seqfeatures/FeatureRendererTest.java index 73ae9d7..53f98c3 100644 --- a/test/jalview/renderer/seqfeatures/FeatureRendererTest.java +++ b/test/jalview/renderer/seqfeatures/FeatureRendererTest.java @@ -1,35 +1,69 @@ +/* + * 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.renderer.seqfeatures; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; +import java.awt.Color; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import jalview.analysis.GeneticCodes; import jalview.api.AlignViewportI; import jalview.api.FeatureColourI; +import jalview.bin.Jalview; +import jalview.datamodel.MappedFeatures; 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.gui.AlignViewport; +import jalview.gui.Desktop; import jalview.io.DataSourceType; import jalview.io.FileLoader; import jalview.schemes.FeatureColour; import jalview.util.matcher.Condition; -import jalview.util.matcher.KeyedMatcher; -import jalview.util.matcher.KeyedMatcherSet; -import jalview.util.matcher.KeyedMatcherSetI; 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; - -import org.testng.annotations.Test; - public class FeatureRendererTest { + @BeforeMethod(alwaysRun = true) + public void closeAll() + { + if (Desktop.instance != null) + Desktop.instance.closeAll_actionPerformed(null); + } @Test(groups = "Functional") public void testFindAllFeatures() @@ -68,9 +102,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)); @@ -129,7 +162,8 @@ public class FeatureRendererTest 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")); /* @@ -260,13 +294,13 @@ 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); + FeatureColourI gc = new FeatureColour(Color.green, Color.yellow, + Color.red, null, 0f, 10f); fr.getFeatureColours().put("Type3", gc); features = fr.findFeaturesAtColumn(seq, 8); assertTrue(features.contains(sf4)); @@ -308,18 +342,18 @@ public class FeatureRendererTest SequenceI seq = av.getAlignment().getSequenceAt(0); SequenceFeature sf1 = new SequenceFeature("Cath", "", 6, 8, Float.NaN, "group1"); - seq.addSequenceFeature(sf1); SequenceFeature sf2 = new SequenceFeature("Cath", "", 5, 11, 2f, "group2"); - seq.addSequenceFeature(sf2); SequenceFeature sf3 = new SequenceFeature("Cath", "", 5, 11, 3f, "group3"); - seq.addSequenceFeature(sf3); SequenceFeature sf4 = new SequenceFeature("Cath", "", 6, 8, 4f, "group4"); - seq.addSequenceFeature(sf4); SequenceFeature sf5 = new SequenceFeature("Cath", "", 6, 9, 5f, "group4"); + seq.addSequenceFeature(sf1); + seq.addSequenceFeature(sf2); + seq.addSequenceFeature(sf3); + seq.addSequenceFeature(sf4); seq.addSequenceFeature(sf5); fr.findAllFeatures(true); @@ -345,18 +379,26 @@ public class FeatureRendererTest assertTrue(features.contains(sf5)); /* - * hide groups 2 and 3 makes no difference to this method + * features in hidden groups are removed */ fr.setGroupVisibility("group2", false); fr.setGroupVisibility("group3", false); features = seq.getSequenceFeatures(); fr.filterFeaturesForDisplay(features); - assertEquals(features.size(), 3); + assertEquals(features.size(), 2); assertTrue(features.contains(sf1) || features.contains(sf4)); assertFalse(features.contains(sf1) && features.contains(sf4)); - assertTrue(features.contains(sf2) || features.contains(sf3)); - assertFalse(features.contains(sf2) && features.contains(sf3)); + assertFalse(features.contains(sf2)); + assertFalse(features.contains(sf3)); assertTrue(features.contains(sf5)); + + /* + * no filtering if transparency is applied + */ + fr.setTransparency(0.5f); + features = seq.getSequenceFeatures(); + fr.filterFeaturesForDisplay(features); + assertEquals(features.size(), 5); } @Test(groups = "Functional") @@ -378,11 +420,12 @@ public class FeatureRendererTest /* * hide feature type, then unhide + * - feature type visibility should not affect the result */ FeatureSettingsBean[] data = new FeatureSettingsBean[1]; data[0] = new FeatureSettingsBean("Cath", fc, null, false); fr.setFeaturePriority(data); - assertNull(fr.getColour(sf1)); + assertEquals(fr.getColour(sf1), Color.red); data[0] = new FeatureSettingsBean("Cath", fc, null, true); fr.setFeaturePriority(data); assertEquals(fr.getColour(sf1), Color.red); @@ -399,8 +442,8 @@ public class FeatureRendererTest * graduated colour by score, no threshold, no score * */ - FeatureColourI gc = new FeatureColour(Color.yellow, Color.red, - Color.green, 1f, 11f); + FeatureColourI gc = new FeatureColour(Color.red, Color.yellow, + Color.red, Color.green, 1f, 11f); fr.getFeatureColours().put("Cath", gc); assertEquals(fr.getColour(sf1), Color.green); @@ -412,7 +455,7 @@ public class FeatureRendererTest // 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 */ @@ -424,9 +467,11 @@ public class FeatureRendererTest * 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); + gc = new FeatureColour(Color.red, 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! + gc.setAutoScaled(false); // this does little other than save a checkbox + // setting! assertEquals(fr.getColour(sf2), new Color(255, 213, 0)); /* @@ -447,7 +492,8 @@ public class FeatureRendererTest * colour by feature attribute value * first with no value held */ - gc = new FeatureColour(Color.yellow, Color.red, Color.green, 1f, 11f); + gc = new FeatureColour(Color.red, Color.yellow, Color.red, Color.green, + 1f, 11f); fr.getFeatureColours().put("Cath", gc); gc.setAttributeName("AF"); assertEquals(fr.getColour(sf2), Color.green); @@ -468,14 +514,14 @@ public class FeatureRendererTest // with filter on AF < 4 gc.setAboveThreshold(false); assertEquals(fr.getColour(sf2), expected); - KeyedMatcherSetI filter = new KeyedMatcherSet(); - filter.and(new KeyedMatcher(Condition.LT, 4f, "AF")); + 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 KeyedMatcherSet(); - filter.and(new KeyedMatcher(Condition.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 @@ -487,10 +533,10 @@ public class FeatureRendererTest sf2.setValue("Consequence", "Missense variant"); assertEquals(fr.getColour(sf2), expected); - // with filter on CSQ.Feature contains "ENST01234" - filter = new KeyedMatcherSet(); - filter.and(new KeyedMatcher(Condition.Matches, "ENST01234", "CSQ", - "Feature")); + // 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)); @@ -506,4 +552,136 @@ public class FeatureRendererTest csqData.put("Feature", "ENST01234"); assertEquals(fr.getColour(sf2), expected); } + + @Test(groups = "Functional") + public void testIsVisible() + { + String seqData = ">s1\nMLQGIFPRS\n"; + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData, + DataSourceType.PASTE); + AlignViewportI av = af.getViewport(); + FeatureRenderer fr = new FeatureRenderer(av); + SequenceI seq = av.getAlignment().getSequenceAt(0); + SequenceFeature sf = new SequenceFeature("METAL", "Desc", 10, 10, 1f, + "Group"); + sf.setValue("AC", "11"); + sf.setValue("CLIN_SIG", "Likely Pathogenic"); + seq.addSequenceFeature(sf); + + assertFalse(fr.isVisible(null)); + + /* + * initial state FeatureRenderer hasn't 'found' feature + * and so its feature type has not yet been set visible + */ + assertFalse(fr.getDisplayedFeatureCols().containsKey("METAL")); + assertFalse(fr.isVisible(sf)); + + fr.findAllFeatures(true); + assertTrue(fr.isVisible(sf)); + + /* + * feature group not visible + */ + fr.setGroupVisibility("Group", false); + assertFalse(fr.isVisible(sf)); + fr.setGroupVisibility("Group", true); + assertTrue(fr.isVisible(sf)); + + /* + * feature score outwith colour threshold (score > 2) + */ + FeatureColourI fc = new FeatureColour(null, Color.white, Color.black, + Color.white, 0, 10); + fc.setAboveThreshold(true); + fc.setThreshold(2f); + fr.setColour("METAL", fc); + assertFalse(fr.isVisible(sf)); // score 1 is not above threshold 2 + fc.setBelowThreshold(true); + assertTrue(fr.isVisible(sf)); // score 1 is below threshold 2 + + /* + * colour with threshold on attribute AC (value is 11) + */ + fc.setAttributeName("AC"); + assertFalse(fr.isVisible(sf)); // value 11 is not below threshold 2 + fc.setAboveThreshold(true); + assertTrue(fr.isVisible(sf)); // value 11 is above threshold 2 + + fc.setAttributeName("AF"); // attribute AF is absent in sf + assertTrue(fr.isVisible(sf)); // feature is not excluded by threshold + + FeatureMatcherSetI filter = new FeatureMatcherSet(); + filter.and(FeatureMatcher.byAttribute(Condition.Contains, "pathogenic", + "CLIN_SIG")); + fr.setFeatureFilter("METAL", filter); + assertTrue(fr.isVisible(sf)); // feature matches filter + filter.and(FeatureMatcher.byScore(Condition.LE, "0.4")); + assertFalse(fr.isVisible(sf)); // feature doesn't match filter + } + + @Test(groups = "Functional") + public void testFindComplementFeaturesAtResidue() + { + Jalview.main( + new String[] + { "--nonews", "--props", "test/jalview/testProps.jvprops" }); + + // codons for MCWHSE + String cdsSeq = ">cds\nATGtgtTGGcacTCAgaa"; + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(cdsSeq, + DataSourceType.PASTE); + af.showTranslation_actionPerformed( + GeneticCodes.getInstance().getStandardCodeTable()); + af.closeMenuItem_actionPerformed(true); + + /* + * find the complement frames (ugly) + */ + AlignFrame[] frames = Desktop.getAlignFrames(); + assertEquals(frames.length, 2); + AlignViewport av1 = frames[0].getViewport(); + AlignViewport av2 = frames[1].getViewport(); + AlignViewport cds = av1.getAlignment().isNucleotide() ? av1 : av2; + AlignViewport peptide = cds == av1 ? av2 : av1; + assertNotNull(cds); + assertNotNull(peptide); + + /* + * add features to CDS at first codon, positions 2-3 + */ + SequenceI seq1 = cds.getAlignment().getSequenceAt(0); + SequenceFeature sf1 = new SequenceFeature("sequence_variant", "G,GT", 2, + 2, "ensembl"); + seq1.addSequenceFeature(sf1); + SequenceFeature sf2 = new SequenceFeature("sequence_variant", "C, CA", + 3, 3, "ensembl"); + seq1.addSequenceFeature(sf2); + + /* + * 'find' mapped features from the peptide position + * - first with CDS features _not_ shown on peptide alignment + */ + SequenceI seq2 = peptide.getAlignment().getSequenceAt(0); + FeatureRenderer frC = new FeatureRenderer(cds); + frC.featuresAdded(); + MappedFeatures mf = frC.findComplementFeaturesAtResidue(seq2, 1); + assertNotNull(mf); + assertEquals(mf.features.size(), 2); + assertSame(mf.features.get(0), sf1); + assertSame(mf.features.get(1), sf2); + + /* + * add exon feature and verify it is only returned once for a + * peptide position, even though it is on all 3 codon positions + */ + SequenceFeature sf3 = new SequenceFeature("exon", "exon1", 4, 12, + "ensembl"); + seq1.addSequenceFeature(sf3); + frC.featuresAdded(); + mf = frC.findComplementFeaturesAtResidue(seq2, 3); + assertNotNull(mf); + assertEquals(mf.features.size(), 1); + assertSame(mf.features.get(0), sf3); + } }