Clover icon

Coverage Report

  1. Project Clover database Mon Nov 11 2024 20:42:03 GMT
  2. Package jalview.gui

File CalculationChooser.java

 

Coverage histogram

../../img/srcFileCovDistChart1.png
56% of files have more coverage

Code metrics

64
255
29
1
939
600
88
0.35
8.79
29
3.03

Classes

Class Line # Actions
CalculationChooser 80 255 88
0.037356323.7%
 

Contributing tests

This file is covered by 1 test. .

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 = 375;
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 if (ssSources == null)
558    {
559  0 return comboBox;
560    }
561  0 ssSources.add(0, MessageManager.getString("option.ss_providers_all"));
562   
563  0 boolean selectedIsPresent = false;
564  0 for (String source : ssSources)
565    {
566  0 if (curSel != null && source.equals(curSel))
567    {
568  0 selectedIsPresent = true;
569  0 curSel = source;
570    }
571  0 sourcesModel.addElement(source);
572   
573    }
574   
575  0 if (selectedIsPresent)
576    {
577  0 sourcesModel.setSelectedItem(curSel);
578    }
579  0 comboBox.setModel(sourcesModel);
580   
581  0 return comboBox;
582    }
583   
 
584  0 toggle private void updateScoreModels(JComboBox<String> comboBox,
585    List<String> toolTips)
586    {
587  0 Object curSel = comboBox.getSelectedItem();
588  0 toolTips.clear();
589  0 DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
590   
591    /*
592    * select the score models applicable to the alignment type
593    */
594  0 boolean nucleotide = af.getViewport().getAlignment().isNucleotide();
595  0 AlignmentAnnotation[] alignmentAnnotations = af.getViewport()
596    .getAlignment().getAlignmentAnnotation();
597   
598  0 boolean ssPresent = AlignmentUtils
599    .isSecondaryStructurePresent(alignmentAnnotations);
600   
601  0 List<ScoreModelI> models = getApplicableScoreModels(nucleotide,
602    pca.isSelected(), ssPresent, (pasimap.isSelected() || pairwise.isSelected()));
603   
604    /*
605    * now we can actually add entries to the combobox,
606    * remembering their descriptions for tooltips
607    */
608  0 boolean selectedIsPresent = false;
609  0 for (ScoreModelI sm : models)
610    {
611  0 if (curSel != null && sm.getName().equals(curSel))
612    {
613  0 selectedIsPresent = true;
614  0 curSel = sm.getName();
615    }
616  0 model.addElement(sm.getName());
617   
618    /*
619    * tooltip is description if provided, else text lookup with
620    * fallback on the model name
621    */
622  0 String tooltip = sm.getDescription();
623  0 if (tooltip == null)
624    {
625  0 tooltip = MessageManager.getStringOrReturn("label.score_model_",
626    sm.getName());
627    }
628  0 toolTips.add(tooltip);
629    }
630   
631  0 if (selectedIsPresent)
632    {
633  0 model.setSelectedItem(curSel);
634    }
635    // finally, update the model
636  0 comboBox.setModel(model);
637  0 comboBox.setEnabled(model.getSize() > 0);
638   
639    }
640   
641    /**
642    * Builds a list of score models which are applicable for the alignment and
643    * calculation type (peptide or generic models for protein, nucleotide or
644    * generic models for nucleotide).
645    * <p>
646    * As a special case, includes BLOSUM62 as an extra option for nucleotide PCA.
647    * This is for backwards compatibility with Jalview prior to 2.8 when BLOSUM62
648    * was the only score matrix supported. This is included if property
649    * BLOSUM62_PCA_FOR_NUCLEOTIDE is set to true in the Jalview properties file.
650    *
651    * @param nucleotide
652    * @param forPca
653    * @param ssPresent
654    * - include secondary structure similarity model
655    * @param forPasimap
656    * - limit to ScoreMatrix based models - allows use of AlignSeq
657    * @return
658    */
 
659  16 toggle protected static List<ScoreModelI> getApplicableScoreModels(
660    boolean nucleotide, boolean forPca, boolean ssPresent,
661    boolean forPasimap)
662    {
663  16 List<ScoreModelI> filtered = new ArrayList<>();
664   
665  16 ScoreModels scoreModels = ScoreModels.getInstance();
666  16 for (ScoreModelI sm : scoreModels.getModels())
667    {
668  96 if ((!forPasimap || sm instanceof ScoreMatrix)
669    && (!nucleotide && sm.isProtein() || nucleotide && sm.isDNA()
670    || sm.isSecondaryStructure() && ssPresent))
671   
672    {
673  38 filtered.add(sm);
674    }
675    }
676   
677    /*
678    * special case: add BLOSUM62 as last option for nucleotide PCA,
679    * for backwards compatibility with Jalview < 2.8 (JAL-2962)
680    */
681  16 if (!forPasimap && nucleotide && forPca
682    && Cache.getDefault("BLOSUM62_PCA_FOR_NUCLEOTIDE", false))
683    {
684  1 filtered.add(scoreModels.getBlosum62());
685    }
686   
687  16 return filtered;
688    }
689   
 
690  0 toggle protected List<String> getApplicableSecondaryStructureSources()
691    {
692  0 AlignmentAnnotation[] annotations = af.getViewport().getAlignment()
693    .getAlignmentAnnotation();
694   
695  0 List<String> ssSources = AlignmentUtils
696    .extractSSSourceInAlignmentAnnotation(annotations);
697  0 return ssSources;
698    }
699   
700    /**
701    * Open and calculate the selected tree or PCA on 'OK'
702    */
 
703  0 toggle protected void calculate_actionPerformed()
704    {
705  0 boolean doPCA = pca.isSelected();
706  0 boolean doPaSiMap = pasimap.isSelected();
707  0 boolean doPairwise = pairwise.isSelected();
708  0 String modelName = modelNames.getSelectedItem() == null ? ""
709    : modelNames.getSelectedItem().toString();
710   
711  0 String ssSource = null;
712   
713  0 if (modelName.equals(secondaryStructureModelName))
714    {
715  0 Object selectedItem = ssSourceDropdown.getSelectedItem();
716  0 if (selectedItem != null)
717    {
718  0 ssSource = selectedItem.toString();
719    }
720    }
721  0 SimilarityParams params = getSimilarityParameters(doPCA);
722  0 params.setSecondaryStructureSource(ssSource);
723   
724  0 if (doPCA)
725    {
726  0 openPcaPanel(modelName, params);
727    }
728  0 else if (doPaSiMap)
729    {
730  0 openPasimapPanel(modelName, params);
731    }
732  0 else if (doPairwise)
733    {
734  0 openPairwisePanel(modelName, params);
735    }
736    else
737    {
738  0 openTreePanel(modelName, params);
739    }
740   
741  0 closeFrame();
742    }
743   
 
744  0 toggle private void openPairwisePanel(String modelName, SimilarityParamsI params)
745    {
746  0 ScoreModelI sm = ScoreModels.getInstance().getScoreModel(modelName,
747    af.alignPanel);
748  0 if (sm == null || !(sm instanceof ScoreMatrix))
749    {
750  0 return;
751    }
752  0 new Thread(new Runnable()
753    {
 
754  0 toggle @Override
755    public void run()
756    {
757  0 String pairwise_alignment_title = af.formCalculationTitle(
758    MessageManager.getString("action.pairwise_alignment")
759    + " with " + sm.getName(),
760    af.getViewport().getSelectionGroup() != null,
761    af.getTitle());
762  0 JInternalFrame frame = new JInternalFrame();
763  0 frame.setFrameIcon(null);
764  0 frame.setContentPane(
765    new PairwiseAlignPanel(af.getViewport(), (ScoreMatrix) sm));
766  0 Desktop.addInternalFrame(frame, pairwise_alignment_title, 600, 500);
767    }
768    }).start();
769    }
770   
771    /**
772    * Open a new Tree panel on the desktop
773    *
774    * @param modelName
775    * @param params
776    */
 
777  0 toggle protected void openTreePanel(String modelName, SimilarityParamsI params)
778    {
779    /*
780    * gui validation shouldn't allow insufficient sequences here, but leave
781    * this check in in case this method gets exposed programmatically in future
782    */
783  0 AlignViewport viewport = af.getViewport();
784  0 SequenceGroup sg = viewport.getSelectionGroup();
785  0 if (sg != null && sg.getSize() < MIN_TREE_SELECTION)
786    {
787  0 JvOptionPane.showMessageDialog(Desktop.desktop,
788    MessageManager.formatMessage(
789    "label.you_need_at_least_n_sequences",
790    MIN_TREE_SELECTION),
791    MessageManager.getString("label.not_enough_sequences"),
792    JvOptionPane.WARNING_MESSAGE);
793  0 return;
794    }
795   
796  0 String treeType = neighbourJoining.isSelected()
797    ? TreeBuilder.NEIGHBOUR_JOINING
798    : TreeBuilder.AVERAGE_DISTANCE;
799  0 af.newTreePanel(treeType, modelName, params);
800    }
801   
802    /**
803    * Open a new PCA panel on the desktop
804    *
805    * @param modelName
806    * @param params
807    */
 
808  0 toggle protected void openPcaPanel(String modelName, SimilarityParamsI params)
809    {
810  0 AlignViewport viewport = af.getViewport();
811   
812    /*
813    * gui validation shouldn't allow insufficient sequences here, but leave
814    * this check in in case this method gets exposed programmatically in future
815    */
816  0 if (((viewport.getSelectionGroup() != null)
817    && (viewport.getSelectionGroup().getSize() < MIN_PCA_SELECTION)
818    && (viewport.getSelectionGroup().getSize() > 0))
819    || (viewport.getAlignment().getHeight() < MIN_PCA_SELECTION))
820    {
821  0 JvOptionPane.showInternalMessageDialog(this,
822    MessageManager.formatMessage(
823    "label.you_need_at_least_n_sequences",
824    MIN_PCA_SELECTION),
825    MessageManager
826    .getString("label.sequence_selection_insufficient"),
827    JvOptionPane.WARNING_MESSAGE);
828  0 return;
829    }
830   
831    /*
832    * construct the panel and kick off its calculation thread
833    */
834  0 pcaPanel = new PCAPanel(af.alignPanel, modelName, params);
835  0 new Thread(pcaPanel).start();
836   
837    }
838   
839    /**
840    * Open a new PaSiMap panel on the desktop
841    *
842    * @param modelName
843    * @param params
844    */
 
845  0 toggle protected void openPasimapPanel(String modelName,
846    SimilarityParamsI params)
847    {
848  0 AlignViewport viewport = af.getViewport();
849   
850    /*
851    * gui validation shouldn't allow insufficient sequences here, but leave
852    * this check in in case this method gets exposed programmatically in future
853    */
854  0 if (((viewport.getSelectionGroup() != null)
855    && (viewport.getSelectionGroup()
856    .getSize() < MIN_PASIMAP_SELECTION)
857    && (viewport.getSelectionGroup().getSize() > 0))
858    || (viewport.getAlignment()
859    .getHeight() < MIN_PASIMAP_SELECTION))
860    {
861  0 JvOptionPane.showInternalMessageDialog(this,
862    MessageManager.formatMessage(
863    "label.you_need_at_least_n_sequences",
864    MIN_PASIMAP_SELECTION),
865    MessageManager
866    .getString("label.sequence_selection_insufficient"),
867    JvOptionPane.WARNING_MESSAGE);
868  0 return;
869    }
870   
871    /*
872    * construct the panel and kick off its calculation thread
873    */
874  0 pasimapPanel = new PaSiMapPanel(af.alignPanel, modelName);
875  0 new Thread(pasimapPanel).start();
876   
877    }
878   
879    /**
880    *
881    */
 
882  0 toggle protected void closeFrame()
883    {
884  0 try
885    {
886  0 frame.setClosed(true);
887    } catch (PropertyVetoException ex)
888    {
889    }
890    }
891   
892    /**
893    * Returns a data bean holding parameters for similarity (or distance) model
894    * calculation
895    *
896    * @param doPCA
897    * @return
898    */
 
899  0 toggle protected SimilarityParams getSimilarityParameters(boolean doPCA)
900    {
901    // commented out: parameter choices read from gui widgets
902    // SimilarityParamsI params = new SimilarityParams(
903    // includeGappedColumns.isSelected(), matchGaps.isSelected(),
904    // includeGaps.isSelected(), shorterSequence.isSelected());
905   
906  0 boolean includeGapGap = true;
907  0 boolean includeGapResidue = true;
908  0 boolean matchOnShortestLength = false;
909   
910    /*
911    * 'matchGaps' flag is only used in the PID calculation
912    * - set to false for PCA so that PCA using PID reproduces SeqSpace PCA
913    * - set to true for Tree to reproduce Jalview 2.10.1 calculation
914    * - set to false for Tree for a more correct calculation (JAL-374)
915    */
916  0 boolean matchGap = doPCA ? false : treeMatchGaps;
917   
918  0 return new SimilarityParams(includeGapGap, matchGap, includeGapResidue,
919    matchOnShortestLength);
920    }
921   
922    /**
923    * Closes dialog on Close button press
924    */
 
925  0 toggle protected void close_actionPerformed()
926    {
927  0 try
928    {
929  0 frame.setClosed(true);
930    } catch (Exception ex)
931    {
932    }
933    }
934   
 
935  0 toggle public PCAPanel getPcaPanel()
936    {
937  0 return pcaPanel;
938    }
939    }