1 package jalview.schemes;
3 import jalview.api.AlignViewportI;
4 import jalview.datamodel.AnnotatedCollectionI;
5 import jalview.datamodel.HiddenMarkovModel;
6 import jalview.datamodel.SequenceI;
7 import jalview.util.ColorUtils;
8 import jalview.util.Comparison;
10 import java.awt.Color;
11 import java.util.List;
15 * Base class for colour schemes based on a selected Hidden Markov Model. The
16 * colour is with reference to an HMM consensus sequence and HMM profile
18 * <li>white for a gap</li>
19 * <li>red for an insertion (position is gapped in the HMM consensus)</li>
20 * <li>orange for negative information content</li>
21 * <li>white to blue for increasing information content</li>
23 * where information content is the log ratio
26 * log(profile match emission probability / residue background probability)
29 * Sub-class implementations use either global ('Uniprot') or local
30 * ('alignment') background frequencies.
35 public abstract class HmmerColourScheme extends ResidueColourScheme
37 private static final Color INSERTION_COLOUR = new Color(230, 0, 0); // reddish
40 * the aligned HMM consensus sequence to use as reference for colouring
42 private List<SequenceI> hmmSeqs=null;
45 private Map<Character, Float> frequencies;
48 * Constructor given a list of Hidden Markov Model consensus sequences. The
49 * first sequence provides the HMM profile from which we can read the emission
50 * probabilities that determine the colour.
54 public HmmerColourScheme(List<SequenceI> hmmSeqs)
56 this.hmmSeqs = hmmSeqs.isEmpty() ? null : hmmSeqs;
59 protected String getAlphabetType()
62 for (SequenceI hmmSeq : hmmSeqs)
66 HiddenMarkovModel hmm = hmmSeq.getHMM();
69 return hmm.getAlphabetType();
73 return ResidueProperties.ALPHABET_AMINO;
77 * Default constructor (required by ColourSchemes.loadColourSchemes)
79 public HmmerColourScheme()
84 public Color findColour(char symbol, int column, SequenceI seq,
85 String consensusResidue, float pid)
87 return findColour(symbol, column);
91 * Returns the colour at a particular symbol at a column in the alignment:
93 * <li>white for a gap</li>
94 * <li>red for an insertion</li>
95 * <li>orange for negative information content</li>
96 * <li>white to blue for increasing information content</li>
103 private Color findColour(char symbol, int column)
105 if (hmmSeqs==null || Comparison.isGap(symbol))
107 // todo: could return probability of seeing a gap ?
110 // locate first hmm with a non-gap at this position
111 for (SequenceI hmmSeq:hmmSeqs)
117 if (!Comparison.isGap(hmmSeq.getCharAt(column)))
124 final double prob = hmmSeq.getHMM()
125 .getMatchEmissionProbability(column, symbol);
129 if (!frequencies.containsKey(symbol))
135 freq = frequencies.get(symbol);
139 * Orange if match emission probability is less than background probability
141 double infoRatio = prob / freq.floatValue();
142 Color colour = Color.ORANGE;
146 * log-scale graduated shade of blue if prob is greater than background
148 float infoLog = (float) Math.log(infoRatio);
149 colour = ColorUtils.getGraduatedColour(infoLog, 0, Color.WHITE,
150 getMaxInformationScore(), Color.blue);
157 return INSERTION_COLOUR;
161 * Answers the maximum possible value of information score (log ratio), for
162 * use in scaling a graduated colour range
166 abstract float getMaxInformationScore();
169 * Answers a new colour scheme instance based on the HMM of the first sequence
170 * in ac that has an HMM
173 public ColourSchemeI getInstance(AlignViewportI viewport,
174 AnnotatedCollectionI ac)
176 return newInstance(ac);
180 * Answers a new instance of the colour scheme for the given HMM
185 protected abstract HmmerColourScheme newInstance(AnnotatedCollectionI ac);
188 public boolean isSimple()
194 * Answers true if the sequence collection has an HMM consensus sequence, else
198 public boolean isApplicableTo(AnnotatedCollectionI ac)
200 return !ac.getHmmSequences().isEmpty();
203 protected Map<Character, Float> getFrequencies()
208 protected void setFrequencies(Map<Character, Float> frequencies)
210 this.frequencies = frequencies;