Merge branch 'kjvdh/features/PhylogenyViewer_tabbedsupport' into merge/2_11_2/kjvdh...
[jalview.git] / src / jalview / gui / CalculationChooser.java
index a3878d7..c43d59b 100644 (file)
@@ -27,8 +27,9 @@ import jalview.analysis.scoremodels.ScoreModels;
 import jalview.analysis.scoremodels.SimilarityParams;
 import jalview.api.analysis.ScoreModelI;
 import jalview.api.analysis.SimilarityParamsI;
+import jalview.bin.Cache;
 import jalview.datamodel.SequenceGroup;
-import jalview.ext.archaeopteryx.ArchaeopteryxTreeBuilder;
+import jalview.ext.archaeopteryx.AptxInit;
 import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
@@ -63,10 +64,6 @@ import javax.swing.JRadioButton;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
 
-import org.forester.archaeopteryx.Archaeopteryx;
-import org.forester.archaeopteryx.MainFrame;
-import org.forester.phylogeny.Phylogeny;
-
 /**
  * A dialog where a user can choose and action Tree or PCA calculation options
  */
@@ -112,6 +109,11 @@ public class CalculationChooser extends JPanel
 
   List<String> tips = new ArrayList<>();
 
+  /*
+   * the most recently opened PCA results panel
+   */
+  private PCAPanel pcaPanel;
+
   /**
    * Constructor
    * 
@@ -157,12 +159,15 @@ public class CalculationChooser extends JPanel
     pca = new JRadioButton(
             MessageManager.getString("label.principal_component_analysis"));
     pca.setOpaque(false);
+
     neighbourJoining = new JRadioButton(
             MessageManager.getString("label.tree_calc_nj"));
     neighbourJoining.setSelected(true);
+    neighbourJoining.setOpaque(false);
+
     averageDistance = new JRadioButton(
             MessageManager.getString("label.tree_calc_av"));
-    neighbourJoining.setOpaque(false);
+    averageDistance.setOpaque(false);
 
     JPanel calcChoicePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
     calcChoicePanel.setOpaque(false);
@@ -171,8 +176,8 @@ public class CalculationChooser extends JPanel
     JPanel treePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
     treePanel.setOpaque(false);
 
-    treePanel.setBorder(BorderFactory
-            .createTitledBorder(MessageManager.getString("label.tree")));
+    JvSwingUtils.createTitledBorder(treePanel,
+            MessageManager.getString("label.tree"), true);
 
     // then copy the inset dimensions for the border-less PCA panel
     JPanel pcaBorderless = new JPanel(new FlowLayout(FlowLayout.LEFT));
@@ -272,9 +277,9 @@ public class CalculationChooser extends JPanel
 
     setMinimumSize(new Dimension(325, height - 10));
     String title = MessageManager.getString("label.choose_calculation");
-    if (af.getViewport().viewName != null)
+    if (af.getViewport().getViewName() != null)
     {
-      title = title + " (" + af.getViewport().viewName + ")";
+      title = title + " (" + af.getViewport().getViewName() + ")";
     }
 
     Desktop.addInternalFrame(frame, title, width, height, false);
@@ -292,6 +297,7 @@ public class CalculationChooser extends JPanel
       };
     });
 
+    validateCalcTypes();
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
   }
 
@@ -421,38 +427,40 @@ public class CalculationChooser extends JPanel
     Object curSel = comboBox.getSelectedItem();
     toolTips.clear();
     DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
+    /*
+     * select the score models applicable to the alignment type
+     */
+    boolean nucleotide = af.getViewport().getAlignment().isNucleotide();
+    List<ScoreModelI> models = getApplicableScoreModels(nucleotide,
+            pca.isSelected());
 
     /*
      * now we can actually add entries to the combobox,
      * remembering their descriptions for tooltips
      */
-    ScoreModels scoreModels = ScoreModels.getInstance();
     boolean selectedIsPresent = false;
-    for (ScoreModelI sm : scoreModels.getModels())
+    for (ScoreModelI sm : models)
     {
-      boolean nucleotide = af.getViewport().getAlignment().isNucleotide();
-      if (sm.isDNA() && nucleotide || sm.isProtein() && !nucleotide)
+      if (curSel != null && sm.getName().equals(curSel))
+      {
+        selectedIsPresent = true;
+        curSel = sm.getName();
+      }
+      model.addElement(sm.getName());
+
+      /*
+       * tooltip is description if provided, else text lookup with
+       * fallback on the model name
+       */
+      String tooltip = sm.getDescription();
+      if (tooltip == null)
       {
-        if (curSel != null && sm.getName().equals(curSel))
-        {
-          selectedIsPresent = true;
-          curSel = sm.getName();
-        }
-        model.addElement(sm.getName());
-
-        /*
-         * tooltip is description if provided, else text lookup with
-         * fallback on the model name
-         */
-        String tooltip = sm.getDescription();
-        if (tooltip == null)
-        {
-          tooltip = MessageManager.getStringOrReturn("label.score_model_",
-                  sm.getName());
-        }
-        toolTips.add(tooltip);
+        tooltip = MessageManager.getStringOrReturn("label.score_model_",
+                sm.getName());
       }
+      toolTips.add(tooltip);
     }
+
     if (selectedIsPresent)
     {
       model.setSelectedItem(curSel);
@@ -462,6 +470,47 @@ public class CalculationChooser extends JPanel
   }
 
   /**
+   * Builds a list of score models which are applicable for the alignment and
+   * calculation type (peptide or generic models for protein, nucleotide or
+   * generic models for nucleotide).
+   * <p>
+   * As a special case, includes BLOSUM62 as an extra option for nucleotide PCA.
+   * This is for backwards compatibility with Jalview prior to 2.8 when BLOSUM62
+   * was the only score matrix supported. This is included if property
+   * BLOSUM62_PCA_FOR_NUCLEOTIDE is set to true in the Jalview properties file.
+   * 
+   * @param nucleotide
+   * @param forPca
+   * @return
+   */
+  protected static List<ScoreModelI> getApplicableScoreModels(
+          boolean nucleotide, boolean forPca)
+  {
+    List<ScoreModelI> filtered = new ArrayList<>();
+
+    ScoreModels scoreModels = ScoreModels.getInstance();
+    for (ScoreModelI sm : scoreModels.getModels())
+    {
+      if (!nucleotide && sm.isProtein() || nucleotide && sm.isDNA())
+      {
+        filtered.add(sm);
+      }
+    }
+
+    /*
+     * special case: add BLOSUM62 as last option for nucleotide PCA, 
+     * for backwards compatibility with Jalview < 2.8 (JAL-2962)
+     */
+    if (nucleotide && forPca
+            && Cache.getDefault("BLOSUM62_PCA_FOR_NUCLEOTIDE", false))
+    {
+      filtered.add(scoreModels.getBlosum62());
+    }
+
+    return filtered;
+  }
+
+  /**
    * Open and calculate the selected tree or PCA on 'OK'
    */
   protected void calculate_actionPerformed()
@@ -476,37 +525,33 @@ public class CalculationChooser extends JPanel
     }
     else
     {
+      createTree(substitutionMatrix, params);
+
+
+
+
 
-      String treeAlgo = determineTreeAlgo();
-      TreeCalculator treeCalculator = new TreeCalculator(treeAlgo,
-              substitutionMatrix, params);
-      TreeBuilder calculatedTree = treeCalculator
-              .makeTree(af.getViewport());
-      TreeModel tree = new TreeModel(calculatedTree);
-      openTreePanel(tree, treeAlgo, substitutionMatrix);
-
-      ArchaeopteryxTreeBuilder aptxTreeBuilder = new ArchaeopteryxTreeBuilder();
-      Phylogeny aptxTree = aptxTreeBuilder.buildAptxTree(calculatedTree);
-      MainFrame aptxFrame = Archaeopteryx.createApplication(aptxTree);
-
-      int width = 400;
-      int height = 550;
-      aptxFrame.setMinimumSize(new Dimension(width - 30, height - 50)); // doesn't
-                                                                        // work
-                                                                        // as it
-                                                                        // gets
-                                                                        // overridden
-                                                                        // during
-                                                                        // addInternalFrame?
-
-      Desktop.addInternalFrame(aptxFrame, "Archaeopteryx Tree View",
-              width, height, true);
 
     }
 
     // closeFrame();
   }
 
+  protected void createTree(String substitutionMatrix,
+          SimilarityParamsI params)
+  {
+    String treeAlgo = determineTreeAlgo();
+    TreeCalculator treeCalculator = new TreeCalculator(treeAlgo,
+            substitutionMatrix, params);
+    TreeBuilder calculatedTree = treeCalculator.makeTree(af.getViewport());
+
+    AptxInit.createInstance(calculatedTree);
+
+    TreeModel tree = new TreeModel(calculatedTree);
+    openTreePanel(tree, treeAlgo, substitutionMatrix);
+  }
+
+
   protected String determineTreeAlgo() // to be modified & expanded
   {
     String treeAlgorithm = neighbourJoining.isSelected()
@@ -579,7 +624,13 @@ public class CalculationChooser extends JPanel
               JvOptionPane.WARNING_MESSAGE);
       return;
     }
-    new PCAPanel(af.alignPanel, modelName, params);
+
+    /*
+     * construct the panel and kick off its calculation thread
+     */
+    pcaPanel = new PCAPanel(af.alignPanel, modelName, params);
+    new Thread(pcaPanel).start();
+
   }
 
   /**
@@ -621,7 +672,6 @@ public class CalculationChooser extends JPanel
      */
     boolean matchGap = doPCA ? false : treeMatchGaps;
 
-
     return new SimilarityParams(includeGapGap, matchGap, includeGapResidue,
             matchOnShortestLength);
   }
@@ -638,4 +688,9 @@ public class CalculationChooser extends JPanel
     {
     }
   }
+
+  public PCAPanel getPcaPanel()
+  {
+    return pcaPanel;
+  }
 }