import java.awt.Color;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
+/**
+ * A colour scheme based on a selected Hidden Markov Model. The colour is
+ * <ul>
+ * <li>white for a gap</li>
+ * <li>red for an insertion</li>
+ * <li>orange for negative information content</li>
+ * <li>white to blue for increasing information content</li>
+ * </ul>
+ * where information content is the log ratio
+ *
+ * <pre>
+ * log(profile match emission probability / residue background probability>
+ * </pre>
+ *
+ * using the alignment's background frequencies for residues.
+ *
+ * @author tzvanaalten
+ *
+ */
public class HMMERAlignmentColourScheme extends ResidueColourScheme
{
- Map<Character, Double> backgroundFrequencies = new HashMap<>();
+ /*
+ * the ratio, for each symbol, of its frequency to total symbol count
+ */
+ Map<Character, Double> frequency = new HashMap<>();
- Double maxLLR;
+ float logTotalCount;
HiddenMarkovModel hmm;
- boolean peptideSpecific;
-
- boolean nucleotideSpecific;
-
- public HMMERAlignmentColourScheme(HiddenMarkovModel markov)
+ /**
+ * 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)
{
- if (hmm == null)
- {
- return Color.white;
- }
return findColour(symbol, position);
}
/**
- * Returns the colour at a particular symbol at a column in the alignment.
+ * Returns the colour at a particular symbol at a column in the alignment:
+ * <ul>
+ * <li>white for a gap</li>
+ * <li>red for an insertion</li>
+ * <li>orange for negative information content</li>
+ * <li>white to blue for increasing information content</li>
+ * </ul>
*
* @param symbol
- * @param position
- * @return Red for an insertion, white for a gap, orange for a negative
- * information content, white to blue for increasing information
- * content.
+ * @param column
+ * @return
*/
- private Color findColour(char symbol, int position)
+ private Color findColour(char symbol, int column)
{
-
- if (Comparison.isGap(symbol))
+ if (hmm == null || Comparison.isGap(symbol))
{
return Color.white;
}
{
symbol = Character.toUpperCase(symbol);
}
- Double prob;
- prob = hmm.getMatchEmissionProbability(position, symbol);
- Double freq = backgroundFrequencies.get(symbol);
+ double prob = hmm.getMatchEmissionProbability(column, symbol);
+ Double freq = frequency.get(symbol);
if (freq == null)
{
return Color.white;
{
return new Color(230, 0, 0);
}
- Double value = Math.log(prob / freq);
+ double value = Math.log(prob / freq.doubleValue());
Color colour = null;
if (value > 0)
{
-
- colour = ColorUtils.getGraduatedColour(value.floatValue(), 0,
- Color.WHITE, maxLLR.floatValue(), Color.blue);
+ colour = ColorUtils.getGraduatedColour((float) value, 0,
+ Color.WHITE, logTotalCount, Color.blue);
}
else if (value < 0)
{
return Color.ORANGE;
-
}
return colour;
}
public void alignmentChanged(AnnotatedCollectionI collection,
Map<SequenceI, SequenceCollectionI> hiddenReps)
{
- List<SequenceI> seqs = collection.getSequences();
- for (SequenceI seq : seqs)
- {
- if (seq.isHMMConsensusSequence())
- {
- hmm = seq.getHMM();
- break;
- }
- }
-
- count(collection);
-
+ /*
+ * ? no need to do anything if alignment is adjusted
+ * since findColour() handles everything
+ */
}
@Override
public ColourSchemeI getInstance(AnnotatedCollectionI sg,
Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
{
- HiddenMarkovModel markov = null;
- List<SequenceI> seqs = sg.getSequences();
- for (SequenceI seq : seqs)
- {
- if (seq.getHMM() != null)
- {
- markov = seq.getHMM();
- break;
- }
- }
-
- count(sg);
-
- HMMERAlignmentColourScheme colour = new HMMERAlignmentColourScheme(
- markov);
- return colour;
-
+ return new HMMERAlignmentColourScheme(sg, hmm);
}
@Override
public boolean isApplicableTo(AnnotatedCollectionI ac)
{
- return true;
-
+ return !ac.getHMMConsensusSequences().isEmpty();
}
@Override
public String getSchemeName()
{
-
- return JalviewColourScheme.HMMERA.name();
+ return JalviewColourScheme.HMMERA.toString();
}
@Override
return false;
}
- public void count(AnnotatedCollectionI sg)
+ /**
+ * Counts and stores the relatively frequency of every residue in the
+ * alignment
+ *
+ * @param sg
+ */
+ public void countFrequencies(AnnotatedCollectionI sg)
{
- ResidueCount counts = new ResidueCount();
- for (SequenceI seq : sg.getSequences())
- {
- for (int i = 0; i < seq.getLength(); i++)
- {
- if (!Comparison.isGap(seq.getCharAt(i)))
- {
- counts.add(seq.getCharAt(i));
- }
- }
- }
-
- int total = counts.getTotalCount();
+ ResidueCount counts = new ResidueCount(sg.getSequences());
+ int total = counts.getTotalCount(); // excludes gaps
for (char symbol : counts.getSymbolCounts().symbols)
{
- double count = Double.valueOf(counts.getCount(symbol))
- / Double.valueOf(total);
- backgroundFrequencies.put(symbol, count);
+ double freq = counts.getCount(symbol) / (double) total;
+ frequency.put(symbol, freq);
}
- maxLLR = Math.log(total);
+ logTotalCount = (float) Math.log(total);
}
}
-