From fdda06e4e3b668fb08532ba9192c199bb57fb5bd Mon Sep 17 00:00:00 2001 From: TZVanaalten Date: Tue, 11 Jul 2017 14:59:08 +0100 Subject: [PATCH] complete Information Content annotation --- src/jalview/analysis/AAFrequency.java | 3 +- src/jalview/datamodel/HiddenMarkovModel.java | 18 +++-- src/jalview/gui/AnnotationLabels.java | 3 +- src/jalview/renderer/AnnotationRenderer.java | 100 ++++++++++++++++++++++++++ src/jalview/schemes/HMMERColourScheme.java | 63 +++++++++++----- 5 files changed, 164 insertions(+), 23 deletions(-) diff --git a/src/jalview/analysis/AAFrequency.java b/src/jalview/analysis/AAFrequency.java index b806355..514b300 100755 --- a/src/jalview/analysis/AAFrequency.java +++ b/src/jalview/analysis/AAFrequency.java @@ -449,6 +449,7 @@ public class AAFrequency return result; } + /** * Extract a sorted extract of cDNA codon profile data. The returned array * contains @@ -531,7 +532,7 @@ public class AAFrequency for (int col = 0; col < cols; col++) { // todo would prefer a Java bean for consensus data - Hashtable columnHash = new Hashtable(); + Hashtable columnHash = new Hashtable<>(); // #seqs, #ungapped seqs, counts indexed by (codon encoded + 1) int[] codonCounts = new int[66]; codonCounts[0] = alignment.getSequences().size(); diff --git a/src/jalview/datamodel/HiddenMarkovModel.java b/src/jalview/datamodel/HiddenMarkovModel.java index 7c8d075..bcfa1c9 100644 --- a/src/jalview/datamodel/HiddenMarkovModel.java +++ b/src/jalview/datamodel/HiddenMarkovModel.java @@ -36,6 +36,8 @@ public class HiddenMarkovModel Map backgroundFrequencies = new HashMap(); + ProfilesI profiles; + final static String YES = "yes"; @@ -385,7 +387,7 @@ public class HiddenMarkovModel return value; } - public char getConsensus(int columnIndex) + public char getConsensusAtAlignColumn(int columnIndex) { char value; Integer index = findNodeIndex(columnIndex + 1); @@ -771,16 +773,23 @@ public class HiddenMarkovModel { Annotation[] annotations = new Annotation[length]; float max = 0f; - for (int i = 0; i < length; i++) + for (int alignPos = 0; alignPos < length; alignPos++) { - Float content = getInformationContent(i); + Float content = getInformationContent(alignPos); if (content > max) { max = content; } + + Character cons; + cons = getConsensusAtAlignColumn(alignPos); + cons = Character.toUpperCase(cons); + String description = String.format("%.3f", content); description += " bits"; - annotations[i] = new Annotation(null, description, ' ', content); + annotations[alignPos] = new Annotation(cons.toString(), description, + ' ', + content); } AlignmentAnnotation annotation = new AlignmentAnnotation( @@ -815,5 +824,6 @@ public class HiddenMarkovModel return informationContent; } + } diff --git a/src/jalview/gui/AnnotationLabels.java b/src/jalview/gui/AnnotationLabels.java index 9127106..3e23ac0 100755 --- a/src/jalview/gui/AnnotationLabels.java +++ b/src/jalview/gui/AnnotationLabels.java @@ -435,7 +435,8 @@ public class AnnotationLabels extends JPanel implements MouseListener, pop.add(item); } } - else if (label.indexOf("Consensus") > -1) + else if (label.indexOf("Consensus") > -1 + || label.indexOf("Information Content") > -1) { pop.addSeparator(); // av and sequencegroup need to implement same interface for diff --git a/src/jalview/renderer/AnnotationRenderer.java b/src/jalview/renderer/AnnotationRenderer.java index 518c179..640bf45 100644 --- a/src/jalview/renderer/AnnotationRenderer.java +++ b/src/jalview/renderer/AnnotationRenderer.java @@ -29,12 +29,14 @@ import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; import jalview.datamodel.ColumnSelection; import jalview.datamodel.HiddenColumns; +import jalview.datamodel.HiddenMarkovModel; import jalview.datamodel.ProfilesI; import jalview.schemes.ColourSchemeI; import jalview.schemes.NucleotideColourScheme; import jalview.schemes.ResidueProperties; import jalview.schemes.ZappoColourScheme; import jalview.util.Platform; +import jalview.util.QuickSort; import java.awt.BasicStroke; import java.awt.Color; @@ -48,6 +50,7 @@ import java.awt.geom.AffineTransform; import java.awt.image.ImageObserver; import java.util.BitSet; import java.util.Hashtable; +import java.util.List; public class AnnotationRenderer { @@ -57,6 +60,10 @@ public class AnnotationRenderer private static final int CHAR_Z = 'Z'; // 90 + private static final int AMINO = 0; + + private static final int DNA = 1; + /** * flag indicating if timing and redraw parameter info should be output */ @@ -337,6 +344,95 @@ public class AnnotationRenderer av_ignoreGapsConsensus = av.isIgnoreGapsConsensus(); } + public int[] getHMMProfileFor(AlignmentAnnotation aa, int column, + boolean removeBelowBackground) + { + + HiddenMarkovModel hmm; + hmm = aa.getHMM(); + int size = 0; + int alphabet = 0; + String alph = hmm.getAlphabetType(); + if (alph.equals("amino")) + { + size = 20; + alphabet = AMINO; + } + else if (alph.equals("DNA")) + { + size = 4; + alphabet = DNA; + } + + char symbols[] = new char[size]; + int values[] = new int[size]; + + List charList = hmm.getSymbols(); + + int i = 0; + for (char character : charList) + { + symbols[i] = character; + i++; + } + + Integer totalCount = 0; + for (int j = 0; j < size; j++) + { + Double value; + char symbol = symbols[j]; + value = hmm.getMatchEmissionProbability(column, symbol); + double freq; + + if (alphabet == AMINO && removeBelowBackground) + { + freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol); + if (value < freq) + { + value = 0d; + } + } + else if (alphabet == DNA && removeBelowBackground) + { + freq = ResidueProperties.nucleotideBackgroundFrequencies + .get(symbol); + if (value < freq) + { + value = 0d; + } + } + value = value * 10000; + values[j] = value.intValue(); + totalCount += value.intValue(); + } + + QuickSort.sort(values, symbols); + + int[] profile = new int[3 + size * 2]; + + profile[0] = AlignmentAnnotation.SEQUENCE_PROFILE; + profile[1] = size; + profile[2] = totalCount; + + if (totalCount != 0) + { + int arrayPos = 3; + for (int k = size - 1; k >= 0; k--) + { + Double percentage; + Integer value = values[k]; + percentage = (value.doubleValue() / totalCount.doubleValue()) + * 100d; + profile[arrayPos] = symbols[k]; + profile[arrayPos + 1] = percentage.intValue(); + arrayPos += 2; + } + } + + return profile; + + } + /** * Returns profile data; the first element is the profile type, the second is * the number of distinct values, the third the total count, and the remainder @@ -352,6 +448,10 @@ public class AnnotationRenderer // properties/rendering attributes as a global 'alignment group' which holds // all vis settings for the alignment as a whole rather than a subset // + if (aa.label.startsWith("Information")) + { + return getHMMProfileFor(aa, column, true); + } if (aa.autoCalculated && (aa.label.startsWith("Consensus") || aa.label .startsWith("cDNA Consensus"))) diff --git a/src/jalview/schemes/HMMERColourScheme.java b/src/jalview/schemes/HMMERColourScheme.java index b2d0742..a7fc8b8 100644 --- a/src/jalview/schemes/HMMERColourScheme.java +++ b/src/jalview/schemes/HMMERColourScheme.java @@ -1,9 +1,12 @@ package jalview.schemes; +import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AnnotatedCollectionI; import jalview.datamodel.HiddenMarkovModel; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceI; +import jalview.util.ColorUtils; +import jalview.util.Comparison; import java.awt.Color; import java.util.Map; @@ -34,7 +37,7 @@ public class HMMERColourScheme extends ResidueColourScheme { if (hmm ==null) { - return new Color(255, 255, 255); + return Color.white; } return findColour(symbol, position); } @@ -42,46 +45,72 @@ public class HMMERColourScheme extends ResidueColourScheme public Color findColour(char symbol, int position) { + if (Comparison.isGap(symbol)) + { + return Color.white; + } + Double prob; + prob = hmm.getMatchEmissionProbability(position, symbol); + double freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol); + Double value = prob - freq; - Double probability; - probability = hmm.getMatchEmissionProbability(position, symbol); - // Double redModifier = Math.pow(probability, 0.9); - Double doubleGreenModifier; - float greenModifier; - if (probability < 0.5) + Color colour = null; + if (value >= 0) { - doubleGreenModifier = probability; - greenModifier = doubleGreenModifier.floatValue(); + + colour = ColorUtils.getGraduatedColour(value.floatValue(), 0, + Color.WHITE, 1f, Color.green); } - else + else if (value < 0) { - doubleGreenModifier = Math.pow(probability, 1 / 1.9); - greenModifier = doubleGreenModifier.floatValue(); + return Color.YELLOW; + } - // Double blueModifier = Math.pow(probability, 0.9); - return new Color(1f, 1f - greenModifier, 0.f); + return colour; } + + + + + @Override public void alignmentChanged(AnnotatedCollectionI collection, Map hiddenReps) { + AlignmentAnnotation[] annArr = collection.getAlignmentAnnotation(); + for (AlignmentAnnotation ann : annArr) + { + if (ann.label.indexOf("Information Content") > -1) + { + hmm = ann.getHMM(); + } + } - collection.setHMM(hmm); } @Override public ColourSchemeI getInstance(AnnotatedCollectionI sg, Map hiddenRepSequences) { + HiddenMarkovModel markov = null; + AlignmentAnnotation[] annArr = sg.getAlignmentAnnotation(); + for (AlignmentAnnotation ann : annArr) + { + if (ann.label.indexOf("Information Content") > -1) + { + markov = ann.getHMM(); + } + } - HMMERColourScheme markov = new HMMERColourScheme(sg.getHMM()); - return markov; + HMMERColourScheme colour = new HMMERColourScheme(markov); + return colour; + } @Override -- 1.7.10.2