Merge branch 'bug/JAL-2592userDefinedScheme' into develop
[jalview.git] / src / jalview / gui / AlignFrame.java
index 9cb9804..f4dd851 100644 (file)
@@ -34,7 +34,7 @@ import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureSettingsControllerI;
 import jalview.api.SplitContainerI;
 import jalview.api.ViewStyleI;
-import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
 import jalview.bin.Cache;
 import jalview.bin.Jalview;
 import jalview.commands.CommandI;
@@ -70,6 +70,7 @@ import jalview.io.FileFormat;
 import jalview.io.FileFormatI;
 import jalview.io.FileFormats;
 import jalview.io.FileLoader;
+import jalview.io.FileParse;
 import jalview.io.FormatAdapter;
 import jalview.io.HtmlSvgOutput;
 import jalview.io.IdentifyFile;
@@ -78,12 +79,12 @@ import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
 import jalview.io.JnetAnnotationMaker;
 import jalview.io.NewickFile;
+import jalview.io.ScoreMatrixFile;
 import jalview.io.TCoffeeScoreFile;
 import jalview.jbgui.GAlignFrame;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemes;
 import jalview.schemes.ResidueColourScheme;
-import jalview.schemes.ResidueProperties;
 import jalview.schemes.TCoffeeColourScheme;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
@@ -166,7 +167,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
   public AlignViewControllerI avc;
 
-  List<AlignmentPanel> alignPanels = new ArrayList<AlignmentPanel>();
+  List<AlignmentPanel> alignPanels = new ArrayList<>();
 
   /**
    * Last format used to load or save alignments in this window
@@ -365,7 +366,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     setMenusFromViewport(viewport);
     buildSortByAnnotationScoresMenu();
-    buildTreeMenu();
+    calculateTree.addActionListener(new ActionListener()
+    {
+
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        openTreePcaDialog();
+      }
+    });
     buildColourMenu();
 
     if (Desktop.desktop != null)
@@ -387,8 +396,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     addKeyListener();
 
-    final List<AlignmentPanel> selviews = new ArrayList<AlignmentPanel>();
-    final List<AlignmentPanel> origview = new ArrayList<AlignmentPanel>();
+    final List<AlignmentPanel> selviews = new ArrayList<>();
+    final List<AlignmentPanel> origview = new ArrayList<>();
     final String menuLabel = MessageManager
             .getString("label.copy_format_from");
     ViewSelectionMenu vsel = new ViewSelectionMenu(menuLabel,
@@ -401,7 +410,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                 origview.clear();
                 origview.add(alignPanel);
                 // make an array of all alignment panels except for this one
-                List<AlignmentPanel> aps = new ArrayList<AlignmentPanel>(
+                List<AlignmentPanel> aps = new ArrayList<>(
                         Arrays.asList(Desktop.getAlignmentPanels(null)));
                 aps.remove(AlignFrame.this.alignPanel);
                 return aps.toArray(new AlignmentPanel[aps.size()]);
@@ -680,26 +689,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           break;
         }
         case KeyEvent.VK_PAGE_UP:
-          if (viewport.getWrapAlignment())
-          {
-            alignPanel.scrollUp(true);
-          }
-          else
-          {
-            alignPanel.setScrollValues(vpRanges.getStartRes(),
-                    2 * vpRanges.getStartSeq() - vpRanges.getEndSeq());
-          }
+          vpRanges.pageUp();
           break;
         case KeyEvent.VK_PAGE_DOWN:
-          if (viewport.getWrapAlignment())
-          {
-            alignPanel.scrollUp(false);
-          }
-          else
-          {
-            alignPanel.setScrollValues(vpRanges.getStartRes(),
-                    vpRanges.getEndSeq());
-          }
+          vpRanges.pageDown();
           break;
         }
       }
@@ -1313,10 +1306,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       alignmentToExport = viewport.getAlignment();
     }
-    alignmentStartEnd = alignmentToExport
-            .getVisibleStartAndEndIndex(viewport.getAlignment()
-                    .getHiddenColumns()
-                    .getListOfCols());
+    alignmentStartEnd = viewport.getAlignment().getHiddenColumns()
+            .getVisibleStartAndEndIndex(alignmentToExport.getWidth());
     AlignmentExportData ed = new AlignmentExportData(alignmentToExport,
             omitHidden, alignmentStartEnd, settings);
     return ed;
@@ -1725,7 +1716,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
   synchronized void slideSequences(boolean right, int size)
   {
-    List<SequenceI> sg = new ArrayList<SequenceI>();
+    List<SequenceI> sg = new ArrayList<>();
     if (viewport.cursorMode)
     {
       sg.add(viewport.getAlignment().getSequenceAt(
@@ -1744,7 +1735,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       return;
     }
 
-    List<SequenceI> invertGroup = new ArrayList<SequenceI>();
+    List<SequenceI> invertGroup = new ArrayList<>();
 
     for (SequenceI seq : viewport.getAlignment().getSequences())
     {
@@ -1877,11 +1868,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     ArrayList<int[]> hiddenColumns = null;
     if (viewport.hasHiddenColumns())
     {
-      hiddenColumns = new ArrayList<int[]>();
-      int hiddenOffset = viewport.getSelectionGroup().getStartRes(), hiddenCutoff = viewport
-              .getSelectionGroup().getEndRes();
-      for (int[] region : viewport.getAlignment().getHiddenColumns()
-              .getListOfCols())
+      hiddenColumns = new ArrayList<>();
+      int hiddenOffset = viewport.getSelectionGroup().getStartRes();
+      int hiddenCutoff = viewport.getSelectionGroup().getEndRes();
+      ArrayList<int[]> hiddenRegions = viewport.getAlignment()
+              .getHiddenColumns().getHiddenColumnsCopy();
+      for (int[] region : hiddenRegions)
       {
         if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff)
         {
@@ -1987,7 +1979,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       }
 
       int alwidth = 0;
-      ArrayList<Integer> newGraphGroups = new ArrayList<Integer>();
+      ArrayList<Integer> newGraphGroups = new ArrayList<>();
       int fgroup = -1;
 
       if (newAlignment)
@@ -2819,7 +2811,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    */
   protected List<String> getExistingViewNames(List<Component> comps)
   {
-    List<String> existingNames = new ArrayList<String>();
+    List<String> existingNames = new ArrayList<>();
     for (Component comp : comps)
     {
       if (comp instanceof AlignmentPanel)
@@ -2953,7 +2945,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void showAllColumns_actionPerformed(ActionEvent e)
   {
     viewport.showAllHiddenColumns();
-    repaint();
+    alignPanel.paintAlignment(true);
     viewport.sendSelection();
   }
 
@@ -2961,7 +2953,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   public void hideSelSequences_actionPerformed(ActionEvent e)
   {
     viewport.hideAllSelectedSeqs();
-    // alignPanel.paintAlignment(true);
   }
 
   /**
@@ -3208,10 +3199,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
     alignPanel.paintAlignment(true);
-    if (alignPanel.getOverviewPanel() != null)
-    {
-      alignPanel.getOverviewPanel().updateOverviewImage();
-    }
   }
 
   /**
@@ -3267,11 +3254,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
 
     JInternalFrame frame = new JInternalFrame();
-    OverviewPanel overview = new OverviewPanel(alignPanel);
+    final OverviewPanel overview = new OverviewPanel(alignPanel);
     frame.setContentPane(overview);
     Desktop.addInternalFrame(frame, MessageManager.formatMessage(
             "label.overview_params", new Object[] { this.getTitle() }),
-            frame.getWidth(), frame.getHeight());
+            true, frame.getWidth(), frame.getHeight(), true, true);
     frame.pack();
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
@@ -3280,6 +3267,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       public void internalFrameClosed(
               javax.swing.event.InternalFrameEvent evt)
       {
+        overview.dispose();
         alignPanel.setOverviewPanel(null);
       };
     });
@@ -3337,7 +3325,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
      * 'User Defined' opens a panel to configure or load a
      * user-defined colour scheme
      */
-    if (ResidueColourScheme.USER_DEFINED.equals(name))
+    if (ResidueColourScheme.USER_DEFINED_MENU.equals(name))
     {
       new UserDefinedColours(alignPanel);
       return;
@@ -3446,7 +3434,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   {
     SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
     AlignmentSorter.sortByPID(viewport.getAlignment(), viewport
-            .getAlignment().getSequenceAt(0), null);
+            .getAlignment().getSequenceAt(0));
     addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
             viewport.getAlignment()));
     alignPanel.paintAlignment(true);
@@ -3540,35 +3528,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void PCAMenuItem_actionPerformed(ActionEvent e)
-  {
-    if (((viewport.getSelectionGroup() != null)
-            && (viewport.getSelectionGroup().getSize() < 4) && (viewport
-            .getSelectionGroup().getSize() > 0))
-            || (viewport.getAlignment().getHeight() < 4))
-    {
-      JvOptionPane
-              .showInternalMessageDialog(
-                      this,
-                      MessageManager
-                              .getString("label.principal_component_analysis_must_take_least_four_input_sequences"),
-                      MessageManager
-                              .getString("label.sequence_selection_insufficient"),
-                      JvOptionPane.WARNING_MESSAGE);
-
-      return;
-    }
-
-    new PCAPanel(alignPanel);
-  }
-
   @Override
   public void autoCalculate_actionPerformed(ActionEvent e)
   {
@@ -3593,83 +3552,24 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
-  {
-    newTreePanel("AV", "PID", "Average distance tree using PID");
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
-  {
-    newTreePanel("NJ", "PID", "Neighbour joining tree using PID");
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
-  {
-    newTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
-  }
-
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param e
-   *          DOCUMENT ME!
-   */
-  @Override
-  protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
-  {
-    newTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
-  }
-
-  /**
-   * DOCUMENT ME!
+   * Constructs a tree panel and adds it to the desktop
    * 
    * @param type
-   *          DOCUMENT ME!
-   * @param pwType
-   *          DOCUMENT ME!
-   * @param title
-   *          DOCUMENT ME!
+   *          tree type (NJ or AV)
+   * @param modelName
+   *          name of score model used to compute the tree
+   * @param options
+   *          parameters for the distance or similarity calculation
    */
-  void newTreePanel(String type, String pwType, String title)
+  void newTreePanel(String type, String modelName, SimilarityParamsI options)
   {
+    String frameTitle = "";
     TreePanel tp;
 
+    boolean onSelection = false;
     if (viewport.getSelectionGroup() != null
             && viewport.getSelectionGroup().getSize() > 0)
     {
-      if (viewport.getSelectionGroup().getSize() < 3)
-      {
-        JvOptionPane
-                .showMessageDialog(
-                        Desktop.desktop,
-                        MessageManager
-                                .getString("label.you_need_more_two_sequences_selected_build_tree"),
-                        MessageManager
-                                .getString("label.not_enough_sequences"),
-                        JvOptionPane.WARNING_MESSAGE);
-        return;
-      }
-
       SequenceGroup sg = viewport.getSelectionGroup();
 
       /* Decide if the selection is a column region */
@@ -3689,45 +3589,29 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           return;
         }
       }
-
-      title = title + " on region";
-      tp = new TreePanel(alignPanel, type, pwType);
+      onSelection = true;
     }
     else
     {
-      // are the visible sequences aligned?
-      if (!viewport.getAlignment().isAligned(false))
-      {
-        JvOptionPane
-                .showMessageDialog(
-                        Desktop.desktop,
-                        MessageManager
-                                .getString("label.sequences_must_be_aligned_before_creating_tree"),
-                        MessageManager
-                                .getString("label.sequences_not_aligned"),
-                        JvOptionPane.WARNING_MESSAGE);
-
-        return;
-      }
-
       if (viewport.getAlignment().getHeight() < 2)
       {
         return;
       }
-
-      tp = new TreePanel(alignPanel, type, pwType);
     }
 
-    title += " from ";
+    tp = new TreePanel(alignPanel, type, modelName, options);
+    frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
+
+    frameTitle += " from ";
 
     if (viewport.viewName != null)
     {
-      title += viewport.viewName + " of ";
+      frameTitle += viewport.viewName + " of ";
     }
 
-    title += this.title;
+    frameTitle += this.title;
 
-    Desktop.addInternalFrame(tp, title, 600, 500);
+    Desktop.addInternalFrame(tp, frameTitle, 600, 500);
   }
 
   /**
@@ -3849,53 +3733,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * call. Listeners are added to remove the menu item when the treePanel is
    * closed, and adjust the tree leaf to sequence mapping when the alignment is
    * modified.
-   * 
-   * @param treePanel
-   *          Displayed tree window.
-   * @param title
-   *          SortBy menu item title.
    */
   @Override
-  public void buildTreeMenu()
+  public void buildTreeSortMenu()
   {
-    calculateTree.removeAll();
-    // build the calculate menu
-
-    for (final String type : new String[] { "NJ", "AV" })
-    {
-      String treecalcnm = MessageManager.getString("label.tree_calc_"
-              + type.toLowerCase());
-      for (final String pwtype : ResidueProperties.scoreMatrices.keySet())
-      {
-        JMenuItem tm = new JMenuItem();
-        ScoreModelI sm = ResidueProperties.scoreMatrices.get(pwtype);
-        if (sm.isDNA() == viewport.getAlignment().isNucleotide()
-                || sm.isProtein() == !viewport.getAlignment()
-                        .isNucleotide())
-        {
-          String smn = MessageManager.getStringOrReturn(
-                  "label.score_model_", sm.getName());
-          final String title = MessageManager.formatMessage(
-                  "label.treecalc_title", treecalcnm, smn);
-          tm.setText(title);//
-          tm.addActionListener(new java.awt.event.ActionListener()
-          {
-            @Override
-            public void actionPerformed(ActionEvent e)
-            {
-              newTreePanel(type, pwtype, title);
-            }
-          });
-          calculateTree.add(tm);
-        }
-
-      }
-    }
     sortByTreeMenu.removeAll();
 
     List<Component> comps = PaintRefresher.components.get(viewport
             .getSequenceSetId());
-    List<TreePanel> treePanels = new ArrayList<TreePanel>();
+    List<TreePanel> treePanels = new ArrayList<>();
     for (Component comp : comps)
     {
       if (comp instanceof TreePanel)
@@ -4041,13 +3887,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
     if (value == JalviewFileChooser.APPROVE_OPTION)
     {
-      String choice = chooser.getSelectedFile().getPath();
-      jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
-      jalview.io.NewickFile fin = null;
+      String filePath = chooser.getSelectedFile().getPath();
+      Cache.setProperty("LAST_DIRECTORY", filePath);
+      NewickFile fin = null;
       try
       {
-        fin = new NewickFile(choice, DataSourceType.FILE);
-        viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
+        fin = new NewickFile(filePath, DataSourceType.FILE);
+        viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
       } catch (Exception ex)
       {
         JvOptionPane
@@ -4069,25 +3915,19 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
-  public TreePanel ShowNewickTree(NewickFile nf, String title)
+  public TreePanel showNewickTree(NewickFile nf, String treeTitle)
   {
-    return ShowNewickTree(nf, title, 600, 500, 4, 5);
+    return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
   }
 
-  public TreePanel ShowNewickTree(NewickFile nf, String title,
-          AlignmentView input)
-  {
-    return ShowNewickTree(nf, title, input, 600, 500, 4, 5);
-  }
-
-  public TreePanel ShowNewickTree(NewickFile nf, String title, int w,
+  public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
           int h, int x, int y)
   {
-    return ShowNewickTree(nf, title, null, w, h, x, y);
+    return showNewickTree(nf, treeTitle, null, w, h, x, y);
   }
 
   /**
-   * Add a treeviewer for the tree extracted from a newick file object to the
+   * Add a treeviewer for the tree extracted from a Newick file object to the
    * current alignment view
    * 
    * @param nf
@@ -4106,7 +3946,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    *          position
    * @return TreePanel handle
    */
-  public TreePanel ShowNewickTree(NewickFile nf, String title,
+  public TreePanel showNewickTree(NewickFile nf, String treeTitle,
           AlignmentView input, int w, int h, int x, int y)
   {
     TreePanel tp = null;
@@ -4117,7 +3957,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
       if (nf.getTree() != null)
       {
-        tp = new TreePanel(alignPanel, "FromFile", title, nf, input);
+        tp = new TreePanel(alignPanel, nf, treeTitle, input);
 
         tp.setSize(w, h);
 
@@ -4126,7 +3966,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           tp.setLocation(x, y);
         }
 
-        Desktop.addInternalFrame(tp, title, w, h);
+        Desktop.addInternalFrame(tp, treeTitle, w, h);
       }
     } catch (Exception ex)
     {
@@ -4161,7 +4001,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       @Override
       public void run()
       {
-        final List<JMenuItem> legacyItems = new ArrayList<JMenuItem>();
+        final List<JMenuItem> legacyItems = new ArrayList<>();
         try
         {
           // System.err.println("Building ws menu again "
@@ -4176,7 +4016,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           // TODO: group services by location as well as function and/or
           // introduce
           // object broker mechanism.
-          final Vector<JMenu> wsmenu = new Vector<JMenu>();
+          final Vector<JMenu> wsmenu = new Vector<>();
           final IProgressIndicator af = me;
 
           /*
@@ -4544,8 +4384,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     // Java's Transferable for native dnd
     evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
     Transferable t = evt.getTransferable();
-    List<String> files = new ArrayList<String>();
-    List<DataSourceType> protocols = new ArrayList<DataSourceType>();
+    List<String> files = new ArrayList<>();
+    List<DataSourceType> protocols = new ArrayList<>();
 
     try
     {
@@ -4565,8 +4405,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
         /**
          * Object[] { String,SequenceI}
          */
-        ArrayList<Object[]> filesmatched = new ArrayList<Object[]>();
-        ArrayList<String> filesnotmatched = new ArrayList<String>();
+        ArrayList<Object[]> filesmatched = new ArrayList<>();
+        ArrayList<String> filesnotmatched = new ArrayList<>();
         for (int i = 0; i < files.size(); i++)
         {
           String file = files.get(i).toString();
@@ -4699,10 +4539,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   /**
-   * Attempt to load a "dropped" file or URL string: First by testing whether
-   * it's an Annotation file, then a JNet file, and finally a features file. If
-   * all are false then the user may have dropped an alignment file onto this
-   * AlignFrame.
+   * Attempt to load a "dropped" file or URL string, by testing in turn for
+   * <ul>
+   * <li>an Annotation file</li>
+   * <li>a JNet file</li>
+   * <li>a features file</li>
+   * <li>else try to interpret as an alignment file</li>
+   * </ul>
    * 
    * @param file
    *          either a filename or a URL string.
@@ -4776,7 +4619,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
           {
             format = new IdentifyFile().identify(file, sourceType);
           }
-          if (FileFormat.Jnet.equals(format))
+          if (FileFormat.ScoreMatrix == format)
+          {
+            ScoreMatrixFile sm = new ScoreMatrixFile(new FileParse(file,
+                    sourceType));
+            sm.parse();
+            // todo: i18n this message
+            statusBar
+                    .setText(MessageManager.formatMessage(
+                            "label.successfully_loaded_matrix",
+                            sm.getMatrixName()));
+          }
+          else if (FileFormat.Jnet.equals(format))
           {
             JPredFile predictions = new JPredFile(file, sourceType);
             new JnetAnnotationMaker();
@@ -5543,7 +5397,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     {
       return;
     }
-    List<SequenceI> cdnaSeqs = new ArrayList<SequenceI>();
+    List<SequenceI> cdnaSeqs = new ArrayList<>();
     for (SequenceI aaSeq : alignment.getSequences())
     {
       for (AlignedCodonFrame acf : mappings)
@@ -5711,6 +5565,18 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
     ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
   }
+
+  /**
+   * Open a dialog (if not already open) that allows the user to select and
+   * calculate PCA or Tree analysis
+   */
+  protected void openTreePcaDialog()
+  {
+    if (alignPanel.getCalculationDialog() == null)
+    {
+      new CalculationChooser(AlignFrame.this);
+    }
+  }
 }
 
 class PrintThread extends Thread