Clover icon

Coverage Report

  1. Project Clover database Thu Nov 7 2024 17:01:39 GMT
  2. Package jalview.gui

File CalculationChooser.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
0% of files have more coverage

Code metrics

62
252
29
1
934
595
87
0.35
8.69
29
3

Classes

Class Line # Actions
CalculationChooser 80 252 87
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.gui;
22   
23    import jalview.analysis.TreeBuilder;
24    import jalview.analysis.scoremodels.ScoreModels;
25    import jalview.analysis.scoremodels.SimilarityParams;
26    import jalview.api.analysis.ScoreModelI;
27    import jalview.api.analysis.SimilarityParamsI;
28    import jalview.bin.Cache;
29    import jalview.datamodel.SequenceGroup;
30    import jalview.util.MessageManager;
31    import jalview.util.Platform;
32    import jalview.viewmodel.AlignmentViewport;
33    import java.awt.BorderLayout;
34    import java.awt.Color;
35    import java.awt.Component;
36    import java.awt.Dimension;
37    import java.awt.FlowLayout;
38    import java.awt.Font;
39    import java.awt.GridLayout;
40    import java.awt.Insets;
41    import java.awt.event.ActionEvent;
42    import java.awt.event.ActionListener;
43    import java.awt.event.FocusEvent;
44    import java.awt.event.FocusListener;
45    import java.awt.event.MouseAdapter;
46    import java.awt.event.MouseEvent;
47    import java.beans.PropertyVetoException;
48    import java.util.ArrayList;
49    import java.util.List;
50   
51    import javax.swing.BorderFactory;
52    import javax.swing.ButtonGroup;
53    import javax.swing.DefaultComboBoxModel;
54    import javax.swing.JButton;
55    import javax.swing.JCheckBox;
56    import javax.swing.JComboBox;
57    import javax.swing.JInternalFrame;
58    import javax.swing.JLabel;
59    import javax.swing.JLayeredPane;
60    import javax.swing.JPanel;
61    import javax.swing.JRadioButton;
62    import javax.swing.event.InternalFrameAdapter;
63    import javax.swing.event.InternalFrameEvent;
64   
65    import jalview.analysis.AlignmentUtils;
66    import jalview.analysis.TreeBuilder;
67    import jalview.analysis.scoremodels.ScoreMatrix;
68    import jalview.analysis.scoremodels.ScoreModels;
69    import jalview.analysis.scoremodels.SimilarityParams;
70    import jalview.api.analysis.ScoreModelI;
71    import jalview.api.analysis.SimilarityParamsI;
72    import jalview.bin.Cache;
73    import jalview.datamodel.AlignmentAnnotation;
74    import jalview.datamodel.SequenceGroup;
75    import jalview.util.MessageManager;
76   
77    /**
78    * A dialog where a user can choose and action Tree or PCA calculation options
79    */
 
80    public class CalculationChooser extends JPanel
81    {
82    /*
83    * flag for whether gap matches residue in the PID calculation for a Tree
84    * - true gives Jalview 2.10.1 behaviour
85    * - set to false (using Groovy) for a more correct tree
86    * (JAL-374)
87    */
88    private static boolean treeMatchGaps = true;
89   
90    private static final Font VERDANA_11PT = new Font("Verdana", 0, 11);
91   
92    private static final int MIN_PAIRWISE_SELECTION = 2;
93   
94    private static final int MIN_TREE_SELECTION = 3;
95   
96    private static final int MIN_PCA_SELECTION = 4;
97   
98    private String secondaryStructureModelName;
99   
 
100  0 toggle private void getSecondaryStructureModelName()
101    {
102   
103  0 ScoreModels scoreModels = ScoreModels.getInstance();
104  0 for (ScoreModelI sm : scoreModels.getModels())
105    {
106  0 if (sm.isSecondaryStructure())
107    {
108  0 secondaryStructureModelName = sm.getName();
109    }
110    }
111   
112    }
113   
114    /**
115    * minimum number of sequences needed for PASIMAP is 9 (so each has 8
116    * connections)
117    */
118    private static final int MIN_PASIMAP_SELECTION = 9;
119   
120    AlignFrame af;
121   
122    JRadioButton pairwise;
123   
124    JRadioButton pca;
125   
126    JRadioButton pasimap;
127   
128    JRadioButton neighbourJoining;
129   
130    JRadioButton averageDistance;
131   
132    JComboBox<String> modelNames;
133   
134    JComboBox<String> ssSourceDropdown;
135   
136    JButton calculate;
137   
138    private JInternalFrame frame;
139   
140    private JCheckBox includeGaps;
141   
142    private JCheckBox matchGaps;
143   
144    private JCheckBox includeGappedColumns;
145   
146    private JCheckBox shorterSequence;
147   
148    final ComboBoxTooltipRenderer renderer = new ComboBoxTooltipRenderer();
149   
150    List<String> tips = new ArrayList<>();
151   
152    /*
153    * the most recently opened PCA results panel
154    */
155    private PCAPanel pcaPanel;
156   
157    private PaSiMapPanel pasimapPanel;
158   
159    /**
160    * Constructor
161    *
162    * @param af
163    */
 
164  0 toggle public CalculationChooser(AlignFrame alignFrame)
165    {
166  0 this.af = alignFrame;
167  0 init();
168  0 af.alignPanel.setCalculationDialog(this);
169   
170    }
171   
172    /**
173    * Lays out the panel and adds it to the desktop
174    */
 
175  0 toggle void init()
176    {
177  0 getSecondaryStructureModelName();
178  0 setLayout(new BorderLayout());
179  0 frame = new JInternalFrame();
180  0 frame.setFrameIcon(null);
181  0 frame.setContentPane(this);
182  0 this.setBackground(Color.white);
183  0 frame.addFocusListener(new FocusListener()
184    {
185   
 
186  0 toggle @Override
187    public void focusLost(FocusEvent e)
188    {
189    }
190   
 
191  0 toggle @Override
192    public void focusGained(FocusEvent e)
193    {
194  0 validateCalcTypes();
195    }
196    });
197    /*
198    * Layout consists of 3 or 4 panels:
199    * - first with choice of PCA or tree method NJ or AV
200    * - second with choice of score model
201    * - third with score model parameter options [suppressed]
202    * - fourth with OK and Cancel
203    */
204  0 pca = new JRadioButton(
205    MessageManager.getString("label.principal_component_analysis"));
206  0 pca.setOpaque(false);
207   
208  0 pasimap = new JRadioButton( // create the JRadioButton for pasimap with
209    // label.pasimap as its text
210    MessageManager.getString("label.pasimap"));
211  0 pasimap.setOpaque(false);
212   
213  0 neighbourJoining = new JRadioButton(
214    MessageManager.getString("label.tree_calc_nj"));
215  0 neighbourJoining.setSelected(true);
216  0 neighbourJoining.setOpaque(false);
217   
218  0 averageDistance = new JRadioButton(
219    MessageManager.getString("label.tree_calc_av"));
220  0 averageDistance.setOpaque(false);
221   
222  0 pairwise = new JRadioButton(
223    MessageManager.getString("action.pairwise_alignment"));
224  0 pairwise.setOpaque(false);
225   
226  0 JPanel calcChoicePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
227  0 calcChoicePanel.setOpaque(false);
228   
229    // first create the Tree calculation's border panel
230  0 JPanel treePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
231  0 treePanel.setOpaque(false);
232   
233  0 JvSwingUtils.createTitledBorder(treePanel,
234    MessageManager.getString("label.tree"), true);
235   
236    // then copy the inset dimensions for the border-less PCA panel
237  0 JPanel pcaBorderless = new JPanel(new FlowLayout(FlowLayout.LEFT));
238  0 Insets b = treePanel.getBorder().getBorderInsets(treePanel);
239  0 pcaBorderless.setBorder(
240    BorderFactory.createEmptyBorder(2, b.left, 2, b.right));
241  0 pcaBorderless.setOpaque(false);
242   
243  0 pcaBorderless.add(pca, FlowLayout.LEFT);
244  0 calcChoicePanel.add(pcaBorderless, FlowLayout.LEFT);
245   
246    // create pasimap panel
247  0 JPanel pasimapBorderless = new JPanel(new FlowLayout(FlowLayout.LEFT)); // create
248    // new
249    // JPanel
250    // (button)
251    // for
252    // pasimap
253  0 pasimapBorderless.setBorder(
254    BorderFactory.createEmptyBorder(2, b.left, 2, b.right)); // set
255    // border
256    // (margin)
257    // for
258    // button
259    // (same as
260    // treePanel
261    // and pca)
262  0 pasimapBorderless.setOpaque(false); // false -> stops every pixel inside
263    // border from being painted
264  0 pasimapBorderless.add(pasimap, FlowLayout.LEFT); // add pasimap button to
265    // the JPanel
266  0 if (!Platform.isJS())
267    {
268    // FIXME JAL-4443
269  0 calcChoicePanel.add(pasimapBorderless, FlowLayout.LEFT); // add button
270    // with
271    // border and
272    // everything to
273    // the overall
274    // ChoicePanel
275    }
276   
277  0 treePanel.add(neighbourJoining);
278  0 treePanel.add(averageDistance);
279   
280  0 calcChoicePanel.add(treePanel);
281  0 calcChoicePanel.add(pairwise, FlowLayout.CENTER);
282   
283  0 ButtonGroup calcTypes = new ButtonGroup();
284  0 calcTypes.add(pca);
285  0 if (!Platform.isJS())
286    {
287    // FIXME JAL-4443
288  0 calcTypes.add(pasimap);
289    }
290  0 calcTypes.add(neighbourJoining);
291  0 calcTypes.add(averageDistance);
292  0 calcTypes.add(pairwise);
293   
294  0 ActionListener calcChanged = new ActionListener()
295    {
 
296  0 toggle @Override
297    public void actionPerformed(ActionEvent e)
298    {
299  0 validateCalcTypes();
300    }
301    };
302  0 pca.addActionListener(calcChanged);
303  0 pasimap.addActionListener(calcChanged); // add the calcChanged
304    // ActionListener to pasimap -->
305    // <++> idk
306  0 neighbourJoining.addActionListener(calcChanged);
307  0 averageDistance.addActionListener(calcChanged);
308   
309    // to do
310  0 ssSourceDropdown = buildSSSourcesOptionsList();
311  0 ssSourceDropdown.setVisible(false); // Initially hide the dropdown
312  0 pairwise.addActionListener(calcChanged);
313    /*
314    * score models drop-down - with added tooltips!
315    */
316  0 modelNames = buildModelOptionsList();
317   
318    // Step 3: Show or Hide Dropdown Based on Selection
319  0 modelNames.addActionListener(new ActionListener()
320    {
 
321  0 toggle @Override
322    public void actionPerformed(ActionEvent e)
323    {
324  0 String selectedModel = modelNames.getSelectedItem().toString();
325   
326  0 if (selectedModel.equals(secondaryStructureModelName))
327    {
328  0 ssSourceDropdown.setVisible(true);
329    }
330    else
331    {
332  0 ssSourceDropdown.setVisible(false);
333    }
334    }
335    });
336   
337  0 JPanel scoreModelPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
338  0 scoreModelPanel.setOpaque(false);
339  0 scoreModelPanel.add(modelNames);
340  0 scoreModelPanel.add(ssSourceDropdown);
341   
342    /*
343    * score model parameters
344    */
345  0 JPanel paramsPanel = new JPanel(new GridLayout(5, 1));
346  0 paramsPanel.setOpaque(false);
347  0 includeGaps = new JCheckBox("Include gaps");
348  0 matchGaps = new JCheckBox("Match gaps");
349  0 includeGappedColumns = new JCheckBox("Include gapped columns");
350  0 shorterSequence = new JCheckBox("Match on shorter sequence");
351  0 paramsPanel.add(new JLabel("Pairwise sequence scoring options"));
352  0 paramsPanel.add(includeGaps);
353  0 paramsPanel.add(matchGaps);
354  0 paramsPanel.add(includeGappedColumns);
355  0 paramsPanel.add(shorterSequence);
356   
357    /*
358    * OK / Cancel buttons
359    */
360  0 calculate = new JButton(MessageManager.getString("action.calculate"));
361  0 calculate.setFont(VERDANA_11PT);
362  0 calculate.addActionListener(new java.awt.event.ActionListener()
363    {
 
364  0 toggle @Override
365    public void actionPerformed(ActionEvent e)
366    {
367  0 calculate_actionPerformed();
368    }
369    });
370  0 JButton close = new JButton(MessageManager.getString("action.close"));
371  0 close.setFont(VERDANA_11PT);
372  0 close.addActionListener(new java.awt.event.ActionListener()
373    {
 
374  0 toggle @Override
375    public void actionPerformed(ActionEvent e)
376    {
377  0 close_actionPerformed();
378    }
379    });
380  0 JPanel actionPanel = new JPanel();
381  0 actionPanel.setOpaque(false);
382  0 actionPanel.add(calculate);
383  0 actionPanel.add(close);
384   
385  0 boolean includeParams = false;
386  0 this.add(calcChoicePanel, BorderLayout.CENTER);
387  0 calcChoicePanel.add(scoreModelPanel);
388  0 if (includeParams)
389    {
390  0 scoreModelPanel.add(paramsPanel);
391    }
392  0 this.add(actionPanel, BorderLayout.SOUTH);
393   
394  0 int width = 365;
395  0 int height = includeParams ? 420 : 240;
396   
397  0 setMinimumSize(new Dimension(325, height - 10));
398  0 String title = MessageManager.getString("label.choose_calculation");
399  0 if (af.getViewport().getViewName() != null)
400    {
401  0 title = title + " (" + af.getViewport().getViewName() + ")";
402    }
403   
404  0 Desktop.addInternalFrame(frame, title, width, height, false);
405  0 calcChoicePanel.doLayout();
406  0 revalidate();
407    /*
408    * null the AlignmentPanel's reference to the dialog when it is closed
409    */
410  0 frame.addInternalFrameListener(new InternalFrameAdapter()
411    {
 
412  0 toggle @Override
413    public void internalFrameClosed(InternalFrameEvent evt)
414    {
415  0 af.alignPanel.setCalculationDialog(null);
416    };
417    });
418   
419  0 validateCalcTypes();
420  0 frame.setLayer(JLayeredPane.PALETTE_LAYER);
421    }
422   
423    /**
424    * enable calculations applicable for the current alignment or selection.
425    */
 
426  0 toggle protected void validateCalcTypes()
427    {
428  0 int size = af.getViewport().getAlignment().getHeight();
429  0 if (af.getViewport().getSelectionGroup() != null)
430    {
431  0 size = af.getViewport().getSelectionGroup().getSize();
432    }
433   
434    /*
435    * disable calc options for which there is insufficient input data
436    * return value of true means enabled and selected
437    */
438  0 boolean checkPca = checkEnabled(pca, size, MIN_PCA_SELECTION);
439  0 boolean checkPasimap = checkEnabled(pasimap, size,
440    MIN_PASIMAP_SELECTION); // check if pasimap is enabled and min_size
441    // is fulfilled
442  0 boolean checkNeighbourJoining = checkEnabled(neighbourJoining, size,
443    MIN_TREE_SELECTION);
444  0 boolean checkAverageDistance = checkEnabled(averageDistance, size,
445    MIN_TREE_SELECTION);
446  0 boolean checkPairwise = checkEnabled(pairwise, size,
447    MIN_PAIRWISE_SELECTION);
448   
449  0 if (checkPca || checkPasimap || checkPca || checkNeighbourJoining
450    || checkAverageDistance || checkPairwise)
451    {
452  0 calculate.setToolTipText(null);
453  0 calculate.setEnabled(true);
454    }
455    else
456    {
457  0 calculate.setEnabled(false);
458    }
459  0 updateScoreModels(modelNames, tips);
460    }
461   
462    /**
463    * Check the input and disable a calculation's radio button if necessary. A
464    * tooltip is shown for disabled calculations.
465    *
466    * @param calc
467    * - radio button for the calculation being validated
468    * @param size
469    * - size of input to calculation
470    * @param minsize
471    * - minimum size for calculation
472    * @return true if size >= minsize and calc.isSelected
473    */
 
474  0 toggle private boolean checkEnabled(JRadioButton calc, int size, int minsize)
475    {
476  0 String ttip = MessageManager
477    .formatMessage("label.you_need_at_least_n_sequences", minsize);
478   
479  0 calc.setEnabled(size >= minsize);
480  0 if (!calc.isEnabled())
481    {
482  0 calc.setToolTipText(ttip);
483    }
484    else
485    {
486  0 calc.setToolTipText(null);
487    }
488  0 if (calc.isSelected())
489    {
490  0 modelNames.setEnabled(calc.isEnabled());
491  0 if (calc.isEnabled())
492    {
493  0 return true;
494    }
495    else
496    {
497  0 calculate.setToolTipText(ttip);
498    }
499    }
500  0 return false;
501    }
502   
503    /**
504    * A rather elaborate helper method (blame Swing, not me) that builds a
505    * drop-down list of score models (by name) with descriptions as tooltips.
506    * There is also a tooltip shown for the currently selected item when hovering
507    * over it (without opening the list).
508    */
 
509  0 toggle protected JComboBox<String> buildModelOptionsList()
510    {
511  0 final JComboBox<String> scoreModelsCombo = new JComboBox<>();
512  0 scoreModelsCombo.setRenderer(renderer);
513   
514    /*
515    * show tooltip on mouse over the combobox
516    * note the listener has to be on the components that make up
517    * the combobox, doesn't work if just on the combobox
518    */
519  0 final MouseAdapter mouseListener = new MouseAdapter()
520    {
 
521  0 toggle @Override
522    public void mouseEntered(MouseEvent e)
523    {
524  0 scoreModelsCombo.setToolTipText(
525    tips.get(scoreModelsCombo.getSelectedIndex()));
526    }
527   
 
528  0 toggle @Override
529    public void mouseExited(MouseEvent e)
530    {
531  0 scoreModelsCombo.setToolTipText(null);
532    }
533    };
534  0 for (Component c : scoreModelsCombo.getComponents())
535    {
536  0 c.addMouseListener(mouseListener);
537    }
538   
539  0 updateScoreModels(scoreModelsCombo, tips);
540   
541    /*
542    * set the list of tooltips on the combobox's renderer
543    */
544  0 renderer.setTooltips(tips);
545   
546  0 return scoreModelsCombo;
547    }
548   
 
549  0 toggle private JComboBox<String> buildSSSourcesOptionsList()
550    {
551  0 final JComboBox<String> comboBox = new JComboBox<>();
552  0 Object curSel = comboBox.getSelectedItem();
553  0 DefaultComboBoxModel<String> sourcesModel = new DefaultComboBoxModel<>();
554   
555  0 List<String> ssSources = getApplicableSecondaryStructureSources();
556   
557  0 boolean selectedIsPresent = false;
558  0 for (String source : ssSources)
559    {
560  0 if (curSel != null && source.equals(curSel))
561    {
562  0 selectedIsPresent = true;
563  0 curSel = source;
564    }
565  0 sourcesModel.addElement(source);
566   
567    }
568   
569  0 if (selectedIsPresent)
570    {
571  0 sourcesModel.setSelectedItem(curSel);
572    }
573  0 comboBox.setModel(sourcesModel);
574   
575  0 return comboBox;
576    }
577   
 
578  0 toggle private void updateScoreModels(JComboBox<String> comboBox,
579    List<String> toolTips)
580    {
581  0 Object curSel = comboBox.getSelectedItem();
582  0 toolTips.clear();
583  0 DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
584   
585    /*
586    * select the score models applicable to the alignment type
587    */
588  0 boolean nucleotide = af.getViewport().getAlignment().isNucleotide();
589  0 AlignmentAnnotation[] alignmentAnnotations = af.getViewport()
590    .getAlignment().getAlignmentAnnotation();
591   
592  0 boolean ssPresent = AlignmentUtils
593    .isSecondaryStructurePresent(alignmentAnnotations);
594   
595  0 List<ScoreModelI> models = getApplicableScoreModels(nucleotide,
596    pca.isSelected(), ssPresent, (pasimap.isSelected() || pairwise.isSelected()));
597   
598    /*
599    * now we can actually add entries to the combobox,
600    * remembering their descriptions for tooltips
601    */
602  0 boolean selectedIsPresent = false;
603  0 for (ScoreModelI sm : models)
604    {
605  0 if (curSel != null && sm.getName().equals(curSel))
606    {
607  0 selectedIsPresent = true;
608  0 curSel = sm.getName();
609    }
610  0 model.addElement(sm.getName());
611   
612    /*
613    * tooltip is description if provided, else text lookup with
614    * fallback on the model name
615    */
616  0 String tooltip = sm.getDescription();
617  0 if (tooltip == null)
618    {
619  0 tooltip = MessageManager.getStringOrReturn("label.score_model_",
620    sm.getName());
621    }
622  0 toolTips.add(tooltip);
623    }
624   
625  0 if (selectedIsPresent)
626    {
627  0 model.setSelectedItem(curSel);
628    }
629    // finally, update the model
630  0 comboBox.setModel(model);
631  0 comboBox.setEnabled(model.getSize() > 0);
632   
633    }
634   
635    /**
636    * Builds a list of score models which are applicable for the alignment and
637    * calculation type (peptide or generic models for protein, nucleotide or
638    * generic models for nucleotide).
639    * <p>
640    * As a special case, includes BLOSUM62 as an extra option for nucleotide PCA.
641    * This is for backwards compatibility with Jalview prior to 2.8 when BLOSUM62
642    * was the only score matrix supported. This is included if property
643    * BLOSUM62_PCA_FOR_NUCLEOTIDE is set to true in the Jalview properties file.
644    *
645    * @param nucleotide
646    * @param forPca
647    * @param ssPresent
648    * - include secondary structure similarity model
649    * @param forPasimap
650    * - limit to ScoreMatrix based models - allows use of AlignSeq
651    * @return
652    */
 
653  0 toggle protected static List<ScoreModelI> getApplicableScoreModels(
654    boolean nucleotide, boolean forPca, boolean ssPresent,
655    boolean forPasimap)
656    {
657  0 List<ScoreModelI> filtered = new ArrayList<>();
658   
659  0 ScoreModels scoreModels = ScoreModels.getInstance();
660  0 for (ScoreModelI sm : scoreModels.getModels())
661    {
662  0 if ((!forPasimap || sm instanceof ScoreMatrix)
663    && (!nucleotide && sm.isProtein() || nucleotide && sm.isDNA()
664    || sm.isSecondaryStructure() && ssPresent))
665   
666    {
667  0 filtered.add(sm);
668    }
669    }
670   
671    /*
672    * special case: add BLOSUM62 as last option for nucleotide PCA,
673    * for backwards compatibility with Jalview < 2.8 (JAL-2962)
674    */
675  0 if (!forPasimap && nucleotide && forPca
676    && Cache.getDefault("BLOSUM62_PCA_FOR_NUCLEOTIDE", false))
677    {
678  0 filtered.add(scoreModels.getBlosum62());
679    }
680   
681  0 return filtered;
682    }
683   
 
684  0 toggle protected List<String> getApplicableSecondaryStructureSources()
685    {
686  0 AlignmentAnnotation[] annotations = af.getViewport().getAlignment()
687    .getAlignmentAnnotation();
688   
689  0 List<String> ssSources = AlignmentUtils
690    .getSecondaryStructureSources(annotations);
691    // List<String> ssSources =
692    // AlignmentUtils.extractSSSourceInAlignmentAnnotation(annotations);
693   
694  0 return ssSources;
695    }
696   
697    /**
698    * Open and calculate the selected tree or PCA on 'OK'
699    */
 
700  0 toggle protected void calculate_actionPerformed()
701    {
702  0 boolean doPCA = pca.isSelected();
703  0 boolean doPaSiMap = pasimap.isSelected();
704  0 boolean doPairwise = pairwise.isSelected();
705  0 String modelName = modelNames.getSelectedItem() == null ? ""
706    : modelNames.getSelectedItem().toString();
707  0 String ssSource = "";
708  0 Object selectedItem = ssSourceDropdown.getSelectedItem();
709  0 if (selectedItem != null)
710    {
711  0 ssSource = selectedItem.toString();
712    }
713  0 SimilarityParams params = getSimilarityParameters(doPCA);
714  0 if (ssSource.length() > 0)
715    {
716  0 params.setSecondaryStructureSource(ssSource);
717    }
718   
719  0 if (doPCA)
720    {
721  0 openPcaPanel(modelName, params);
722    }
723  0 else if (doPaSiMap)
724    {
725  0 openPasimapPanel(modelName, params);
726    }
727  0 else if (doPairwise)
728    {
729  0 openPairwisePanel(modelName, params);
730    }
731    else
732    {
733  0 openTreePanel(modelName, params);
734    }
735   
736  0 closeFrame();
737    }
738   
 
739  0 toggle private void openPairwisePanel(String modelName, SimilarityParamsI params)
740    {
741  0 ScoreModelI sm = ScoreModels.getInstance().getScoreModel(modelName,
742    af.alignPanel);
743  0 if (sm == null || !(sm instanceof ScoreMatrix))
744    {
745  0 return;
746    }
747  0 new Thread(new Runnable()
748    {
 
749  0 toggle @Override
750    public void run()
751    {
752  0 String pairwise_alignment_title = af.formCalculationTitle(
753    MessageManager.getString("action.pairwise_alignment")
754    + " with " + sm.getName(),
755    af.getViewport().getSelectionGroup() != null,
756    af.getTitle());
757  0 JInternalFrame frame = new JInternalFrame();
758  0 frame.setFrameIcon(null);
759  0 frame.setContentPane(
760    new PairwiseAlignPanel(af.getViewport(), (ScoreMatrix) sm));
761  0 Desktop.addInternalFrame(frame, pairwise_alignment_title, 600, 500);
762    }
763    }).start();
764    }
765   
766    /**
767    * Open a new Tree panel on the desktop
768    *
769    * @param modelName
770    * @param params
771    */
 
772  0 toggle protected void openTreePanel(String modelName, SimilarityParamsI params)
773    {
774    /*
775    * gui validation shouldn't allow insufficient sequences here, but leave
776    * this check in in case this method gets exposed programmatically in future
777    */
778  0 AlignViewport viewport = af.getViewport();
779  0 SequenceGroup sg = viewport.getSelectionGroup();
780  0 if (sg != null && sg.getSize() < MIN_TREE_SELECTION)
781    {
782  0 JvOptionPane.showMessageDialog(Desktop.desktop,
783    MessageManager.formatMessage(
784    "label.you_need_at_least_n_sequences",
785    MIN_TREE_SELECTION),
786    MessageManager.getString("label.not_enough_sequences"),
787    JvOptionPane.WARNING_MESSAGE);
788  0 return;
789    }
790   
791  0 String treeType = neighbourJoining.isSelected()
792    ? TreeBuilder.NEIGHBOUR_JOINING
793    : TreeBuilder.AVERAGE_DISTANCE;
794  0 af.newTreePanel(treeType, modelName, params);
795    }
796   
797    /**
798    * Open a new PCA panel on the desktop
799    *
800    * @param modelName
801    * @param params
802    */
 
803  0 toggle protected void openPcaPanel(String modelName, SimilarityParamsI params)
804    {
805  0 AlignViewport viewport = af.getViewport();
806   
807    /*
808    * gui validation shouldn't allow insufficient sequences here, but leave
809    * this check in in case this method gets exposed programmatically in future
810    */
811  0 if (((viewport.getSelectionGroup() != null)
812    && (viewport.getSelectionGroup().getSize() < MIN_PCA_SELECTION)
813    && (viewport.getSelectionGroup().getSize() > 0))
814    || (viewport.getAlignment().getHeight() < MIN_PCA_SELECTION))
815    {
816  0 JvOptionPane.showInternalMessageDialog(this,
817    MessageManager.formatMessage(
818    "label.you_need_at_least_n_sequences",
819    MIN_PCA_SELECTION),
820    MessageManager
821    .getString("label.sequence_selection_insufficient"),
822    JvOptionPane.WARNING_MESSAGE);
823  0 return;
824    }
825   
826    /*
827    * construct the panel and kick off its calculation thread
828    */
829  0 pcaPanel = new PCAPanel(af.alignPanel, modelName, params);
830  0 new Thread(pcaPanel).start();
831   
832    }
833   
834    /**
835    * Open a new PaSiMap panel on the desktop
836    *
837    * @param modelName
838    * @param params
839    */
 
840  0 toggle protected void openPasimapPanel(String modelName,
841    SimilarityParamsI params)
842    {
843  0 AlignViewport viewport = af.getViewport();
844   
845    /*
846    * gui validation shouldn't allow insufficient sequences here, but leave
847    * this check in in case this method gets exposed programmatically in future
848    */
849  0 if (((viewport.getSelectionGroup() != null)
850    && (viewport.getSelectionGroup()
851    .getSize() < MIN_PASIMAP_SELECTION)
852    && (viewport.getSelectionGroup().getSize() > 0))
853    || (viewport.getAlignment()
854    .getHeight() < MIN_PASIMAP_SELECTION))
855    {
856  0 JvOptionPane.showInternalMessageDialog(this,
857    MessageManager.formatMessage(
858    "label.you_need_at_least_n_sequences",
859    MIN_PASIMAP_SELECTION),
860    MessageManager
861    .getString("label.sequence_selection_insufficient"),
862    JvOptionPane.WARNING_MESSAGE);
863  0 return;
864    }
865   
866    /*
867    * construct the panel and kick off its calculation thread
868    */
869  0 pasimapPanel = new PaSiMapPanel(af.alignPanel, modelName);
870  0 new Thread(pasimapPanel).start();
871   
872    }
873   
874    /**
875    *
876    */
 
877  0 toggle protected void closeFrame()
878    {
879  0 try
880    {
881  0 frame.setClosed(true);
882    } catch (PropertyVetoException ex)
883    {
884    }
885    }
886   
887    /**
888    * Returns a data bean holding parameters for similarity (or distance) model
889    * calculation
890    *
891    * @param doPCA
892    * @return
893    */
 
894  0 toggle protected SimilarityParams getSimilarityParameters(boolean doPCA)
895    {
896    // commented out: parameter choices read from gui widgets
897    // SimilarityParamsI params = new SimilarityParams(
898    // includeGappedColumns.isSelected(), matchGaps.isSelected(),
899    // includeGaps.isSelected(), shorterSequence.isSelected());
900   
901  0 boolean includeGapGap = true;
902  0 boolean includeGapResidue = true;
903  0 boolean matchOnShortestLength = false;
904   
905    /*
906    * 'matchGaps' flag is only used in the PID calculation
907    * - set to false for PCA so that PCA using PID reproduces SeqSpace PCA
908    * - set to true for Tree to reproduce Jalview 2.10.1 calculation
909    * - set to false for Tree for a more correct calculation (JAL-374)
910    */
911  0 boolean matchGap = doPCA ? false : treeMatchGaps;
912   
913  0 return new SimilarityParams(includeGapGap, matchGap, includeGapResidue,
914    matchOnShortestLength);
915    }
916   
917    /**
918    * Closes dialog on Close button press
919    */
 
920  0 toggle protected void close_actionPerformed()
921    {
922  0 try
923    {
924  0 frame.setClosed(true);
925    } catch (Exception ex)
926    {
927    }
928    }
929   
 
930  0 toggle public PCAPanel getPcaPanel()
931    {
932  0 return pcaPanel;
933    }
934    }