Merge branch 'develop' into update_212_Dec_merge_with_21125_chamges
[jalview.git] / test / jalview / renderer / seqfeatures / FeatureRendererTest.java
index da7cada..e1dac7d 100644 (file)
@@ -1,35 +1,68 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ * 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.AfterMethod;
+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.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
 {
+  @AfterMethod(alwaysRun = true)
+  public void tearDown()
+  {
+    Desktop.getInstance().closeAll_actionPerformed(null);
+  }
 
   @Test(groups = "Functional")
   public void testFindAllFeatures()
@@ -265,8 +298,8 @@ public class FeatureRendererTest
      * 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 +341,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,17 +378,17 @@ 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));
 
     /*
@@ -408,8 +441,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);
 
@@ -433,9 +466,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));
 
     /*
@@ -456,7 +491,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);
@@ -515,4 +551,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);
+  }
 }