From 878897fd12216b10828d6ff387f5450029d8b017 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 30 Mar 2017 10:27:28 +0100 Subject: [PATCH] JAL-728 offer choice of substitution matrix for Quality calculation --- resources/lang/Messages.properties | 1 + src/jalview/analysis/Conservation.java | 9 ++- src/jalview/appletgui/APopupMenu.java | 7 +-- src/jalview/gui/AlignFrame.java | 76 ++++++++++++++++++++++++++ src/jalview/jbgui/GAlignFrame.java | 29 ++++++++++ src/jalview/viewmodel/AlignmentViewport.java | 30 +++++----- src/jalview/workers/ConservationThread.java | 29 +++++++++- 7 files changed, 157 insertions(+), 24 deletions(-) diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 6ca43b0..36e807e 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -578,6 +578,7 @@ label.monospaced_fonts_faster_to_render = Monospaced fonts are faster to render label.anti_alias_fonts = Anti-alias Fonts (Slower to render) label.monospaced_font= Monospaced label.quality = Quality +label.quality_label = Alignment Quality based on {0} scores label.maximize_window = Maximize Window label.conservation = Conservation label.consensus = Consensus diff --git a/src/jalview/analysis/Conservation.java b/src/jalview/analysis/Conservation.java index 2b5a8f6..c79a47b 100755 --- a/src/jalview/analysis/Conservation.java +++ b/src/jalview/analysis/Conservation.java @@ -21,7 +21,6 @@ package jalview.analysis; import jalview.analysis.scoremodels.ScoreMatrix; -import jalview.analysis.scoremodels.ScoreModels; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; import jalview.datamodel.ResidueCount; @@ -554,9 +553,9 @@ public class Conservation } // From Alignment.java in jalview118 - public void findQuality() + public void findQuality(ScoreMatrix scoreModel) { - findQuality(0, maxLength - 1, ScoreModels.getInstance().getBlosum62()); + findQuality(0, maxLength - 1, scoreModel); } /** @@ -840,7 +839,7 @@ public class Conservation */ public static Conservation calculateConservation(String name, List seqs, int start, int end, boolean positiveOnly, - int maxPercentGaps, boolean calcQuality) + int maxPercentGaps, boolean calcQuality, ScoreMatrix scoreModel) { Conservation cons = new Conservation(name, seqs, start, end); cons.calculate(); @@ -848,7 +847,7 @@ public class Conservation if (calcQuality) { - cons.findQuality(); + cons.findQuality(scoreModel); } return cons; diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java index 8fd317a..9d4a4b9 100644 --- a/src/jalview/appletgui/APopupMenu.java +++ b/src/jalview/appletgui/APopupMenu.java @@ -1298,10 +1298,9 @@ public class APopupMenu extends java.awt.PopupMenu implements if (conservationColour.getState()) { Conservation conservation = Conservation.calculateConservation( - "Group", sg - .getSequences(ap.av.getHiddenRepSequences()), 0, ap.av - .getAlignment().getWidth(), false, ap.av.getConsPercGaps(), - false); + "Group", sg.getSequences(ap.av.getHiddenRepSequences()), 0, + ap.av.getAlignment().getWidth(), false, + ap.av.getConsPercGaps(), false, null); sg.getGroupColourScheme().setConservation(conservation); SliderPanel.setConservationSlider(ap, sg.cs, sg.getName()); SliderPanel.showConservationSlider(); diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index de1d003..c45167c 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -26,6 +26,10 @@ import jalview.analysis.CrossRef; import jalview.analysis.Dna; import jalview.analysis.ParseProperties; import jalview.analysis.SequenceIdMatcher; +import jalview.analysis.scoremodels.ScoreMatrix; +import jalview.analysis.scoremodels.ScoreModels; +import jalview.api.AlignCalcManagerI; +import jalview.api.AlignCalcWorkerI; import jalview.api.AlignExportSettingI; import jalview.api.AlignViewControllerGuiI; import jalview.api.AlignViewControllerI; @@ -89,6 +93,7 @@ import jalview.schemes.TCoffeeColourScheme; import jalview.util.MessageManager; import jalview.viewmodel.AlignmentViewport; import jalview.viewmodel.ViewportRanges; +import jalview.workers.ConservationThread; import jalview.ws.DBRefFetcher; import jalview.ws.DBRefFetcher.FetchFinishedListenerI; import jalview.ws.jws1.Discoverer; @@ -864,6 +869,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, modifyConservation.setEnabled(!nucleotide && conservationMenuItem.isSelected()); showGroupConservation.setEnabled(!nucleotide); + qualityScoreModel.setEnabled(!nucleotide); showComplementMenuItem.setText(nucleotide ? MessageManager .getString("label.protein") : MessageManager @@ -5639,6 +5645,76 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, ColourMenuHelper.setColourSelected(colourMenu, schemeName); } + + /** + * Repopulates the sub-menu with choice of score matrices each time the menu + * is selected, in case matrices have been added dynamically + */ + @Override + protected void scoreModel_menuSelected() + { + qualityScoreModel.removeAll(); + boolean nucleotide = getViewport().getAlignment().isNucleotide(); + final AlignCalcManagerI calcManager = getViewport().getCalcManager(); + + /* + * which model is currently selected? + */ + String modelName = null; + final List cons = calcManager + .getRegisteredWorkersOfClass(ConservationThread.class); + if (cons == null || cons.isEmpty()) + { + return; + } + for (AlignCalcWorkerI worker : cons) + { + modelName = ((ConservationThread) worker).getScoreModel().getName(); + } + + /* + * repopulate menu + */ + final ScoreModels scoreModels = ScoreModels.getInstance(); + for (final ScoreModelI sm : scoreModels.getModels()) + { + final String name = sm.getName(); + JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(name); + + /* + * if the score model doesn't provide a description, try to look one + * up in the text bundle, falling back on its name + * TODO push this inside ScoreModels? + */ + String tooltip = sm.getDescription(); + if (tooltip == null) + { + tooltip = MessageManager.getStringOrReturn("label.score_model_", + name); + } + menuItem.setToolTipText(tooltip); + menuItem.setSelected(modelName.equals(name)); + if (sm.isProtein() && (sm instanceof ScoreMatrix)) + { + menuItem.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + // set model on ConservationThread, restart thread + for (AlignCalcWorkerI worker : cons) + { + ((ConservationThread) worker) + .setScoreModel((ScoreMatrix) scoreModels + .forName(name)); + } + getViewport().alignmentChanged(alignPanel); + } + }); + qualityScoreModel.add(menuItem); + } + } + } } class PrintThread extends Thread diff --git a/src/jalview/jbgui/GAlignFrame.java b/src/jalview/jbgui/GAlignFrame.java index f7fe1b6..0876eb1 100755 --- a/src/jalview/jbgui/GAlignFrame.java +++ b/src/jalview/jbgui/GAlignFrame.java @@ -187,6 +187,8 @@ public class GAlignFrame extends JInternalFrame protected JCheckBoxMenuItem showGroupConservation = new JCheckBoxMenuItem(); + protected JMenu qualityScoreModel = new JMenu(); + protected JCheckBoxMenuItem showConsensusHistogram = new JCheckBoxMenuItem(); protected JCheckBoxMenuItem showSequenceLogo = new JCheckBoxMenuItem(); @@ -828,6 +830,27 @@ public class GAlignFrame extends JInternalFrame } }); + + qualityScoreModel.setText("Quality Score Model"); // todo i18n + qualityScoreModel.addMenuListener(new MenuListener() + { + @Override + public void menuSelected(MenuEvent e) + { + scoreModel_menuSelected(); + } + + @Override + public void menuDeselected(MenuEvent e) + { + } + + @Override + public void menuCanceled(MenuEvent e) + { + } + }); + showConsensusHistogram.setText(MessageManager .getString("label.show_consensus_histogram")); showConsensusHistogram.addActionListener(new ActionListener() @@ -1789,6 +1812,8 @@ public class GAlignFrame extends JInternalFrame autoAnnMenu.addSeparator(); autoAnnMenu.add(showGroupConservation); autoAnnMenu.add(showGroupConsensus); + autoAnnMenu.addSeparator(); + autoAnnMenu.add(qualityScoreModel); annotationsMenu.add(autoAnnMenu); @@ -1863,6 +1888,10 @@ public class GAlignFrame extends JInternalFrame // selectMenu.add(listenToViewSelections); } + protected void scoreModel_menuSelected() + { + } + /** * Constructs the entries on the Colour menu (but does not add them to the * menu). diff --git a/src/jalview/viewmodel/AlignmentViewport.java b/src/jalview/viewmodel/AlignmentViewport.java index 3547757..7d152ce 100644 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@ -20,17 +20,6 @@ */ package jalview.viewmodel; -import java.awt.Color; -import java.beans.PropertyChangeSupport; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.BitSet; -import java.util.Deque; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; - import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder; import jalview.analysis.Conservation; import jalview.api.AlignCalcManagerI; @@ -62,12 +51,24 @@ import jalview.structure.VamsasSource; import jalview.util.Comparison; import jalview.util.MapList; import jalview.util.MappingUtils; +import jalview.util.MessageManager; import jalview.viewmodel.styles.ViewStyle; import jalview.workers.AlignCalcManager; import jalview.workers.ComplementConsensusThread; import jalview.workers.ConsensusThread; import jalview.workers.StrucConsensusThread; +import java.awt.Color; +import java.beans.PropertyChangeSupport; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Deque; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + /** * base class holding visualization and analysis attributes and common logic for * an active alignment view displayed in the GUI @@ -1859,7 +1860,7 @@ public abstract class AlignmentViewport implements AlignViewportI, { rs.setConservation(Conservation.calculateConservation("All", alignment.getSequences(), 0, alignment.getWidth(), false, - getConsPercGaps(), false)); + getConsPercGaps(), false, null)); } } @@ -1988,8 +1989,9 @@ public abstract class AlignmentViewport implements AlignViewportI, if (quality == null) { quality = new AlignmentAnnotation("Quality", - "Alignment Quality based on Blosum62 scores", - new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH); + MessageManager.formatMessage("label.quality_label", + "Blosum62"), new Annotation[1], 0f, 11f, + AlignmentAnnotation.BAR_GRAPH); quality.hasText = true; quality.autoCalculated = true; alignment.addAnnotation(quality); diff --git a/src/jalview/workers/ConservationThread.java b/src/jalview/workers/ConservationThread.java index 571234c..5cdd28e 100644 --- a/src/jalview/workers/ConservationThread.java +++ b/src/jalview/workers/ConservationThread.java @@ -21,10 +21,13 @@ package jalview.workers; import jalview.analysis.Conservation; +import jalview.analysis.scoremodels.ScoreMatrix; +import jalview.analysis.scoremodels.ScoreModels; import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; +import jalview.util.MessageManager; import java.util.ArrayList; import java.util.List; @@ -40,6 +43,7 @@ public class ConservationThread extends AlignCalcWorker { super(alignViewport, alignPanel); ConsPercGaps = alignViewport.getConsPercGaps(); + setScoreModel(ScoreModels.getInstance().getBlosum62()); } private Conservation cons; @@ -48,6 +52,8 @@ public class ConservationThread extends AlignCalcWorker int alWidth; + private ScoreMatrix scoreModel; + @Override public void run() { @@ -97,7 +103,7 @@ public class ConservationThread extends AlignCalcWorker { cons = Conservation.calculateConservation("All", alignment.getSequences(), 0, alWidth - 1, false, - ConsPercGaps, quality != null); + ConsPercGaps, quality != null, scoreModel); } catch (IndexOutOfBoundsException x) { // probable race condition. just finish and return without any fuss. @@ -144,4 +150,25 @@ public class ConservationThread extends AlignCalcWorker updateResultAnnotation(false); } + + /** + * Sets the substitution matrix to be used in the Quality calculation. This + * method is not thread-safe. + * + * @param model + */ + public void setScoreModel(ScoreMatrix model) + { + scoreModel = model; + if (quality != null) + { + quality.description = MessageManager.formatMessage( + "label.quality_label", model.getName()); + } + } + + public ScoreMatrix getScoreModel() + { + return scoreModel; + } } -- 1.7.10.2