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.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 global ('Uniprot') background frequencies for residues.
+ *
+ * @author tzvanaalten
+ *
+ */
public 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;
- AnnotatedCollectionI alignment;
+ private static final Color REDDISH = new Color(230, 0, 0);
HiddenMarkovModel hmm;
-
- boolean peptideSpecific;
-
- boolean nucleotideSpecific;
+ /**
+ * Constructor given a Hidden Markov Model
+ *
+ * @param markov
+ */
public HMMERColourScheme(HiddenMarkovModel markov)
{
hmm = markov;
}
+
+ /**
+ * Default constructor (required by ColourSchemes.loadColourSchemes)
+ */
public HMMERColourScheme()
{
-
}
@Override
public Color findColour(char symbol, int position, SequenceI seq,
String consensusResidue, float pid)
{
- if (hmm ==null)
- {
- return new Color(255, 255, 255);
- }
return findColour(symbol, position);
}
- public Color findColour(char symbol, int position)
+ /**
+ * 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 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 probability;
- probability = hmm.getMatchEmissionProbability(position, symbol);
- // Double redModifier = Math.pow(probability, 0.9);
- Double doubleGreenModifier;
- float greenModifier;
- if (probability < 0.5)
+ double prob = hmm.getMatchEmissionProbability(column, symbol);
+ Float freq = 0f;
+ String alpha = hmm.getAlphabetType();
+ if (!ResidueProperties.backgroundFrequencies.get(alpha)
+ .containsKey(symbol))
{
- doubleGreenModifier = probability;
- greenModifier = doubleGreenModifier.floatValue();
+ return Color.WHITE;
}
else
{
- doubleGreenModifier = Math.pow(probability, 1 / 1.9);
- greenModifier = doubleGreenModifier.floatValue();
+ freq = ResidueProperties.backgroundFrequencies.get(alpha).get(symbol);
}
- // Double blueModifier = Math.pow(probability, 0.9);
- return new Color(1f, 1f - greenModifier, 0.f);
-
+ if (prob == 0D)
+ {
+ return REDDISH;
+ }
+ 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);
+ }
+ else if (value < 0)
+ {
+ return Color.ORANGE;
+ }
+ return colour;
}
@Override
public void alignmentChanged(AnnotatedCollectionI collection,
Map<SequenceI, SequenceCollectionI> hiddenReps)
{
-
- collection.setHMM(hmm);
+ /*
+ * ? no need to do anything if alignment is adjusted
+ * since findColour() handles everything
+ */
}
+ /**
+ * Answers a new colour scheme instance based on the HMM of the first sequence
+ * in sg that has an HMM
+ */
@Override
public ColourSchemeI getInstance(AnnotatedCollectionI sg,
Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
{
-
-
-
-
-
- HMMERColourScheme markov = new HMMERColourScheme(sg.getHMM());
- return markov;
+ HiddenMarkovModel model = null;
+ List<SequenceI> seqs = sg.getHMMConsensusSequences();
+ if (!seqs.isEmpty())
+ {
+ model = seqs.get(0).getHMM();
+ }
+ HMMERColourScheme colour = new HMMERColourScheme(model);
+ return colour;
}
@Override
- public boolean isApplicableTo(AnnotatedCollectionI ac)
+ public String getSchemeName()
{
- return true;
-
+ return JalviewColourScheme.HMMERU.toString();
}
@Override
- public String getSchemeName()
+ public boolean isSimple()
{
-
- return JalviewColourScheme.HMMER.name();
+ return false;
}
@Override
- public boolean isSimple()
+ public boolean isApplicableTo(AnnotatedCollectionI ac)
{
- // TODO Auto-generated method stub
- return false;
+ return !ac.getHMMConsensusSequences().isEmpty();
}
}