JAL-728 offer choice of substitution matrix for Quality calculation features/JAL-728alternateQuality
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 30 Mar 2017 09:27:28 +0000 (10:27 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 30 Mar 2017 09:27:28 +0000 (10:27 +0100)
resources/lang/Messages.properties
src/jalview/analysis/Conservation.java
src/jalview/appletgui/APopupMenu.java
src/jalview/gui/AlignFrame.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/workers/ConservationThread.java

index 6ca43b0..36e807e 100644 (file)
@@ -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
index 2b5a8f6..c79a47b 100755 (executable)
@@ -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<SequenceI> 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;
index 8fd317a..9d4a4b9 100644 (file)
@@ -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();
index de1d003..c45167c 100644 (file)
@@ -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<AlignCalcWorkerI> 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
index f7fe1b6..0876eb1 100755 (executable)
@@ -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).
index 3547757..7d152ce 100644 (file)
  */
 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);
index 571234c..5cdd28e 100644 (file)
 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;
+  }
 }