JAL-1466 new calculation menu option to recover the full width sequences either side...
authorJim Procter <jprocter@dundee.ac.uk>
Tue, 15 Apr 2014 17:50:12 +0000 (18:50 +0100)
committerJim Procter <jprocter@dundee.ac.uk>
Mon, 21 Apr 2014 13:09:17 +0000 (14:09 +0100)
src/jalview/analysis/AlignmentUtils.java [new file with mode: 0644]
src/jalview/gui/AlignFrame.java
src/jalview/jbgui/GAlignFrame.java
test/jalview/analysis/AlignmentUtilsTests.java [new file with mode: 0644]

diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java
new file mode 100644 (file)
index 0000000..2e607c0
--- /dev/null
@@ -0,0 +1,91 @@
+package jalview.analysis;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.AlignmentI;
+
+/**
+ * grab bag of useful alignment manipulation operations
+ * Expect these to be refactored elsewhere at some point.
+ * @author jimp
+ *
+ */
+public class AlignmentUtils
+{
+
+  /**
+   * given an existing alignment, create a new alignment including all, or up to flankSize additional symbols from each sequence's dataset sequence
+   * @param core
+   * @param flankSize
+   * @return AlignmentI
+   */
+  public static AlignmentI expandContext(AlignmentI core, int flankSize)
+  {
+    List<SequenceI> sq = new ArrayList<SequenceI>();
+    int maxoffset = 0;
+    for (SequenceI s:core.getSequences())
+    {
+      SequenceI newSeq = s.deriveSequence();
+      if (newSeq.getStart()>maxoffset)
+      {
+        maxoffset = newSeq.getStart();
+      }
+      sq.add(newSeq);
+    }
+    if (flankSize>-1) {
+      maxoffset = flankSize;
+    }
+    // now add offset to create a new expanded alignment
+    for (SequenceI s:sq)
+    {
+      SequenceI ds = s;
+      while (ds.getDatasetSequence()!=null) {
+        ds=ds.getDatasetSequence();
+      }
+      // find available flanking residues for sequence
+      int ustream_ds=s.getStart()-ds.getStart(),dstream_ds=ds.getEnd()-s.getEnd();
+      
+      // build new flanked sequence
+      
+      // compute gap padding to start of flanking sequence
+      int offset=maxoffset - ustream_ds;
+      
+      // padding is gapChar x ( maxoffset - min(ustream_ds, flank)
+      if (flankSize>=0) {
+        if (flankSize<ustream_ds)
+        {
+        // take up to flankSize residues
+        offset = maxoffset-flankSize;
+        ustream_ds = flankSize;
+      }
+        if (flankSize<dstream_ds)
+        {
+          dstream_ds=flankSize;
+        }
+      }
+      char[] upstream = new String(ds.getSequence(s.getStart()-1-ustream_ds, s.getStart()-1)).toLowerCase().toCharArray();
+      char[] downstream = new String(ds.getSequence(s.getEnd()+1,s.getEnd()+1+dstream_ds)).toLowerCase().toCharArray();
+      char[] coreseq=s.getSequence();
+      char[] nseq = new char[offset+upstream.length+downstream.length+coreseq.length]; 
+      char c = core.getGapCharacter();
+      // TODO could lowercase the flanking regions
+      int p=0;
+      for (; p<offset;p++)
+      {
+        nseq[p] = c;
+      }
+//      s.setSequence(new String(upstream).toLowerCase()+new String(coreseq) + new String(downstream).toLowerCase());
+      System.arraycopy(upstream, 0, nseq, p, upstream.length);
+      System.arraycopy(coreseq, 0, nseq, p+upstream.length, coreseq.length);
+      System.arraycopy(downstream, 0, nseq, p+coreseq.length+upstream.length, downstream.length);
+      s.setSequence(new String(nseq));
+      s.setStart(s.getStart()-ustream_ds);
+      s.setEnd(s.getEnd()+downstream.length);
+    }
+    AlignmentI newAl = new jalview.datamodel.Alignment(sq.toArray(new SequenceI[0]));
+    newAl.setDataset(core.getDataset());
+    return newAl;
+  }
+}
index a305479..f7e95b7 100644 (file)
@@ -20,6 +20,7 @@ package jalview.gui;
 
 import jalview.analysis.AAFrequency;
 import jalview.analysis.AlignmentSorter;
+import jalview.analysis.AlignmentUtils;
 import jalview.analysis.Conservation;
 import jalview.analysis.CrossRef;
 import jalview.analysis.NJTree;
@@ -2061,7 +2062,59 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
 
   }
+  @Override
+  protected void expand_newalign(ActionEvent e)
+  {
+    try {
+    AlignmentI alignment = AlignmentUtils.expandContext(getViewport().getAlignment(), -1);
+    AlignFrame af = new AlignFrame(alignment, DEFAULT_WIDTH,
+            DEFAULT_HEIGHT);
+    String newtitle = new String("Flanking alignment");
+
+    if (Desktop.jalviewClipboard != null
+            && Desktop.jalviewClipboard[2] != null)
+    {
+      Vector hc = (Vector) Desktop.jalviewClipboard[2];
+      for (int i = 0; i < hc.size(); i++)
+      {
+        int[] region = (int[]) hc.elementAt(i);
+        af.viewport.hideColumns(region[0], region[1]);
+      }
+    }
+
+    // >>>This is a fix for the moment, until a better solution is
+    // found!!<<<
+    af.alignPanel.seqPanel.seqCanvas.getFeatureRenderer()
+            .transferSettings(
+                    alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
+
+    // TODO: maintain provenance of an alignment, rather than just make the
+    // title a concatenation of operations.
+    {
+      if (title.startsWith("Copied sequences"))
+      {
+        newtitle = title;
+      }
+      else
+      {
+        newtitle = newtitle.concat("- from " + title);
+      }
+    }
+
+    Desktop.addInternalFrame(af, newtitle, DEFAULT_WIDTH,
+            DEFAULT_HEIGHT);
 
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+      System.out.println("Exception whilst pasting: " + ex);
+      // could be anything being pasted in here
+    }
+    catch (OutOfMemoryError oom)
+    {
+      new OOMWarning("Viewing flanking region of alignment", oom);
+    }
+  }
   /**
    * DOCUMENT ME!
    * 
index 13ec23f..6feca56 100755 (executable)
@@ -242,6 +242,8 @@ public class GAlignFrame extends JInternalFrame
   protected JMenuItem showTranslation = new JMenuItem();
 
   protected JMenuItem extractScores = new JMenuItem();
+  
+  protected JMenuItem expandAlignment = new JMenuItem();
 
   protected JMenu showProducts = new JMenu();
 
@@ -630,7 +632,14 @@ public class GAlignFrame extends JInternalFrame
         makeGrpsFromSelection_actionPerformed(e);
       }
     });
-
+    expandAlignment.setText(MessageManager.getString("action.view_flanking_regions"));
+    expandAlignment.addActionListener(new java.awt.event.ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        expand_newalign(e);
+      }
+    });
     remove2LeftMenuItem.setText(MessageManager.getString("action.remove_left"));
     remove2LeftMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(
             java.awt.event.KeyEvent.VK_L, Toolkit.getDefaultToolkit()
@@ -1972,6 +1981,7 @@ public class GAlignFrame extends JInternalFrame
     selectMenu.add(unGroup);
     selectMenu.add(grpsFromSelection);
     selectMenu.add(deleteGroups);
+    calculateMenu.add(expandAlignment);
     // TODO - determine if the listenToViewSelections button is needed : see bug
     // JAL-574
     // selectMenu.addSeparator();
@@ -2612,4 +2622,10 @@ public class GAlignFrame extends JInternalFrame
   {
 
   }
+
+  protected void expand_newalign(ActionEvent e)
+  {
+    // TODO Auto-generated method stub
+    
+  }
 }
diff --git a/test/jalview/analysis/AlignmentUtilsTests.java b/test/jalview/analysis/AlignmentUtilsTests.java
new file mode 100644 (file)
index 0000000..5039deb
--- /dev/null
@@ -0,0 +1,30 @@
+package jalview.analysis;
+
+import org.junit.Test;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.io.AppletFormatAdapter;
+
+public class AlignmentUtilsTests 
+{
+  public static Sequence ts=new Sequence("short","ASDASDASDASDASDASDASDASDASDASDASDASDASD");
+  @Test
+  public void testExpandFlanks()
+  {
+    AlignmentI al = new Alignment(new Sequence[] {});
+    for (int i=4;i<14;i+=3)
+    {
+      SequenceI s1=ts.deriveSequence().getSubSequence(i, i+7);
+      al.addSequence(s1);
+    }
+    System.out.println(new AppletFormatAdapter().formatSequences("Clustal", al, true));
+    for (int flnk=-1;flnk<25; flnk++)
+    {
+      System.out.println("\nFlank size: "+flnk);
+      System.out.println(new AppletFormatAdapter().formatSequences("Clustal", AlignmentUtils.expandContext(al, flnk), true));
+    }    
+  }
+}