From 4a1114e5c20bb42ec0bf9fb2a85b54c85ca6c40e Mon Sep 17 00:00:00 2001 From: gmungoc Date: Fri, 23 Mar 2018 10:28:44 +0000 Subject: [PATCH] JAL-2938 extracted base class for Hmmer colour schems --- .../schemes/HMMERAlignmentColourScheme.java | 179 -------------------- ...MERColourScheme.java => HmmerColourScheme.java} | 88 ++++++---- src/jalview/schemes/HmmerGlobalBackground.java | 59 +++++++ src/jalview/schemes/HmmerLocalBackground.java | 81 +++++++++ src/jalview/schemes/JalviewColourScheme.java | 4 +- ...emeTest.java => HmmerGlobalBackgroundTest.java} | 4 +- ...hemeTest.java => HmmerLocalBackgroundTest.java} | 4 +- 7 files changed, 201 insertions(+), 218 deletions(-) delete mode 100644 src/jalview/schemes/HMMERAlignmentColourScheme.java rename src/jalview/schemes/{HMMERColourScheme.java => HmmerColourScheme.java} (62%) create mode 100644 src/jalview/schemes/HmmerGlobalBackground.java create mode 100644 src/jalview/schemes/HmmerLocalBackground.java rename test/jalview/schemes/{HMMERColourSchemeTest.java => HmmerGlobalBackgroundTest.java} (95%) rename test/jalview/schemes/{HMMERAlignmentColourSchemeTest.java => HmmerLocalBackgroundTest.java} (95%) diff --git a/src/jalview/schemes/HMMERAlignmentColourScheme.java b/src/jalview/schemes/HMMERAlignmentColourScheme.java deleted file mode 100644 index 79fc871..0000000 --- a/src/jalview/schemes/HMMERAlignmentColourScheme.java +++ /dev/null @@ -1,179 +0,0 @@ -package jalview.schemes; - -import jalview.datamodel.AnnotatedCollectionI; -import jalview.datamodel.HiddenMarkovModel; -import jalview.datamodel.ResidueCount; -import jalview.datamodel.SequenceCollectionI; -import jalview.datamodel.SequenceI; -import jalview.util.ColorUtils; -import jalview.util.Comparison; - -import java.awt.Color; -import java.util.HashMap; -import java.util.Map; - -/** - * A colour scheme based on a selected Hidden Markov Model. The colour is - * - * where information content is the log ratio - * - *
- *   log(profile match emission probability / residue background probability>
- * 
- * - * using the alignment's background frequencies for residues. - * - * @author tzvanaalten - * - */ -public class HMMERAlignmentColourScheme extends ResidueColourScheme -{ - /* - * the ratio, for each symbol, of its frequency to total symbol count - */ - Map frequency = new HashMap<>(); - - float logTotalCount; - - HiddenMarkovModel hmm; - - /** - * Constructor given a Hidden Markov Model - * - * @param sg - * - * @param markov - */ - public HMMERAlignmentColourScheme(AnnotatedCollectionI sg, - HiddenMarkovModel markov) - { - hmm = markov; - countFrequencies(sg); - } - - /** - * Default constructor (required by ColourSchemes.loadColourSchemes) - */ - public HMMERAlignmentColourScheme() - { - } - - @Override - public Color findColour(char symbol, int position, SequenceI seq, - String consensusResidue, float pid) - { - return findColour(symbol, position); - } - - /** - * Returns the colour at a particular symbol at a column in the alignment: - * - * - * @param symbol - * @param column - * @return - */ - private Color findColour(char symbol, int column) - { - if (hmm == null || Comparison.isGap(symbol)) - { - return Color.white; - } - if (Character.isLowerCase(symbol)) - { - symbol = Character.toUpperCase(symbol); - } - double prob = hmm.getMatchEmissionProbability(column, symbol); - Double freq = frequency.get(symbol); - if (freq == null) - { - return Color.white; - } - if (prob == 0) - { - return new Color(230, 0, 0); - } - double value = Math.log(prob / freq.doubleValue()); - Color colour = null; - if (value > 0) - { - colour = ColorUtils.getGraduatedColour((float) value, 0, - Color.WHITE, logTotalCount, Color.blue); - } - else if (value < 0) - { - return Color.ORANGE; - } - return colour; - } - - @Override - public void alignmentChanged(AnnotatedCollectionI collection, - Map hiddenReps) - { - /* - * ? no need to do anything if alignment is adjusted - * since findColour() handles everything - */ - } - - @Override - public ColourSchemeI getInstance(AnnotatedCollectionI sg, - Map hiddenRepSequences) - { - SequenceI hmmSeq = sg.getHmmConsensus(); - HiddenMarkovModel model = hmmSeq == null ? null : hmmSeq.getHMM(); - return new HMMERAlignmentColourScheme(sg, model); - } - - /** - * Answers true if the sequence collection has an HMM consensus sequence, else - * false - */ - @Override - public boolean isApplicableTo(AnnotatedCollectionI ac) - { - return ac.getHmmConsensus() != null; - } - - @Override - public String getSchemeName() - { - return JalviewColourScheme.HMMERA.toString(); - } - - @Override - public boolean isSimple() - { - return false; - } - - /** - * Counts and stores the relatively frequency of every residue in the - * alignment - * - * @param sg - */ - public void countFrequencies(AnnotatedCollectionI sg) - { - ResidueCount counts = new ResidueCount(sg.getSequences()); - int total = counts.getTotalResidueCount(); // excludes gaps - - for (char symbol : counts.getSymbolCounts().symbols) - { - double freq = counts.getCount(symbol) / (double) total; - frequency.put(symbol, freq); - } - logTotalCount = (float) Math.log(total); - } -} diff --git a/src/jalview/schemes/HMMERColourScheme.java b/src/jalview/schemes/HmmerColourScheme.java similarity index 62% rename from src/jalview/schemes/HMMERColourScheme.java rename to src/jalview/schemes/HmmerColourScheme.java index ee6c873..011c071 100644 --- a/src/jalview/schemes/HMMERColourScheme.java +++ b/src/jalview/schemes/HmmerColourScheme.java @@ -11,7 +11,8 @@ import java.awt.Color; import java.util.Map; /** - * A colour scheme based on a selected Hidden Markov Model. The colour is + * Base class for colour schemes based on a selected Hidden Markov Model. The + * colour is *
    *
  • white for a gap
  • *
  • red for an insertion
  • @@ -21,33 +22,29 @@ import java.util.Map; * where information content is the log ratio * *
    - *   log(profile match emission probability / residue background probability>
    + *   log(profile match emission probability / residue background probability)
      * 
    * - * using global ('Uniprot') background frequencies for residues. + * Sub-class implementations use either global ('Uniprot') or local + * ('alignment') background frequencies. * * @author tzvanaalten - * + * @author gmcarstairs */ -public class HMMERColourScheme extends ResidueColourScheme +public abstract class HmmerColourScheme extends ResidueColourScheme { - /* - * The highest possible log ratio is when match emission probability in - * the HMM model is 1, and background (for W) is 0.0109 giving - * log(1/0.0109) = log(91.743) = 4.519 - */ - private static final float MAX_LOG_RATIO = 4.519f; + private static final Color INSERTION_COLOUR = new Color(230, 0, 0); // reddish - private static final Color REDDISH = new Color(230, 0, 0); + private HiddenMarkovModel hmm; - HiddenMarkovModel hmm; + private Map frequencies; /** * Constructor given a Hidden Markov Model * * @param markov */ - public HMMERColourScheme(HiddenMarkovModel markov) + public HmmerColourScheme(HiddenMarkovModel markov) { hmm = markov; } @@ -55,7 +52,7 @@ public class HMMERColourScheme extends ResidueColourScheme /** * Default constructor (required by ColourSchemes.loadColourSchemes) */ - public HMMERColourScheme() + public HmmerColourScheme() { } @@ -81,7 +78,7 @@ public class HMMERColourScheme extends ResidueColourScheme */ private Color findColour(char symbol, int column) { - if (hmm == null || Comparison.isGap(symbol)) + if (getHmm() == null || Comparison.isGap(symbol)) { return Color.white; } @@ -90,28 +87,27 @@ public class HMMERColourScheme extends ResidueColourScheme symbol = Character.toUpperCase(symbol); } - double prob = hmm.getMatchEmissionProbability(column, symbol); + double prob = getHmm().getMatchEmissionProbability(column, symbol); Float freq = 0f; - String alpha = hmm.getAlphabetType(); - if (!ResidueProperties.backgroundFrequencies.get(alpha) - .containsKey(symbol)) + + if (!frequencies.containsKey(symbol)) { return Color.WHITE; } else { - freq = ResidueProperties.backgroundFrequencies.get(alpha).get(symbol); + freq = frequencies.get(symbol); } if (prob == 0D) { - return REDDISH; + return INSERTION_COLOUR; } double value = Math.log(prob / freq.floatValue()); Color colour = null; if (value > 0) { colour = ColorUtils.getGraduatedColour((float) value, 0, - Color.WHITE, MAX_LOG_RATIO, Color.blue); + Color.WHITE, getMaxInformationScore(), Color.blue); } else if (value < 0) { @@ -120,6 +116,14 @@ public class HMMERColourScheme extends ResidueColourScheme return colour; } + /** + * Answers the maximum possible value of information score (log ratio), for + * use in scaling a graduated colour range + * + * @return + */ + abstract float getMaxInformationScore(); + @Override public void alignmentChanged(AnnotatedCollectionI collection, Map hiddenReps) @@ -132,24 +136,27 @@ public class HMMERColourScheme extends ResidueColourScheme /** * Answers a new colour scheme instance based on the HMM of the first sequence - * in sg that has an HMM + * in ac that has an HMM */ @Override - public ColourSchemeI getInstance(AnnotatedCollectionI sg, + public ColourSchemeI getInstance(AnnotatedCollectionI ac, Map hiddenRepSequences) { - SequenceI hmmSeq = sg.getHmmConsensus(); + SequenceI hmmSeq = ac.getHmmConsensus(); HiddenMarkovModel model = hmmSeq == null ? null : hmmSeq.getHMM(); - HMMERColourScheme colour = new HMMERColourScheme(model); - return colour; + return newInstance(ac, model); } - @Override - public String getSchemeName() - { - return JalviewColourScheme.HMMERU.toString(); - } + /** + * Answers a new instance of the colour scheme for the given HMM + * + * @param ac + * @param model + * @return + */ + protected abstract HmmerColourScheme newInstance(AnnotatedCollectionI ac, + HiddenMarkovModel model); @Override public boolean isSimple() @@ -167,4 +174,19 @@ public class HMMERColourScheme extends ResidueColourScheme return ac.getHmmConsensus() != null; } + protected Map getFrequencies() + { + return frequencies; + } + + protected void setFrequencies(Map frequencies) + { + this.frequencies = frequencies; + } + + protected HiddenMarkovModel getHmm() + { + return hmm; + } + } diff --git a/src/jalview/schemes/HmmerGlobalBackground.java b/src/jalview/schemes/HmmerGlobalBackground.java new file mode 100644 index 0000000..76d77ab --- /dev/null +++ b/src/jalview/schemes/HmmerGlobalBackground.java @@ -0,0 +1,59 @@ +package jalview.schemes; + +import jalview.datamodel.AnnotatedCollectionI; +import jalview.datamodel.HiddenMarkovModel; + +/** + * An HMM colour scheme that uses global ('Uniprot') background frequencies for + * residues + * + * @author tzvanaalten + */ +public class HmmerGlobalBackground extends HmmerColourScheme +{ + /* + * The highest possible log ratio is when match emission probability in + * the HMM model is 1, and background (for W) is 0.0109 giving + * log(1/0.0109) = log(91.743) = 4.519 + */ + private static final float MAX_LOG_RATIO = 4.519f; + + /** + * Constructor given a Hidden Markov Model + * + * @param markov + */ + public HmmerGlobalBackground(HiddenMarkovModel markov) + { + super(markov); + setFrequencies(ResidueProperties.backgroundFrequencies + .get(getHmm().getAlphabetType())); + } + + /** + * Default constructor (required by ColourSchemes.loadColourSchemes) + */ + public HmmerGlobalBackground() + { + } + + @Override + public String getSchemeName() + { + return JalviewColourScheme.HMMERU.toString(); + } + + @Override + protected HmmerColourScheme newInstance(AnnotatedCollectionI ac, + HiddenMarkovModel model) + { + return new HmmerGlobalBackground(model); + } + + @Override + float getMaxInformationScore() + { + return MAX_LOG_RATIO; + } + +} diff --git a/src/jalview/schemes/HmmerLocalBackground.java b/src/jalview/schemes/HmmerLocalBackground.java new file mode 100644 index 0000000..b878b9e --- /dev/null +++ b/src/jalview/schemes/HmmerLocalBackground.java @@ -0,0 +1,81 @@ +package jalview.schemes; + +import jalview.datamodel.AnnotatedCollectionI; +import jalview.datamodel.HiddenMarkovModel; +import jalview.datamodel.ResidueCount; + +import java.util.HashMap; +import java.util.Map; + +/** + * An HMM colour scheme that uses local (alignment or sub-group) background + * frequencies for residues + * + * @author tzvanaalten + */ +public class HmmerLocalBackground extends HmmerColourScheme +{ + float logTotalCount; + + /** + * Constructor given a Hidden Markov Model + * + * @param sg + * + * @param markov + */ + public HmmerLocalBackground(AnnotatedCollectionI sg, + HiddenMarkovModel markov) + { + super(markov); + countFrequencies(sg); + } + + /** + * Default constructor (required by ColourSchemes.loadColourSchemes) + */ + public HmmerLocalBackground() + { + } + + @Override + public String getSchemeName() + { + return JalviewColourScheme.HMMERA.toString(); + } + + /** + * Counts and stores the relative frequency of every residue in the alignment + * + * @param sg + */ + public void countFrequencies(AnnotatedCollectionI sg) + { + Map freqs = new HashMap<>(); + ResidueCount counts = new ResidueCount(sg.getSequences()); + int total = counts.getTotalResidueCount(); // excludes gaps + + for (char symbol : counts.getSymbolCounts().symbols) + { + double freq = counts.getCount(symbol) / (double) total; + freqs.put(symbol, (float) freq); + } + + setFrequencies(freqs); + + logTotalCount = (float) Math.log(total); + } + + @Override + float getMaxInformationScore() + { + return logTotalCount; + } + + @Override + protected HmmerColourScheme newInstance(AnnotatedCollectionI ac, + HiddenMarkovModel model) + { + return new HmmerLocalBackground(ac, model); + } +} diff --git a/src/jalview/schemes/JalviewColourScheme.java b/src/jalview/schemes/JalviewColourScheme.java index 3d6d88d..57ff88d 100644 --- a/src/jalview/schemes/JalviewColourScheme.java +++ b/src/jalview/schemes/JalviewColourScheme.java @@ -43,8 +43,8 @@ public enum JalviewColourScheme PurinePyrimidine("Purine/Pyrimidine", PurinePyrimidineColourScheme.class), RNAHelices("RNA Helices", RNAHelicesColour.class), TCoffee("T-Coffee Scores", TCoffeeColourScheme.class), - HMMERU("HMMER-Uniprot", HMMERColourScheme.class), - HMMERA("HMMER-Alignment", HMMERAlignmentColourScheme.class); + HMMERU("HMMER-Uniprot", HmmerColourScheme.class), + HMMERA("HMMER-Alignment", HmmerLocalBackground.class); // RNAInteraction("RNA Interaction type", RNAInteractionColourScheme.class) private String name; diff --git a/test/jalview/schemes/HMMERColourSchemeTest.java b/test/jalview/schemes/HmmerGlobalBackgroundTest.java similarity index 95% rename from test/jalview/schemes/HMMERColourSchemeTest.java rename to test/jalview/schemes/HmmerGlobalBackgroundTest.java index 9d8093d..b417482 100644 --- a/test/jalview/schemes/HMMERColourSchemeTest.java +++ b/test/jalview/schemes/HmmerGlobalBackgroundTest.java @@ -11,7 +11,7 @@ import java.net.MalformedURLException; import org.testng.annotations.Test; -public class HMMERColourSchemeTest { +public class HmmerGlobalBackgroundTest { @Test(groups = "Functional") public void testFindColour() throws MalformedURLException, IOException @@ -19,7 +19,7 @@ public class HMMERColourSchemeTest { HMMFile file = new HMMFile("test/jalview/io/test_PKinase_hmm.txt", DataSourceType.FILE); - ColourSchemeI scheme = new HMMERColourScheme(file.getHMM()); + ColourSchemeI scheme = new HmmerGlobalBackground(file.getHMM()); /* * 'A' in column 1, node 2, match emission 2.77204 diff --git a/test/jalview/schemes/HMMERAlignmentColourSchemeTest.java b/test/jalview/schemes/HmmerLocalBackgroundTest.java similarity index 95% rename from test/jalview/schemes/HMMERAlignmentColourSchemeTest.java rename to test/jalview/schemes/HmmerLocalBackgroundTest.java index 0907c9a..991adb5 100644 --- a/test/jalview/schemes/HMMERAlignmentColourSchemeTest.java +++ b/test/jalview/schemes/HmmerLocalBackgroundTest.java @@ -15,7 +15,7 @@ import java.net.MalformedURLException; import org.testng.annotations.Test; -public class HMMERAlignmentColourSchemeTest { +public class HmmerLocalBackgroundTest { @Test(groups = "Functional") public void testFindColour() throws MalformedURLException, IOException @@ -34,7 +34,7 @@ public class HMMERAlignmentColourSchemeTest { SequenceI seq1 = new Sequence("seq1", "AAMMMKKKVV"); SequenceI seq2 = new Sequence("seq2", "aAM-QKRSSSL"); AnnotatedCollectionI ac = new Alignment(new SequenceI[] { seq1, seq2 }); - ColourSchemeI scheme = new HMMERAlignmentColourScheme(ac, + ColourSchemeI scheme = new HmmerLocalBackground(ac, file.getHMM()); /* -- 1.7.10.2