From 1750b2f1dcdb6e7de41d0ef7beda88dc3400afba Mon Sep 17 00:00:00 2001 From: gmungoc Date: Mon, 13 Feb 2017 09:01:54 +0000 Subject: [PATCH] JAL-1632 first cut of Tree chooser dialog and ScoreModels singleton --- resources/lang/Messages.properties | 2 +- src/jalview/analysis/AlignSeq.java | 2 +- src/jalview/analysis/PCA.java | 2 +- .../scoremodels}/ScoreMatrix.java | 8 +- src/jalview/analysis/scoremodels/ScoreModels.java | 68 ++++++++ src/jalview/api/analysis/ScoreModelI.java | 12 ++ src/jalview/datamodel/BinarySequence.java | 2 +- src/jalview/gui/AlignFrame.java | 110 +++--------- src/jalview/gui/TreeChooser.java | 176 ++++++++++++++++++++ src/jalview/jbgui/GAlignFrame.java | 59 +------ src/jalview/schemes/ResidueProperties.java | 11 +- test/jalview/schemes/ScoreMatrixPrinter.java | 1 + 12 files changed, 297 insertions(+), 156 deletions(-) rename src/jalview/{schemes => analysis/scoremodels}/ScoreMatrix.java (96%) create mode 100644 src/jalview/analysis/scoremodels/ScoreModels.java create mode 100644 src/jalview/gui/TreeChooser.java diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index f720f39..7d540f9 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -78,7 +78,7 @@ action.scale_left = Scale Left action.scale_right = Scale Right action.by_tree_order = By Tree Order action.sort = Sort -action.calculate_tree = Calculate Tree +action.calculate_tree = Calculate Tree... action.help = Help action.by_annotation = By Annotation... action.invert_sequence_selection = Invert Sequence Selection diff --git a/src/jalview/analysis/AlignSeq.java b/src/jalview/analysis/AlignSeq.java index 86bf721..061a0a1 100755 --- a/src/jalview/analysis/AlignSeq.java +++ b/src/jalview/analysis/AlignSeq.java @@ -20,13 +20,13 @@ */ package jalview.analysis; +import jalview.analysis.scoremodels.ScoreMatrix; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.Mapping; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceI; import jalview.schemes.ResidueProperties; -import jalview.schemes.ScoreMatrix; import jalview.util.Comparison; import jalview.util.Format; import jalview.util.MapList; diff --git a/src/jalview/analysis/PCA.java b/src/jalview/analysis/PCA.java index eaea7bf..41dbcc0 100755 --- a/src/jalview/analysis/PCA.java +++ b/src/jalview/analysis/PCA.java @@ -20,11 +20,11 @@ */ package jalview.analysis; +import jalview.analysis.scoremodels.ScoreMatrix; import jalview.datamodel.BinarySequence; import jalview.datamodel.BinarySequence.InvalidSequenceTypeException; import jalview.math.Matrix; import jalview.schemes.ResidueProperties; -import jalview.schemes.ScoreMatrix; import java.io.PrintStream; diff --git a/src/jalview/schemes/ScoreMatrix.java b/src/jalview/analysis/scoremodels/ScoreMatrix.java similarity index 96% rename from src/jalview/schemes/ScoreMatrix.java rename to src/jalview/analysis/scoremodels/ScoreMatrix.java index 5e5fa8d..41aef82 100644 --- a/src/jalview/schemes/ScoreMatrix.java +++ b/src/jalview/analysis/scoremodels/ScoreMatrix.java @@ -18,10 +18,10 @@ * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ -package jalview.schemes; +package jalview.analysis.scoremodels; -import jalview.analysis.scoremodels.PairwiseSeqScoreModel; import jalview.api.analysis.ScoreModelI; +import jalview.schemes.ResidueProperties; public class ScoreMatrix extends PairwiseSeqScoreModel implements ScoreModelI @@ -53,7 +53,7 @@ public class ScoreMatrix extends PairwiseSeqScoreModel implements * @param type * 0 for Protein, 1 for NA */ - ScoreMatrix(String name, int[][] matrix, int type) + public ScoreMatrix(String name, int[][] matrix, int type) { this.matrix = matrix; this.type = type; @@ -89,6 +89,7 @@ public class ScoreMatrix extends PairwiseSeqScoreModel implements return getPairwiseScore(A1.charAt(0), A2.charAt(0)); } + @Override public int getPairwiseScore(char c, char d) { int pog = 0; @@ -112,6 +113,7 @@ public class ScoreMatrix extends PairwiseSeqScoreModel implements /** * pretty print the matrix */ + @Override public String toString() { return outputMatrix(false); diff --git a/src/jalview/analysis/scoremodels/ScoreModels.java b/src/jalview/analysis/scoremodels/ScoreModels.java new file mode 100644 index 0000000..4fa6396 --- /dev/null +++ b/src/jalview/analysis/scoremodels/ScoreModels.java @@ -0,0 +1,68 @@ +package jalview.analysis.scoremodels; + +import jalview.api.analysis.ScoreModelI; +import jalview.schemes.ResidueProperties; + +import java.util.Map; +import java.util.TreeMap; + +/** + * A class that can register and serve instances of ScoreModelI + */ +public class ScoreModels +{ + private static ScoreModels instance = new ScoreModels(); + + private Map models; + + public static ScoreModels getInstance() + { + return instance; + } + + /** + * Private constructor to enforce use of singleton. Registers Jalview's + * "built-in" score models: + *
    + *
  • BLOSUM62
  • + *
  • PAM250
  • + *
  • DNA
  • + *
  • Sequence Feature Similarity
  • + *
  • Percentage Identity
  • + *
+ */ + private ScoreModels() + { + /* + * using TreeMap keeps models ordered alphabetically by name + */ + models = new TreeMap(String.CASE_INSENSITIVE_ORDER); + registerScoreModel(new ScoreMatrix("BLOSUM62", + ResidueProperties.BLOSUM62, 0)); + registerScoreModel(new ScoreMatrix("PAM250", ResidueProperties.PAM250, + 0)); + registerScoreModel(new ScoreMatrix("DNA", ResidueProperties.DNA, 1)); + registerScoreModel(new FeatureScoreModel()); + registerScoreModel(new PIDScoreModel()); + } + + public Iterable getModelNames() + { + return models.keySet(); + } + + public ScoreModelI forName(String s) + { + return models.get(s); + } + + public void registerScoreModel(ScoreModelI sm) + { + ScoreModelI sm2 = models.get(sm.getName()); + if (sm2 != null) + { + System.err.println("Warning: replacing score model " + sm2.getName()); + } + models.put(sm.getName(), sm); + } +} diff --git a/src/jalview/api/analysis/ScoreModelI.java b/src/jalview/api/analysis/ScoreModelI.java index 31a1c32..332bba5 100644 --- a/src/jalview/api/analysis/ScoreModelI.java +++ b/src/jalview/api/analysis/ScoreModelI.java @@ -29,8 +29,20 @@ public interface ScoreModelI String getName(); + /** + * Answers true if this model is applicable for nucleotide data (so should be + * shown in menus in that context) + * + * @return + */ boolean isDNA(); + /** + * Answers true if this model is applicable for peptide data (so should be + * shown in menus in that context) + * + * @return + */ boolean isProtein(); } diff --git a/src/jalview/datamodel/BinarySequence.java b/src/jalview/datamodel/BinarySequence.java index ed57dce..a959cc7 100755 --- a/src/jalview/datamodel/BinarySequence.java +++ b/src/jalview/datamodel/BinarySequence.java @@ -20,8 +20,8 @@ */ package jalview.datamodel; +import jalview.analysis.scoremodels.ScoreMatrix; import jalview.schemes.ResidueProperties; -import jalview.schemes.ScoreMatrix; /** * Encode a sequence as a numeric vector using either classic residue binary diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index b5fc817..d6dfd9d 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -82,7 +82,6 @@ import jalview.jbgui.GAlignFrame; import jalview.schemes.ColourSchemeI; import jalview.schemes.ColourSchemes; import jalview.schemes.ResidueColourScheme; -import jalview.schemes.ResidueProperties; import jalview.schemes.TCoffeeColourScheme; import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; @@ -360,7 +359,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, setMenusFromViewport(viewport); buildSortByAnnotationScoresMenu(); - buildTreeMenu(); + calculateTree.addActionListener(new ActionListener() + { + + @Override + public void actionPerformed(ActionEvent e) + { + new TreeChooser(AlignFrame.this); + } + }); buildColourMenu(); if (Desktop.desktop != null) @@ -3580,54 +3587,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, /** * DOCUMENT ME! * - * @param e - * DOCUMENT ME! - */ - @Override - public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e) - { - newTreePanel("AV", "PID", "Average distance tree using PID"); - } - - /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! - */ - @Override - public void neighbourTreeMenuItem_actionPerformed(ActionEvent e) - { - newTreePanel("NJ", "PID", "Neighbour joining tree using PID"); - } - - /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! - */ - @Override - protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e) - { - newTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62"); - } - - /** - * DOCUMENT ME! - * - * @param e - * DOCUMENT ME! - */ - @Override - protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e) - { - newTreePanel("AV", "BL", "Average distance tree using BLOSUM62"); - } - - /** - * DOCUMENT ME! - * * @param type * DOCUMENT ME! * @param pwType @@ -3834,48 +3793,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, * call. Listeners are added to remove the menu item when the treePanel is * closed, and adjust the tree leaf to sequence mapping when the alignment is * modified. - * - * @param treePanel - * Displayed tree window. - * @param title - * SortBy menu item title. */ @Override - public void buildTreeMenu() + public void buildTreeSortMenu() { - calculateTree.removeAll(); - // build the calculate menu - - for (final String type : new String[] { "NJ", "AV" }) - { - String treecalcnm = MessageManager.getString("label.tree_calc_" - + type.toLowerCase()); - for (final String pwtype : ResidueProperties.scoreMatrices.keySet()) - { - JMenuItem tm = new JMenuItem(); - ScoreModelI sm = ResidueProperties.scoreMatrices.get(pwtype); - if (sm.isDNA() == viewport.getAlignment().isNucleotide() - || sm.isProtein() == !viewport.getAlignment() - .isNucleotide()) - { - String smn = MessageManager.getStringOrReturn( - "label.score_model_", sm.getName()); - final String title = MessageManager.formatMessage( - "label.treecalc_title", treecalcnm, smn); - tm.setText(title);// - tm.addActionListener(new java.awt.event.ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - newTreePanel(type, pwtype, title); - } - }); - calculateTree.add(tm); - } - - } - } sortByTreeMenu.removeAll(); List comps = PaintRefresher.components.get(viewport @@ -5699,6 +5620,17 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, ColourMenuHelper.setColourSelected(colourMenu, schemeName); } + + public void newTreePanel(String treeType, ScoreModelI sm) + { + String treecalcnm = MessageManager.getString("label.tree_calc_" + + treeType.toLowerCase()); + String smn = MessageManager.getStringOrReturn("label.score_model_", + sm.getName()); + final String ttl = MessageManager.formatMessage("label.treecalc_title", + treecalcnm, smn); + newTreePanel(treeType, sm.getName(), ttl); + } } class PrintThread extends Thread diff --git a/src/jalview/gui/TreeChooser.java b/src/jalview/gui/TreeChooser.java new file mode 100644 index 0000000..338fbb8 --- /dev/null +++ b/src/jalview/gui/TreeChooser.java @@ -0,0 +1,176 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ +package jalview.gui; + +import jalview.analysis.scoremodels.ScoreModels; +import jalview.api.analysis.ScoreModelI; +import jalview.util.MessageManager; + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; + +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JInternalFrame; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; + +/** + * A dialog to allow a user to select and action Tree calculation options + */ +public class TreeChooser extends JPanel +{ + private static final Font VERDANA_11PT = new Font("Verdana", 0, 11); + + AlignFrame af; + + JRadioButton neighbourJoining; + + JRadioButton averageDistance; + + JComboBox matrixNames; + + private JInternalFrame frame; + + private ButtonGroup treeTypes; + + /** + * Constructor + * + * @param af + */ + public TreeChooser(AlignFrame alignFrame) + { + this.af = alignFrame; + init(); + } + + void init() + { + frame = new JInternalFrame(); + frame.setContentPane(this); + this.setBackground(Color.white); + + neighbourJoining = new JRadioButton( + MessageManager.getString("label.tree_calc_nj")); + neighbourJoining.setOpaque(false); + averageDistance = new JRadioButton( + MessageManager.getString("label.tree_calc_av")); + treeTypes = new ButtonGroup(); + treeTypes.add(neighbourJoining); + treeTypes.add(averageDistance); + neighbourJoining.setSelected(true); + + matrixNames = new JComboBox(); + ScoreModels scoreModels = ScoreModels.getInstance(); + for (String scoreType : scoreModels.getModelNames()) + { + ScoreModelI sm = scoreModels.forName(scoreType); + if (sm.isDNA() == af.getViewport().getAlignment().isNucleotide() + || sm.isProtein() == !af.getViewport().getAlignment() + .isNucleotide()) + { + matrixNames.addItem(sm.getName()); + } + } + + JButton ok = new JButton(MessageManager.getString("action.ok")); + ok.setFont(VERDANA_11PT); + ok.addActionListener(new java.awt.event.ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + ok_actionPerformed(e); + } + }); + + JButton cancel = new JButton(MessageManager.getString("action.cancel")); + cancel.setFont(VERDANA_11PT); + cancel.addActionListener(new java.awt.event.ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + cancel_actionPerformed(e); + } + }); + + JPanel p1 = new JPanel(); + p1.setOpaque(false); + p1.add(neighbourJoining); + p1.add(averageDistance); + this.add(p1); + JPanel p2 = new JPanel(new FlowLayout(FlowLayout.LEFT)); + p2.setOpaque(false); + p2.add(matrixNames, FlowLayout.LEFT); + this.add(p2); + JPanel p3 = new JPanel(); + p3.setOpaque(false); + p3.add(ok); + p3.add(cancel); + this.add(p3); + + Desktop.addInternalFrame(frame, + MessageManager.getString("label.choose_tree"), + 400, 200, false); + + frame.setLayer(JLayeredPane.PALETTE_LAYER); + } + + /** + * Open and calculate the selected tree on 'OK' + * + * @param e + */ + protected void ok_actionPerformed(ActionEvent e) + { + try + { + frame.setClosed(true); + String treeType = neighbourJoining.isSelected() ? "NJ" : "AV"; + ScoreModelI sm = ScoreModels.getInstance().forName( + matrixNames.getSelectedItem().toString()); + af.newTreePanel(treeType, sm); + } catch (Exception ex) + { + } + } + + /** + * Closes dialog on cancel + * + * @param e + */ + protected void cancel_actionPerformed(ActionEvent e) + { + try + { + frame.setClosed(true); + } catch (Exception ex) + { + } + } +} diff --git a/src/jalview/jbgui/GAlignFrame.java b/src/jalview/jbgui/GAlignFrame.java index b39f4a8..97dcfa0 100755 --- a/src/jalview/jbgui/GAlignFrame.java +++ b/src/jalview/jbgui/GAlignFrame.java @@ -129,7 +129,7 @@ public class GAlignFrame extends JInternalFrame protected JMenu sort = new JMenu(); - protected JMenu calculateTree = new JMenu(); + protected JMenuItem calculateTree = new JMenuItem(); protected JCheckBoxMenuItem padGapsMenuitem = new JCheckBoxMenuItem(); @@ -533,26 +533,6 @@ public class GAlignFrame extends JInternalFrame PCAMenuItem_actionPerformed(e); } }); - JMenuItem averageDistanceTreeMenuItem = new JMenuItem( - MessageManager.getString("label.average_distance_identity")); - averageDistanceTreeMenuItem.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - averageDistanceTreeMenuItem_actionPerformed(e); - } - }); - JMenuItem neighbourTreeMenuItem = new JMenuItem( - MessageManager.getString("label.neighbour_joining_identity")); - neighbourTreeMenuItem.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - neighbourTreeMenuItem_actionPerformed(e); - } - }); this.getContentPane().setLayout(new BorderLayout()); alignFrameMenuBar.setFont(new java.awt.Font("Verdana", 0, 11)); @@ -563,27 +543,6 @@ public class GAlignFrame extends JInternalFrame outputTextboxMenu.setText(MessageManager .getString("label.out_to_textbox")); - - JMenuItem avDistanceTreeBlosumMenuItem = new JMenuItem( - MessageManager.getString("label.average_distance_blosum62")); - avDistanceTreeBlosumMenuItem.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - avTreeBlosumMenuItem_actionPerformed(e); - } - }); - JMenuItem njTreeBlosumMenuItem = new JMenuItem( - MessageManager.getString("label.neighbour_blosum62")); - njTreeBlosumMenuItem.addActionListener(new ActionListener() - { - @Override - public void actionPerformed(ActionEvent e) - { - njTreeBlosumMenuItem_actionPerformed(e); - } - }); annotationPanelMenuItem.setActionCommand(""); annotationPanelMenuItem.setText(MessageManager .getString("label.show_annotations")); @@ -1203,7 +1162,7 @@ public class GAlignFrame extends JInternalFrame @Override public void menuSelected(MenuEvent e) { - buildTreeMenu(); + buildTreeSortMenu(); } @Override @@ -2327,22 +2286,10 @@ public class GAlignFrame extends JInternalFrame { } - protected void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e) - { - } - protected void neighbourTreeMenuItem_actionPerformed(ActionEvent e) { } - protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e) - { - } - - protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e) - { - } - protected void conservationMenuItem_actionPerformed(boolean selected) { } @@ -2627,7 +2574,7 @@ public class GAlignFrame extends JInternalFrame } - public void buildTreeMenu() + public void buildTreeSortMenu() { } diff --git a/src/jalview/schemes/ResidueProperties.java b/src/jalview/schemes/ResidueProperties.java index 406814a..c774ebf 100755 --- a/src/jalview/schemes/ResidueProperties.java +++ b/src/jalview/schemes/ResidueProperties.java @@ -22,6 +22,7 @@ package jalview.schemes; import jalview.analysis.scoremodels.FeatureScoreModel; import jalview.analysis.scoremodels.PIDScoreModel; +import jalview.analysis.scoremodels.ScoreMatrix; import jalview.api.analysis.ScoreModelI; import java.awt.Color; @@ -477,7 +478,7 @@ public class ResidueProperties // public static final double hydmax = 1.38; // public static final double hydmin = -2.53; - private static final int[][] BLOSUM62 = { + public static final int[][] BLOSUM62 = { { 4, -1, -2, -2, 0, -1, -1, 0, -2, -1, -1, -1, -1, -2, -1, 1, 0, -3, -2, 0, -2, -1, 0, -4 }, { -1, 5, 0, -2, -3, 1, 0, -2, 0, -3, -2, 2, -1, -3, -2, -1, -1, -3, @@ -527,7 +528,7 @@ public class ResidueProperties { -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, 1 }, }; - static final int[][] PAM250 = { + public static final int[][] PAM250 = { { 2, -2, 0, 0, -2, 0, 0, 1, -1, -1, -2, -1, -1, -3, 1, 1, 1, -6, -3, 0, 0, 0, 0, -8 }, { -2, 6, 0, -1, -4, 1, -1, -3, 2, -2, -3, 3, 0, -4, 0, 0, -1, 2, -4, @@ -603,7 +604,8 @@ public class ResidueProperties // treats T and U identically. R and Y weak equivalence with AG and CTU. // N matches any other base weakly // - static final int[][] DNA = { { 10, -8, -8, -8, -8, 1, 1, 1, -8, 1, 1 }, // A + public static final int[][] DNA = { + { 10, -8, -8, -8, -8, 1, 1, 1, -8, 1, 1 }, // A { -8, 10, -8, -8, -8, 1, 1, -8, 1, 1, 1 }, // C { -8, -8, 10, -8, -8, 1, 1, 1, -8, 1, 1 }, // G { -8, -8, -8, 10, 10, 1, 1, -8, 1, 1, 1 }, // T @@ -1252,7 +1254,8 @@ public class ResidueProperties // scoreMatrices.put("Conservation EnhPos", new // ScoreMatrix("Conservation EnhPos",propMatrixEpos,0)); scoreMatrices.put("PID", new PIDScoreModel()); - scoreMatrices.put("Displayed Features", new FeatureScoreModel()); + scoreMatrices.put("Sequence Feature Similarity", + new FeatureScoreModel()); } private ResidueProperties() diff --git a/test/jalview/schemes/ScoreMatrixPrinter.java b/test/jalview/schemes/ScoreMatrixPrinter.java index a743163..4e7755c 100644 --- a/test/jalview/schemes/ScoreMatrixPrinter.java +++ b/test/jalview/schemes/ScoreMatrixPrinter.java @@ -20,6 +20,7 @@ */ package jalview.schemes; +import jalview.analysis.scoremodels.ScoreMatrix; import jalview.api.analysis.ScoreModelI; import jalview.gui.JvOptionPane; -- 1.7.10.2