Clover icon

Coverage Report

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