JAL-3187 basic first version for tooltips only (rendering yet to do)
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 18 Jan 2019 15:12:46 +0000 (15:12 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 18 Jan 2019 15:12:46 +0000 (15:12 +0000)
src/jalview/api/ViewStyleI.java
src/jalview/gui/FeatureRenderer.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/SeqPanel.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/viewmodel/styles/ViewStyle.java

index 2b554ea..978ce61 100644 (file)
@@ -24,6 +24,9 @@ import java.awt.Color;
 
 public interface ViewStyleI
 {
+  void setShowComplementFeatures(boolean b);
+
+  boolean isShowComplementFeatures();
 
   void setColourAppliesToAllGroups(boolean b);
 
index 46f574e..c2a84c6 100644 (file)
@@ -21,6 +21,9 @@
 package jalview.gui;
 
 import jalview.api.FeatureColourI;
+import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.Mapping;
+import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceFeature;
@@ -574,4 +577,49 @@ public class FeatureRenderer
   {
     Arrays.sort(renderOrder, order);
   }
+
+  /**
+   * Answers a (possibly empty) list of features in this alignment at a position
+   * (or range) which is mappable from the given sequence residue position in a
+   * mapped alignment.
+   * 
+   * @param sequence
+   * @param pos
+   * @return
+   */
+  public List<SequenceFeature> findComplementFeaturesAtResidue(
+          SequenceI sequence, int pos)
+  {
+    SequenceI ds = sequence.getDatasetSequence();
+    List<SequenceFeature> result = new ArrayList<>();
+    List<AlignedCodonFrame> mappings = this.av.getAlignment()
+            .getCodonFrame(sequence);
+    for (AlignedCodonFrame acf : mappings)
+    {
+      Mapping mapping = acf.getMappingForSequence(sequence);
+      if (mapping.getMap().getFromRatio() == mapping.getMap().getToRatio())
+      {
+        continue; // we are only looking for 3:1 or 1:3 mappings
+      }
+      SearchResultsI sr = new SearchResults();
+      acf.markMappedRegion(ds, pos, sr);
+      for (SearchResultMatchI match : sr.getResults())
+      {
+        for (int i = match.getStart(); i <= match.getEnd(); i++)
+        {
+          List<SequenceFeature> fs = findFeaturesAtResidue(
+                  match.getSequence(), i);
+          for (SequenceFeature sf : fs)
+          {
+            if (!result.contains(sf))
+            {
+              result.addAll(fs);
+            }
+          }
+        }
+      }
+    }
+    
+    return result;
+  }
 }
index dbe3317..35215b4 100644 (file)
@@ -150,6 +150,8 @@ public class FeatureSettings extends JPanel
 
   JSlider transparency = new JSlider();
 
+  JCheckBox showComplement;
+
   /*
    * when true, constructor is still executing - so ignore UI events
    */
@@ -1260,6 +1262,19 @@ public class FeatureSettings extends JPanel
     transparency.setToolTipText(
             MessageManager.getString("label.transparency_tip"));
 
+    boolean nucleotide = af.getViewport().getAlignment().isNucleotide();
+    showComplement = new JCheckBox(
+            "Show " + (nucleotide ? "protein" : "CDS") + " features");
+    showComplement.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        af.getViewport()
+                .setShowComplementFeatures(showComplement.isSelected());
+      }
+    });
+
     JPanel transPanel = new JPanel(new GridLayout(1, 2));
     bigPanel.add(transPanel, BorderLayout.SOUTH);
 
@@ -1269,7 +1284,16 @@ public class FeatureSettings extends JPanel
     transbuttons.add(sortByScore);
     transbuttons.add(sortByDens);
     transbuttons.add(help);
-    transPanel.add(transparency);
+
+    boolean hasComplement = af.getViewport().getCodingComplement() != null;
+    JPanel transPanelLeft = new JPanel(
+            new GridLayout(hasComplement ? 2 : 1, 1));
+    transPanelLeft.add(transparency);
+    if (hasComplement)
+    {
+      transPanelLeft.add(showComplement);
+    }
+    transPanel.add(transPanelLeft);
     transPanel.add(transbuttons);
 
     JPanel buttonPanel = new JPanel();
index 8b2e7bc..6feda5a 100644 (file)
@@ -847,6 +847,23 @@ public class SeqPanel extends JPanel
               .findFeaturesAtColumn(sequence, column + 1);
       seqARep.appendFeatures(tooltipText, pos, features,
               this.ap.getSeqPanel().seqCanvas.fr);
+
+      /*
+       * add features in CDS/protein complement at the corresponding
+       * position if configured to do so
+       */
+      if (av.isShowComplementFeatures())
+      {
+        if (!Comparison.isGap(sequence.getCharAt(column)))
+        {
+          AlignViewportI complement = ap.getAlignViewport()
+                  .getCodingComplement();
+          AlignFrame af = Desktop.getAlignFrameFor(complement);
+          FeatureRenderer fr2 = af.getFeatureRenderer();
+          features = fr2.findComplementFeaturesAtResidue(sequence, pos);
+          seqARep.appendFeatures(tooltipText, pos, features, fr2);
+        }
+      }
     }
     if (tooltipText.length() == 6) // <html>
     {
index 1366ada..ec3f12e 100644 (file)
@@ -2714,6 +2714,18 @@ public abstract class AlignmentViewport
     viewStyle.setProteinFontAsCdna(b);
   }
 
+  @Override
+  public void setShowComplementFeatures(boolean b)
+  {
+    viewStyle.setShowComplementFeatures(b);
+  }
+
+  @Override
+  public boolean isShowComplementFeatures()
+  {
+    return viewStyle.isShowComplementFeatures();
+  }
+
   /**
    * @return true if view should scroll to show the highlighted region of a
    *         sequence
index 553f813..1f69776 100644 (file)
@@ -320,12 +320,12 @@ public abstract class FeatureRendererModel
             visibleTypes);
 
     /*
-     * include features unless their feature group is not displayed, or
-     * they are hidden (have no colour) based on a filter or colour threshold
+     * include features unless they are hidden (have no colour), based on 
+     * feature group visibility, or a filter or colour threshold
      */
     for (SequenceFeature sf : features)
     {
-      if (!featureGroupNotShown(sf) && getColour(sf) != null)
+      if (getColour(sf) != null)
       {
         result.add(sf);
       }
index 16aa580..1d1ab4d 100644 (file)
@@ -365,6 +365,8 @@ public class ViewStyle implements ViewStyleI
 
   private int fontStyle;
 
+  private boolean showComplementFeatures;
+
   /**
    * GUI state
    * 
@@ -1111,4 +1113,16 @@ public class ViewStyle implements ViewStyleI
   {
     proteinFontAsCdna = b;
   }
+
+  @Override
+  public void setShowComplementFeatures(boolean b)
+  {
+    showComplementFeatures = b;
+  }
+
+  @Override
+  public boolean isShowComplementFeatures()
+  {
+    return showComplementFeatures;
+  }
 }