JAL-1541 BioJs MSA Viewer export option implementation
authorCharles Ofoegbu <tcnofoegbu@dundee.ac.uk>
Thu, 30 Oct 2014 10:35:04 +0000 (10:35 +0000)
committerCharles Ofoegbu <tcnofoegbu@dundee.ac.uk>
Thu, 30 Oct 2014 10:35:04 +0000 (10:35 +0000)
.gitignore
resources/templates/BioJSTemplate.txt [new file with mode: 0644]
src/jalview/gui/AlignFrame.java
src/jalview/io/BioJsHTMLOutput.java [new file with mode: 0644]
src/jalview/jbgui/GAlignFrame.java

index 9841761..c47ff62 100644 (file)
@@ -3,4 +3,5 @@
 /classes
 .externalToolBuilders/Jalview Release indices [Builder].launch
 /.DS_Store
+.DS_Store
 /.com.apple.timemachine.supported
diff --git a/resources/templates/BioJSTemplate.txt b/resources/templates/BioJSTemplate.txt
new file mode 100644 (file)
index 0000000..324ecfe
--- /dev/null
@@ -0,0 +1,59 @@
+<html>
+<header><title>BioJS viewer</title></header>
+<body>
+
+<meta name="description" content="Simple BioJS example" />
+
+<!-- include MSA js + css -->
+<script src="https://s3-eu-west-1.amazonaws.com/biojs/msa/latest/msa.js"></script>
+<link type=text/css rel=stylesheet href=https://s3-eu-west-1.amazonaws.com/biojs/msa/latest/msa.css />
+  
+
+<!-- optional: menubar -->
+<link type=text/css rel=stylesheet href=  https://raw.githubusercontent.com/greenify/biojs-vis-msa/master/external/jquery.dropdown.css />
+  
+<div id="menuDiv"></div>
+<div id="yourDiv">press "Run with JS"</div>
+</body>
+</html>
+
+
+<script src=//cdn.biojs-msa.org/msa/0.2/msa.min.gz.js></script>
+
+<script>
+// this is a way how you use a bundled file parser
+biojs.io.clustal.read("http://www.corsproxy.com/rostlab.org/~goldberg/jalv_example.clustal", function(seqs){
+
+var opts = {};
+
+// set your custom properties
+// @see: https://github.com/greenify/biojs-vis-msa/tree/master/src/g 
+
+var seqOnFly = [];
+
+#sequenceData#
+//seqOnFly.push({seq:'ABCDEFGHIJKLMNOPQ', name:'seq1', id:0});
+//seqOnFly.push({seq:'ABCDEFGHIJKLMNOPQ', name:'seq2', id:1});
+
+opts.seqs = seqOnFly; //msa.utils.seqgen.getDummySequences(1000,300);
+
+//opts.seqs = seqs; //msa.utils.seqgen.getDummySequences(1000,300);
+opts.el = document.getElementById("yourDiv");
+opts.vis = {conserv: false, overviewbox: false};
+opts.zoomer = {alignmentHeight: 225, labelWidth: 130,labelFontsize: "13px",labelIdLength: 20,   menuFontsize: "12px",menuMarginLeft: "3px", menuPadding: "3px 4px 3px 4px", menuItemFontsize: "14px", menuItemLineHeight: "14px"};
+
+// init msa
+var m = new msa.msa(opts);
+
+// the menu is independent to the MSA container
+var menuOpts = {};
+menuOpts.el = document.getElementById('div');
+menuOpts.msa = m;
+var defMenu = new msa.menu.defaultmenu(menuOpts);
+m.addView("menu", defMenu);
+
+// call render at the end to display the whole MSA
+m.render();
+  
+});
+</script>
\ No newline at end of file
index d9c0c6a..a9eeb12 100644 (file)
@@ -53,6 +53,7 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.io.AlignmentProperties;
 import jalview.io.AnnotationFile;
+import jalview.io.BioJsHTMLOutput;
 import jalview.io.FeaturesFile;
 import jalview.io.FileLoader;
 import jalview.io.FormatAdapter;
@@ -377,7 +378,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                         .getKeyCode() >= KeyEvent.VK_NUMPAD0 && evt
                         .getKeyCode() <= KeyEvent.VK_NUMPAD9))
                 && Character.isDigit(evt.getKeyChar()))
+        {
           alignPanel.seqPanel.numberPressed(evt.getKeyChar());
+        }
 
         switch (evt.getKeyCode())
         {
@@ -389,32 +392,48 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
         case KeyEvent.VK_DOWN:
           if (evt.isAltDown() || !viewport.cursorMode)
+          {
             moveSelectedSequences(false);
+          }
           if (viewport.cursorMode)
+          {
             alignPanel.seqPanel.moveCursor(0, 1);
+          }
           break;
 
         case KeyEvent.VK_UP:
           if (evt.isAltDown() || !viewport.cursorMode)
+          {
             moveSelectedSequences(true);
+          }
           if (viewport.cursorMode)
+          {
             alignPanel.seqPanel.moveCursor(0, -1);
+          }
 
           break;
 
         case KeyEvent.VK_LEFT:
           if (evt.isAltDown() || !viewport.cursorMode)
+          {
             slideSequences(false, alignPanel.seqPanel.getKeyboardNo1());
+          }
           else
+          {
             alignPanel.seqPanel.moveCursor(-1, 0);
+          }
 
           break;
 
         case KeyEvent.VK_RIGHT:
           if (evt.isAltDown() || !viewport.cursorMode)
+          {
             slideSequences(true, alignPanel.seqPanel.getKeyboardNo1());
+          }
           else
+          {
             alignPanel.seqPanel.moveCursor(1, 0);
+          }
           break;
 
         case KeyEvent.VK_SPACE:
@@ -551,14 +570,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         {
         case KeyEvent.VK_LEFT:
           if (evt.isAltDown() || !viewport.cursorMode)
+          {
             viewport.firePropertyChange("alignment", null, viewport
                     .getAlignment().getSequences());
+          }
           break;
 
         case KeyEvent.VK_RIGHT:
           if (evt.isAltDown() || !viewport.cursorMode)
+          {
             viewport.firePropertyChange("alignment", null, viewport
                     .getAlignment().getSequences());
+          }
           break;
         }
       }
@@ -1207,6 +1230,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
   }
 
+  @Override
+  public void bioJSMenuItem_actionPerformed(ActionEvent e)
+  {
+    new BioJsHTMLOutput(alignPanel,
+            alignPanel.seqPanel.seqCanvas.getSequenceRenderer(),
+            alignPanel.seqPanel.seqCanvas.getFeatureRenderer());
+  }
   public void createImageMap(File file, String image)
   {
     alignPanel.makePNGImageMap(file, image);
@@ -1458,7 +1488,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   protected void undoMenuItem_actionPerformed(ActionEvent e)
   {
     if (viewport.historyList.empty())
+    {
       return;
+    }
     CommandI command = (CommandI) viewport.historyList.pop();
     viewport.redoList.push(command);
     command.undoCommand(getViewAlignments());
@@ -1611,37 +1643,53 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     for (int i = 0; i < viewport.getAlignment().getHeight(); i++)
     {
       if (!sg.contains(viewport.getAlignment().getSequenceAt(i)))
+      {
         invertGroup.add(viewport.getAlignment().getSequenceAt(i));
+      }
     }
 
     SequenceI[] seqs1 = sg.toArray(new SequenceI[0]);
 
     SequenceI[] seqs2 = new SequenceI[invertGroup.size()];
     for (int i = 0; i < invertGroup.size(); i++)
+    {
       seqs2[i] = (SequenceI) invertGroup.elementAt(i);
+    }
 
     SlideSequencesCommand ssc;
     if (right)
+    {
       ssc = new SlideSequencesCommand("Slide Sequences", seqs2, seqs1,
               size, viewport.getGapCharacter());
+    }
     else
+    {
       ssc = new SlideSequencesCommand("Slide Sequences", seqs1, seqs2,
               size, viewport.getGapCharacter());
+    }
 
     int groupAdjustment = 0;
     if (ssc.getGapsInsertedBegin() && right)
     {
       if (viewport.cursorMode)
+      {
         alignPanel.seqPanel.moveCursor(size, 0);
+      }
       else
+      {
         groupAdjustment = size;
+      }
     }
     else if (!ssc.getGapsInsertedBegin() && !right)
     {
       if (viewport.cursorMode)
+      {
         alignPanel.seqPanel.moveCursor(-size, 0);
+      }
       else
+      {
         groupAdjustment = -size;
+      }
     }
 
     if (groupAdjustment != 0)
@@ -1662,7 +1710,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
 
     if (!appendHistoryItem)
+    {
       addHistoryItem(ssc);
+    }
 
     repaint();
   }
@@ -1997,7 +2047,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           {
             AlignmentAnnotation sann[] = sequences[i].getAnnotation();
             if (sann == null)
+            {
               continue;
+            }
             for (int avnum = 0; avnum < alview.length; avnum++)
             {
               if (alview[avnum] != alignment)
@@ -4643,7 +4695,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
               if (ds.getSequences() == null
                       || !ds.getSequences().contains(
                               sprods[s].getDatasetSequence()))
+              {
                 ds.addSequence(sprods[s].getDatasetSequence());
+              }
               sprods[s].updatePDBIds();
             }
             Alignment al = new Alignment(sprods);
diff --git a/src/jalview/io/BioJsHTMLOutput.java b/src/jalview/io/BioJsHTMLOutput.java
new file mode 100644 (file)
index 0000000..5a236dc
--- /dev/null
@@ -0,0 +1,91 @@
+package jalview.io;
+
+import static java.nio.file.Files.readAllBytes;
+import static java.nio.file.Paths.get;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignViewport;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.FeatureRenderer;
+import jalview.gui.SequenceRenderer;
+import jalview.util.MessageManager;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class BioJsHTMLOutput
+{
+  private AlignViewport av;
+  private FeatureRenderer fr;
+
+  public BioJsHTMLOutput(AlignmentPanel ap, SequenceRenderer sr,
+          FeatureRenderer fr1)
+  {
+    System.out.println("BioJs working as expected so far");
+    this.av = ap.av;
+
+    this.fr = new FeatureRenderer(ap);
+    fr.transferSettings(fr1);
+    exportAsBioJsHtml();
+  }
+
+  private void exportAsBioJsHtml()
+  {
+    try
+    {
+      JalviewFileChooser jvFileChooser = getJalviewFileChooserOption();
+      int fileChooserOpt = jvFileChooser.showSaveDialog(null);
+      if (fileChooserOpt == JalviewFileChooser.APPROVE_OPTION)
+      {
+        jalview.bin.Cache.setProperty("LAST_DIRECTORY", jvFileChooser
+                .getSelectedFile().getParent());
+        String selectedFile = jvFileChooser.getSelectedFile().getPath();
+        String generartedBioJs = generateBioJsAlignmentData(av
+                .getAlignment());
+        PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
+                selectedFile));
+        out.print(generartedBioJs);
+        out.close();
+        jalview.util.BrowserLauncher.openURL("file:///" + selectedFile);
+      }
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+
+  private JalviewFileChooser getJalviewFileChooserOption()
+  {
+    JalviewFileChooser chooser = new JalviewFileChooser(
+            jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[]
+            { "html" }, new String[]
+            { "HTML files" }, "HTML files");
+
+    chooser.setFileView(new JalviewFileView());
+    // TODO uncomment when supported by MassageManager
+    // chooser.setDialogTitle(MessageManager.getString("label.save_as_biojs_html"));
+    chooser.setDialogTitle("save as BioJs HTML");
+    chooser.setToolTipText(MessageManager.getString("action.save"));
+
+    return chooser;
+  }
+
+  private String generateBioJsAlignmentData(AlignmentI alignment)
+          throws IOException
+  {
+    StringBuilder bioJsData = new StringBuilder();
+    int count = 0;
+    for (SequenceI seq : alignment.getSequences())
+    {
+      bioJsData.append("seqOnFly.push({seq:'" + seq.getSequenceAsString()
+              + "', name:'" + seq.getName() + "', id:" + ++count + "});");
+    }
+    String bioJSTemplate = new String(
+            readAllBytes(get("resources/templates/BioJSTemplate.txt")));
+
+    return bioJSTemplate.replaceAll("#sequenceData#", bioJsData.toString());
+  }
+
+
+}
+
index afb0dc1..741c124 100755 (executable)
@@ -210,6 +210,8 @@ public class GAlignFrame extends JInternalFrame
 
   JMenuItem createPNG = new JMenuItem();
 
+  JMenuItem createBioJS = new JMenuItem();
+
   protected JMenuItem font = new JMenuItem();
 
   public JCheckBoxMenuItem seqLimits = new JCheckBoxMenuItem();
@@ -1118,6 +1120,19 @@ public class GAlignFrame extends JInternalFrame
         htmlMenuItem_actionPerformed(e);
       }
     });
+
+    // TODO uncomment when supported by MassageManager
+    // createBioJS.setText(MessageManager.getString("label.biojs_html_export"));
+    createBioJS.setText("BioJS");
+    createBioJS.addActionListener(new java.awt.event.ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        bioJSMenuItem_actionPerformed(e);
+      }
+    });
+
     overviewMenuItem.setText(MessageManager
             .getString("label.overview_window"));
     overviewMenuItem.addActionListener(new java.awt.event.ActionListener()
@@ -1497,7 +1512,6 @@ public class GAlignFrame extends JInternalFrame
         font_actionPerformed(e);
       }
     });
-
     seqLimits.setText(MessageManager
             .getString("label.show_sequence_limits"));
     seqLimits.setState(jalview.bin.Cache.getDefault("SHOW_JVSUFFIX", true));
@@ -2225,6 +2239,7 @@ public class GAlignFrame extends JInternalFrame
     jMenu2.add(htmlMenuItem);
     jMenu2.add(epsFile);
     jMenu2.add(createPNG);
+    jMenu2.add(createBioJS);
     addSequenceMenu.add(addFromFile);
     addSequenceMenu.add(addFromText);
     addSequenceMenu.add(addFromURL);
@@ -2455,6 +2470,11 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
+  protected void bioJSMenuItem_actionPerformed(ActionEvent e)
+  {
+
+  }
+
   protected void closeMenuItem_actionPerformed(boolean b)
   {
   }