JAL-2871 JAL-2877 hideous attempt at seeing if non-static configuration
[jalview.git] / src / jalview / ext / archaeopteryx / AptxInit.java
index 4a49734..aa106c3 100644 (file)
@@ -1,25 +1,48 @@
 package jalview.ext.archaeopteryx;
 
 import jalview.analysis.TreeBuilder;
+import jalview.bin.Cache;
 import jalview.datamodel.SequenceI;
 import jalview.ext.treeviewer.ExternalTreeBuilderI;
 import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
 import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
+import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 
+import java.awt.Component;
 import java.awt.Dimension;
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.HashMap;
 import java.util.Map;
 
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JSeparator;
+
 import org.forester.archaeopteryx.AptxUtil;
 import org.forester.archaeopteryx.Archaeopteryx;
 import org.forester.archaeopteryx.Configuration;
 import org.forester.archaeopteryx.MainFrame;
+import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
+import org.forester.archaeopteryx.webservices.WebserviceUtil;
+import org.forester.io.parsers.PhylogenyParser;
+import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
 import org.forester.io.parsers.nhx.NHXParser;
+import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
+import org.forester.io.parsers.phyloxml.PhyloXmlParser;
+import org.forester.io.parsers.tol.TolParser;
+import org.forester.io.parsers.util.ParserUtils;
 import org.forester.phylogeny.Phylogeny;
+import org.forester.phylogeny.PhylogenyMethods;
 import org.forester.phylogeny.PhylogenyNode;
+import org.forester.phylogeny.data.Identifier;
+import org.forester.util.ForesterUtil;
 
 /**
  * Static class for creating Archaeopteryx tree viewer instances from calculated
@@ -31,138 +54,470 @@ import org.forester.phylogeny.PhylogenyNode;
 public final class AptxInit
 {
 
-  private final static Configuration APTX_CONFIG = new Configuration(
-          "_aptx_jalview_configuration_file", false, false, false);
+  private static Map<MainFrame, JalviewBinding> activeAptx = new HashMap<>();
 
-  private final static boolean VALIDATE_PHYLOXML_XSD = APTX_CONFIG
-          .isValidatePhyloXmlAgainstSchema();
 
-  private final static boolean REPLACE_NHX_UNDERSCORES = APTX_CONFIG
-          .isReplaceUnderscoresInNhParsing();
 
-  private final static boolean INTERNAL_NUMBERS_AS_CONFIDENCE = APTX_CONFIG
-          .isInternalNumberAreConfidenceForNhParsing();
+  public static MainFrame createInstanceFromCalculation(
+          final TreeBuilder calculatedTree)
+  {
+    ExternalTreeBuilderI<Phylogeny, PhylogenyNode> aptxTreeBuilder = new AptxTreeBuilder(
+            calculatedTree);
 
-  private final static boolean MIDPOINT_REROOT = APTX_CONFIG
-          .isMidpointReroot();
+    Phylogeny aptxTree = aptxTreeBuilder.buildTree();
 
-  private final static NHXParser.TAXONOMY_EXTRACTION TAXONOMY_EXTRACTION = APTX_CONFIG
-          .getTaxonomyExtraction();
+    MainFrame aptxApp = createAptxFrame(aptxTree,
+            calculatedTree.getAvport(), null);
+            
+    return aptxApp;
+  }
 
   /**
-   * Test method, should generally not be used as it does not bind the tree to
-   * its alignment
+   * Refactored from Archaeopteryx.main
    * 
-   * @param aptxTrees
+   * @param filePath
+   * @param viewport
    * @return
+   * @throws IOException
+   * @throws FileNotFoundException
    */
-  public static MainFrame createUnboundInstance(final Phylogeny aptxTree)
+  public static MainFrame[] createInstancesFromFile(String filePath,
+          AlignmentViewport viewport)
+          throws FileNotFoundException, IOException
   {
-    Phylogeny[] aptxTrees = { aptxTree };
-    return createAptxFrame(aptxTrees);
-  }
+    Configuration APTX_CONFIG = new Configuration(Cache.getDefault(
+            "APTXCONFIG",
+            Desktop.instance.getClass()
+                    .getResource("/_aptx_jalview_configuration_file.txt")
+                    .toString()),
+            false, false, false);
+    File treeFile = new File(filePath);
+    final String err = ForesterUtil.isReadableFile(treeFile);
+    if (!ForesterUtil.isEmpty(err))
+    {
+      JvOptionPane.showMessageDialog(Desktop.desktop, err,
+              MessageManager.getString("label.problem_reading_tree_file"),
+              JvOptionPane.WARNING_MESSAGE);
+    }
 
-  // public static MainFrame createInstance(final Phylogeny[] aptxTrees,
-  // AlignmentViewport jalviewAlignmentView)
-  // {
-  // return createAptxFrameInJalview(aptxTrees);
-  //
-  // }
-  //
-  // public static MainFrame createInstance(final Phylogeny aptxTree,
-  // final AlignmentViewport jalviewAlignmentView)
-  // {
-  // Phylogeny[] aptxTrees = { aptxTree }; // future possibility to load in
-  // // several trees simultaneously
-  // return createAptxFrameInJalview(aptxTrees);
-  //
-  // }
-
-  public static MainFrame createInstance(
-          final TreeBuilder calculatedTree) // very dense method, to be split up
-  {
-    ExternalTreeBuilderI<Phylogeny, PhylogenyNode> aptxTreeBuilder = new AptxTreeBuilder(
-            calculatedTree);
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.startLoading(filePath);
+    }
+    boolean nhx_or_nexus = false;
+    final PhylogenyParser parser = ParserUtils.createParserDependingOnFileType(
+                    treeFile,
+                    APTX_CONFIG.isValidatePhyloXmlAgainstSchema());
+    if (parser instanceof NHXParser)
+    {
+      nhx_or_nexus = true;
+      final NHXParser nhx = (NHXParser) parser;
+      nhx.setReplaceUnderscores(
+              APTX_CONFIG.isReplaceUnderscoresInNhParsing());
+      nhx.setIgnoreQuotes(false);
+      nhx.setTaxonomyExtraction(APTX_CONFIG.getTaxonomyExtraction());
+    }
+    else if (parser instanceof NexusPhylogeniesParser)
+    {
+      nhx_or_nexus = true;
+      final NexusPhylogeniesParser nex = (NexusPhylogeniesParser) parser;
+      nex.setReplaceUnderscores(
+              APTX_CONFIG.isReplaceUnderscoresInNhParsing());
+      nex.setIgnoreQuotes(false);
+    }
+    else if (parser instanceof PhyloXmlParser)
+    {
+      if (APTX_CONFIG.isValidatePhyloXmlAgainstSchema() == false)
+      {
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                MessageManager.getString("error.phyloxml_validation"),
+                MessageManager.getString("label.file_open_error"),
+                                       JvOptionPane.WARNING_MESSAGE );
+      }
+    }
+    Phylogeny[] trees = PhylogenyMethods.readPhylogenies(parser, treeFile);
+    MainFrame[] aptxFrames = new MainFrame[trees.length];
 
-    Phylogeny aptxTree = aptxTreeBuilder.buildTree();
-    Phylogeny[] aptxTrees = { aptxTree }; // future possibility to load in
-                                          // several trees simultaneously
 
-    MainFrame aptxApp = createAptxFrame(aptxTrees);
-            
-    bindNodesToJalviewSequences(aptxApp, calculatedTree.getAvport(),
-            aptxTreeBuilder.getAlignmentBoundNodes(),
-            aptxTreeBuilder.getNodesBoundAlignment());
+    for (int i = 0; i < trees.length; i++)
+      {
+      Phylogeny tree = trees[i];
 
-    return bindFrameToJalview(aptxApp);
+      if (nhx_or_nexus
+              && APTX_CONFIG.isInternalNumberAreConfidenceForNhParsing())
+      {
+        PhylogenyMethods.transferInternalNodeNamesToConfidence(tree, "");
+      }
+      String treeTitle = treeFile.getName() + "[" + i + "]";
+      tree.setName(treeTitle);
+      aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
 
-  }
+    }
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.stopLoading();
+    }
+    return aptxFrames;
+    }
 
-  public static MainFrame createInstanceFromFile(String filePath,
+
+  public static MainFrame[] createInstancesFromUrl(URL treeUrl,
           AlignmentViewport viewport)
+          throws FileNotFoundException, IOException, RuntimeException
   {
-    String[] AptxArgs = new String[] { "-c",
-        APTX_CONFIG.getConfigFilename(), filePath };
-    MainFrame aptxApp = Archaeopteryx.main(AptxArgs);
-
-    int tabCount = aptxApp.getMainPanel().getTabbedPane().getTabCount();
-
-    for (int i = 0; i < tabCount; i++)
+    Configuration APTX_CONFIG = new Configuration(Cache.getDefault(
+            "APTXCONFIG",
+            Desktop.instance.getClass()
+                    .getResource("/_aptx_jalview_configuration_file.txt")
+                    .toString()),
+            false, false, false);
+    String treeTitle = treeUrl.getFile();
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.startLoading(treeTitle);
+    }
+    Phylogeny[] trees = AptxUtil.readPhylogeniesFromUrl(treeUrl,
+            APTX_CONFIG.isValidatePhyloXmlAgainstSchema(),
+            APTX_CONFIG.isReplaceUnderscoresInNhParsing(),
+            APTX_CONFIG.isInternalNumberAreConfidenceForNhParsing(),
+            APTX_CONFIG.getTaxonomyExtraction(),
+            APTX_CONFIG.isMidpointReroot());
+
+    MainFrame[] aptxFrames = new MainFrame[trees.length];
+    for (int i = 0; i < trees.length; i++)
     {
-      // roundabout way to select each tree because getComponentAt(i) requires
-      // casting to TreePanel which doesn't work
-      aptxApp.getMainPanel().getTabbedPane().setSelectedIndex(i);
-      Phylogeny tree = aptxApp.getMainPanel().getCurrentTreePanel()
-              .getPhylogeny();
+      Phylogeny tree = trees[i];
+      aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
+    }
 
-    LoadedTreeAssociation bindAptxNodes = new LoadedTreeAssociation(
-            viewport.getAlignment().getSequencesArray(),
-              tree);
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.stopLoading();
+    }
 
-    bindAptxNodes.associateLeavesToSequences();
+    return aptxFrames;
 
-    bindNodesToJalviewSequences(aptxApp, viewport,
-            bindAptxNodes.getAlignmentWithNodes(),
-            bindAptxNodes.getNodesWithAlignment());
-    }
-    return bindFrameToJalview(aptxApp);
   }
 
-  public static MainFrame createInstanceFromUrl(URL treeUrl,
+  /**
+   * Refactored from Forester's UrlTreeReader, this can be more efficient
+   * 
+   * @param databaseIndex
+   * @param viewport
+   * @return
+   */
+  public static MainFrame[] createInstancesFromDb(
+          PhylogeniesWebserviceClient treeDbClient, String identifier,
           AlignmentViewport viewport)
-          throws FileNotFoundException, IOException, RuntimeException
   {
-    
-    Phylogeny[] trees = AptxUtil.readPhylogeniesFromUrl(treeUrl,
-            VALIDATE_PHYLOXML_XSD,
-             REPLACE_NHX_UNDERSCORES, INTERNAL_NUMBERS_AS_CONFIDENCE,
-            TAXONOMY_EXTRACTION, MIDPOINT_REROOT);
-    MainFrame aptxApp = Archaeopteryx.createApplication(trees, APTX_CONFIG,
-            null);
-
-    for (Phylogeny tree : trees)
+    Configuration APTX_CONFIG = new Configuration(Cache.getDefault(
+            "APTXCONFIG",
+            Desktop.instance.getClass()
+                    .getResource("/_aptx_jalview_configuration_file.txt")
+                    .toString()),
+            false, false, false);
+    URL url = null;
+    Phylogeny[] trees = null;
+
+    if ((identifier != null) && (identifier.trim().length() > 0))
     {
-      LoadedTreeAssociation bindAptxNodes = new LoadedTreeAssociation(
-              viewport.getAlignment().getSequencesArray(), tree);
+      if (Desktop.instance != null)
+      {
+        Desktop.instance.startLoading(identifier);
+      }
+
+      identifier = identifier.trim();
+      if (treeDbClient.isQueryInteger())
+      {
+        identifier = identifier.replaceAll("^\\D+", "");
+
+        int id;
+        try
+        {
+          id = Integer.parseInt(identifier);
+        } catch (final NumberFormatException e)
+        {
+          JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                  MessageManager.formatMessage(
+                          "error.database_id_has_letters", new String[]
+                          { identifier }),
+                  MessageManager.getString("label.invalid_url"),
+                  JvOptionPane.ERROR_MESSAGE);
+          return new MainFrame[0];
+        }
+        identifier = id + "";
+      }
+      boolean exception = false;
+      try
+      {
+        String url_str = treeDbClient.getUrl();
+        url_str = url_str.replaceFirst(
+                PhylogeniesWebserviceClient.QUERY_PLACEHOLDER, identifier);
+        url = new URL(url_str);
+        PhylogenyParser parser = null;
+        switch (treeDbClient.getReturnFormat())
+        {
+        case TOL_XML_RESPONSE:
+          parser = new TolParser();
+          break;
+        case NEXUS:
+          parser = new NexusPhylogeniesParser();
+          ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
+          break;
+        case TREEBASE_TREE:
+          parser = new NexusPhylogeniesParser();
+          ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
+          ((NexusPhylogeniesParser) parser)
+                  .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
+          break;
+        case TREEBASE_STUDY:
+          parser = new NexusPhylogeniesParser();
+          ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
+          ((NexusPhylogeniesParser) parser)
+                  .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
+          break;
+        case NH:
+          parser = new NHXParser();
+          ((NHXParser) parser)
+                  .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
+          ((NHXParser) parser).setReplaceUnderscores(true);
+          ((NHXParser) parser).setGuessRootedness(true);
+          break;
+        case NH_EXTRACT_TAXONOMY:
+          parser = new NHXParser();
+          ((NHXParser) parser).setTaxonomyExtraction(
+                  NHXParser.TAXONOMY_EXTRACTION.AGGRESSIVE);
+          ((NHXParser) parser).setReplaceUnderscores(false);
+          ((NHXParser) parser).setGuessRootedness(true);
+          break;
+        case PFAM:
+          parser = new NHXParser();
+          ((NHXParser) parser).setTaxonomyExtraction(
+                  NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT);
+          ((NHXParser) parser).setReplaceUnderscores(false);
+          ((NHXParser) parser).setGuessRootedness(true);
+          break;
+        case NHX:
+          parser = new NHXParser();
+          ((NHXParser) parser)
+                  .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
+          ((NHXParser) parser).setReplaceUnderscores(false);
+          ((NHXParser) parser).setGuessRootedness(true);
+          break;
+        case PHYLOXML:
+          parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();
+          break;
+        default:
+          throw new IllegalArgumentException(
+                  "unknown format: " + treeDbClient.getReturnFormat());
+        }
+        //
+        // if (_main_frame.getMainPanel().getCurrentTreePanel() != null)
+        // {
+        // _main_frame.getMainPanel().getCurrentTreePanel().setWaitCursor();
+        // }
+        // else
+        // {
+        // _main_frame.getMainPanel().setWaitCursor();
+        // }
+        trees = ForesterUtil.readPhylogeniesFromUrl(url, parser);
+      } catch (final MalformedURLException e)
+      {
+        exception = true;
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                MessageManager.formatMessage(
+                        "exception.unable_to_launch_url", new String[]
+                        { url.toString() }),
+                MessageManager.getString("label.invalid_url"),
+                JvOptionPane.ERROR_MESSAGE);
+        System.err.println(e.getLocalizedMessage());
+      } catch (final IOException e)
+      {
+        exception = true;
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                "Could not read from " + url + "\n"
+                        + e.getLocalizedMessage(),
+                "Failed to read tree from " + treeDbClient.getName() + " for "
+                        + identifier,
+                JvOptionPane.ERROR_MESSAGE);
+        System.err.println(e.getLocalizedMessage());
+      } catch (final NumberFormatException e)
+      {
+        exception = true;
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                "Could not read from " + url + "\n"
+                        + e.getLocalizedMessage(),
+                "Failed to read tree from " + treeDbClient.getName() + " for "
+                        + identifier,
+                JvOptionPane.ERROR_MESSAGE);
+        System.err.println(e.getLocalizedMessage());
+      } catch (final Exception e)
+      {
+        exception = true;
+        e.printStackTrace();
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                e.getLocalizedMessage(), "Unexpected Exception",
+                JvOptionPane.ERROR_MESSAGE);
+        System.err.println(e.getLocalizedMessage());
+      }
+      if ((trees != null) && (trees.length > 0))
+      {
+        for (final Phylogeny phylogeny : trees)
+        {
+          if (!phylogeny.isEmpty())
+          {
+            if (treeDbClient.getName().equals(WebserviceUtil.TREE_FAM_NAME))
+            {
+              phylogeny.setRerootable(false);
+              phylogeny.setRooted(true);
+            }
+            if (treeDbClient.getProcessingInstructions() != null)
+            {
+              try
+              {
+                WebserviceUtil.processInstructions(treeDbClient, phylogeny);
+              } catch (final PhyloXmlDataFormatException e)
+              {
+                JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                        "Error:\n" + e.getLocalizedMessage(), "Error",
+                        JvOptionPane.ERROR_MESSAGE);
+              }
+            }
+            if (treeDbClient.getNodeField() != null)
+            {
+              try
+              {
+                PhylogenyMethods.transferNodeNameToField(phylogeny,
+                        treeDbClient.getNodeField(), false);
+              } catch (final PhyloXmlDataFormatException e)
+              {
+                JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                        "Error:\n" + e.getLocalizedMessage(), "Error",
+                        JvOptionPane.ERROR_MESSAGE);
+              }
+            }
+            phylogeny.setIdentifier(
+                    new Identifier(identifier, treeDbClient.getName()));
+            // _main_frame.getJMenuBar().remove(_main_frame.getHelpMenu());
+            // _main_frame.getMenuBarOfMainFrame()
+            // .add(_main_frame.getHelpMenu());
+            // _main_frame.getMainPanel().addPhylogenyInNewTab(phylogeny,
+            // _main_frame.getConfiguration(),
+            // new File(url.getFile()).getName(), url.toString());
+
+            MainFrame aptxApp = createAptxFrame(phylogeny, viewport,
+                    url.getFile());
+            String my_name_for_file = "";
+            if (!ForesterUtil.isEmpty(phylogeny.getName()))
+            {
+              my_name_for_file = new String(phylogeny.getName())
+                      .replaceAll(" ", "_");
+            }
+            else if (phylogeny.getIdentifier() != null)
+            {
+              final StringBuffer sb = new StringBuffer();
+              if (!ForesterUtil
+                      .isEmpty(phylogeny.getIdentifier().getProvider()))
+              {
+                sb.append(phylogeny.getIdentifier().getProvider());
+                sb.append("_");
+              }
+              sb.append(phylogeny.getIdentifier().getValue());
+              my_name_for_file = new String(
+                      sb.toString().replaceAll(" ", "_"));
+            }
+            aptxApp.getMainPanel().getCurrentTreePanel()
+                    .setTreeFile(new File(my_name_for_file));
+            AptxUtil.lookAtSomeTreePropertiesForAptxControlSettings(
+                    phylogeny, aptxApp.getMainPanel().getControlPanel(),
+                    APTX_CONFIG);
+            // _main_frame.getMainPanel().getControlPanel().showWhole();
+
+            aptxApp.activateSaveAllIfNeeded();
+          }
+        }
+      }
+      else if (!exception) // ..what?
+      {
+        JvOptionPane.showMessageDialog(null,
+                ForesterUtil.wordWrap(
+                        "Failed to read in tree(s) from [" + url + "]", 80),
+                "Error", JvOptionPane.ERROR_MESSAGE);
+      }
+      if ((trees != null) && (trees.length > 0))
+      {
+        try
+        {
+          JvOptionPane.showMessageDialog(null,
+                  ForesterUtil.wordWrap("Successfully read in "
+                          + trees.length + " tree(s) from [" + url + "]",
+                          80),
+                  "Success", JvOptionPane.INFORMATION_MESSAGE);
+        } catch (final Exception e)
+        {
+          // Not important if this fails, do nothing.
+        }
+        // _main_frame.getContentPane().repaint();
+      }
+    }
+
+    System.gc();
 
-      bindAptxNodes.associateLeavesToSequences();
-      bindNodesToJalviewSequences(aptxApp, viewport,
-              bindAptxNodes.getAlignmentWithNodes(),
-              bindAptxNodes.getNodesWithAlignment());
 
+    if (Desktop.instance != null)
+    {
+      Desktop.instance.stopLoading();
     }
+    return null;
 
-    return bindFrameToJalview(aptxApp);
 
   }
 
 
 
+
+
   public static MainFrame createAptxFrame(
-          final Phylogeny[] aptxTrees)
+          final Phylogeny aptxTree,
+          final AlignmentViewport jalviewAlignport, String treeTitle)
   {
-    MainFrame aptxApp = Archaeopteryx.createApplication(aptxTrees,
-            APTX_CONFIG, null);
+    Configuration APTX_CONFIG = new Configuration(Cache.getDefault(
+            "APTXCONFIG",
+            Desktop.instance.getClass()
+                    .getResource("/_aptx_jalview_configuration_file.txt")
+                    .toString()),
+            false, false, false);
+    if (APTX_CONFIG == null || APTX_CONFIG.isCouldReadConfigFile() == false)
+    {
+      int keepGoing = JvOptionPane.showConfirmDialog(Desktop.desktop,
+              MessageManager.getString("label.aptx_config_not_found"),
+              MessageManager.formatMessage("label.couldnt_locate",
+                      new String[]
+                      { "_aptx_jalview_configuration_file" }),
+              JvOptionPane.YES_NO_CANCEL_OPTION);
+
+      if (keepGoing == JvOptionPane.CANCEL_OPTION
+              || keepGoing == JvOptionPane.CLOSED_OPTION
+              || keepGoing == JvOptionPane.NO_OPTION)
+      {
+        return null;
+      }
+
+    }
+    MainFrame aptxApp = Archaeopteryx.createApplication(aptxTree,
+            APTX_CONFIG, treeTitle);
+
+
+    LoadedTreeSequenceAssociation bindAptxNodes = new LoadedTreeSequenceAssociation(
+            jalviewAlignport.getAlignment().getSequencesArray(), aptxTree);
+    bindAptxNodes.associateLeavesToSequences();
+
+    bindNodesToJalviewSequences(aptxApp, jalviewAlignport,
+            bindAptxNodes.getAlignmentWithNodes(),
+            bindAptxNodes.getNodesWithAlignment());
+    bindTreeViewFrameToJalview(aptxApp);
+
+    adaptAptxGui(aptxApp);
     return aptxApp;
   }
 
@@ -173,24 +528,107 @@ public final class AptxInit
           final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
           final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
   {
-    return new JalviewBinding(aptxApp, jalviewAlignViewport,
+    JalviewBinding treeBinding = new JalviewBinding(aptxApp,
+            jalviewAlignViewport,
             alignMappedToNodes, nodesMappedToAlign);
+    activeAptx.put(aptxApp, treeBinding);
+    return treeBinding;
   }
 
 
-  public static MainFrame bindFrameToJalview(final MainFrame aptxApp)
+  public static MainFrame bindTreeViewFrameToJalview(
+          final MainFrame aptxApp)
   {
     int width = 400;
     int height = 550;
     aptxApp.setMinimumSize(new Dimension(width, height));
     // aptxApp.setFont(Desktop.instance.getFont());
     // aptxApp.getMainPanel().setFont(Desktop.instance.getFont());
+    String frameTitle = MessageManager.getString("label.aptx_title");
+    File treeFile = aptxApp.getMainPanel().getCurrentTreePanel()
+            .getTreeFile();
+    if (treeFile != null)
+    {
+      frameTitle += MessageManager.formatMessage("label.aptx_title_append",
+              new String[]
+              { treeFile.getAbsolutePath() });
+    }
+    Desktop.addInternalFrame(aptxApp, frameTitle, true, width, height, true,
+            true);
+    return aptxApp;
+
+  }
 
-    Desktop.addInternalFrame(aptxApp, "Archaeopteryx Tree View", true,
-            width, height, true, true);
+  /**
+   * Hides certain redundant Archaeopteryx GUI elements such as the menu items
+   * for reading in trees and adds extra items related to Jalview such as the
+   * tree sorting item.
+   * 
+   * 
+   * @param aptxFrame
+   */
+  private static void adaptAptxGui(MainFrame aptxFrame)
+  {
+    JMenuBar frameBar = aptxFrame.getJMenuBar();
+
+    for (int i = 0; i < frameBar.getMenuCount();i++) {
+      JMenu menu = frameBar.getMenu(i);
+
+      if (menu.getText().contains("File"))
+      {
+        // hide all "Read from ..." and "New" menu items and any Separators that
+        // come directly after them
+        Component previousMenuItem = null;
+        for (Component menuItem : menu.getMenuComponents()) {
+          if (previousMenuItem instanceof JMenuItem)
+          {
+            if (((JMenuItem) previousMenuItem).getText().startsWith("Read")
+                    || ((JMenuItem) previousMenuItem).getText()
+                            .startsWith("New"))
+            {
+              previousMenuItem.setVisible(false);
+
+              if (menuItem instanceof JSeparator)
+              {
+                menuItem.setVisible(false);
+              }
+            }
+          }
+          previousMenuItem = menuItem;
+        }
+      }
+      else if (menu.getText().contains("Inference"))
+      {
+        menu.setVisible(false);
+      }
+      else if (menu.getText().contains("View"))
+      {
+        menu.addSeparator();
+        JMenuItem sortByTree = new JMenuItem("Sort alignment by tree");
+        JMenuItem refreshJalview = new JMenuItem(
+                "Filter alignment to show only currently visible sequences");
+
+        refreshJalview.setFont(menu.getFont());
+
+        menu.add(sortByTree);
+        menu.add(refreshJalview);
+
+        sortByTree.setFont(menu.getFont());
+        sortByTree.setVisible(false); // don't show unless it's actually
+        // possible
+
+        refreshJalview.addActionListener(activeAptx.get(aptxFrame));
+
+
+      }
 
-    return aptxApp;
+    }
+    aptxFrame.validate();
+  }
 
+  public static Map<MainFrame, JalviewBinding> getAllAptxFrames()
+  {
+    return activeAptx;
   }