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.io.BufferedReader;
12 import java.io.FileNotFoundException;
13 import java.io.FileReader;
14 import java.io.IOException;
15 import java.util.ArrayList;
16 import java.util.HashMap;
17 import java.util.List;
23 public class HMMMatchScoreColourScheme extends ResidueColourScheme
26 private Map<Character, Map<Integer, Map<String, Double>>> probabilities;
28 private List<Integer> ranges;
30 private static double binSize;
32 public class MatchProbReader
34 private BufferedReader reader;
36 MatchProbReader() throws FileNotFoundException
38 reader = new BufferedReader(
39 new FileReader("resources/ProbabilityOfMatch"));
43 public Map<Character, Map<String, Double>> getProbabilities() throws IOException
45 Map<Character, Map<String, Double>> probabilities = new HashMap<>();
47 String[] alphabet = reader.readLine().split("\\,");
48 for (int i = 1; i < alphabet.length - 1; i++)
50 probabilities.put(alphabet[i].replaceAll("\\ ", "").charAt(0),
54 String line = reader.readLine();
57 String[] contents = line.split("\\,");
59 for(int i = 1; i < contents.length; i++)
61 probabilities.get(alphabet[i].replaceAll("\\ ", "").charAt(0))
62 .put(contents[0], Double
63 .valueOf(contents[i].replaceAll("\\ ", "")));
65 line = reader.readLine();
73 public Map<Character, Map<Integer, Map<String, Double>>> getProbabilities()
77 Map<Character, Map<Integer, Map<String, Double>>> probabilities = new HashMap<>();
79 ranges = new ArrayList<>();
82 binSize = Double.valueOf((reader.readLine().replaceAll("\\ ", "")));
83 String line = reader.readLine();
84 char c = line.charAt(0);
88 line = reader.readLine();
89 while (line != null && line.split("\\,").length != 1)
91 String[] llrs = line.split("\\,");
92 String[] counts = reader.readLine().split("\\,");
93 int range = Integer.valueOf(llrs[0]);
95 if (!ranges.contains(range))
99 if (!probabilities.containsKey(c))
101 probabilities.put(c, new HashMap<>());
103 probabilities.get(c).put(range, new HashMap<>());
105 for (int i = 1; i < llrs.length; i++)
107 probabilities.get(c).get(range).put(
108 llrs[i].replaceAll("\\ ", ""),
109 Double.valueOf(counts[i].replaceAll("\\ ", "")));
112 line = reader.readLine();
120 return probabilities;
125 private static final Color INSERTION_COLOUR = Color.white;
128 * the aligned HMM consensus sequence to use as reference for colouring
130 private SequenceI hmmSeq;
132 private HiddenMarkovModel hmm;
134 private Map<Character, Float> frequencies;
137 * Constructor given a list of Hidden Markov Model consensus sequences. The
138 * first sequence provides the HMM profile from which we can read the emission
139 * probabilities that determine the colour.
142 * @throws IOException
144 public HMMMatchScoreColourScheme(List<SequenceI> hmmSeqs)
146 hmmSeq = hmmSeqs.isEmpty() ? null : hmmSeqs.get(0);
147 hmm = hmmSeq == null ? null : hmmSeq.getHMM();
151 MatchProbReader probabilityReader = new MatchProbReader();
152 probabilities = probabilityReader.getProbabilities();
153 } catch (IOException e)
155 System.out.println(e.getStackTrace());
160 * Default constructor (required by ColourSchemes.loadColourSchemes)
162 public HMMMatchScoreColourScheme()
167 public Color findColour(char symbol, int column, SequenceI seq,
168 String consensusResidue, float pid)
174 return findColour(symbol, column, seq.gapMap().length);
177 // TODO change documentation
179 * Returns the colour at a particular symbol at a column in the alignment:
181 * <li>white for a gap</li>
182 * <li>red for an insertion</li>
183 * <li>orange for negative information content</li>
184 * <li>white to blue for increasing information content</li>
191 private Color findColour(char symbol, int column, int length)
193 if (getHmm() == null || Comparison.isGap(symbol))
197 if (Comparison.isGap(hmmSeq.getCharAt(column)))
199 return INSERTION_COLOUR;
201 if (Character.isLowerCase(symbol))
203 symbol = Character.toUpperCase(symbol);
207 if (hmm.getBackgroundFrequencies().containsKey(symbol))
209 int lengthBin = getLengthBin(length);
212 .log(getHmm().getMatchEmissionProbability(column, symbol)
213 / hmm.getBackgroundFrequencies().get(symbol));
215 if (!probabilities.containsKey(symbol)
216 || !probabilities.get(symbol).get(lengthBin)
217 .containsKey(format(llr)))
219 return new Color(140, 140, 140);
223 prob = probabilities.get(symbol).get(lengthBin).get(format(llr));
227 return new Color(140, 140, 140);
230 Color colour = Color.ORANGE;
234 colour = ColorUtils.getGraduatedColour((float) prob, 0.5f,
240 colour = ColorUtils.getGraduatedColour((float) prob, 0f, Color.red,
247 public static String format(Double d)
249 String formatArg = String.valueOf(binSize);
251 // if bin size, need format "%.n" where n is number of decimal places
254 formatArg = "." + formatArg.split("\\.")[1].length();
257 Double rounded = Math.round(d / binSize) * binSize;
258 String formatted = String.format("%" + formatArg + "f", rounded);
260 // format sometimes returns a number rounded to 0 as -0
261 // this ensures output will always be 0
262 if (Double.valueOf(formatted) == 0)
271 * Answers the maximum possible value of information score (log ratio), for use
272 * in scaling a graduated colour range
276 protected float getMaxInformationScore()
282 * Answers a new colour scheme instance based on the HMM of the first sequence
283 * in ac that has an HMM
286 public ColourSchemeI getInstance(AlignViewportI viewport,
287 AnnotatedCollectionI ac)
289 return newInstance(ac);
293 * Constructor given a sequence collection
297 public HMMMatchScoreColourScheme(AnnotatedCollectionI ac)
299 this(ac.getHmmSequences());
303 * Answers a new instance of the colour scheme for the given HMM
308 protected HMMMatchScoreColourScheme newInstance(AnnotatedCollectionI ac)
310 return new HMMMatchScoreColourScheme(ac);
314 public boolean isSimple()
320 * Answers true if the sequence collection has an HMM consensus sequence and
321 * that the first HMM sequence contains background frequencies, else false
324 public boolean isApplicableTo(AnnotatedCollectionI ac)
326 return !ac.getHmmSequences().isEmpty() && ac.getHmmSequences().get(0)
327 .getHMM().getBackgroundFrequencies() != null;
330 protected Map<Character, Float> getFrequencies()
335 protected void setFrequencies(Map<Character, Float> frequencies)
337 this.frequencies = frequencies;
340 protected HiddenMarkovModel getHmm()
345 protected SequenceI getHmmSequence()
351 public String getSchemeName()
353 return JalviewColourScheme.HMMMatchScore.toString();
356 private int getLengthBin(int l)
358 for (int i = 1; i < ranges.size(); i++)
360 if (l >= ranges.get(i - 1) && l < ranges.get(i))
362 return ranges.get(i);