1 package jalview.workers;
3 import jalview.analysis.AAFrequency;
4 import jalview.api.AlignViewportI;
5 import jalview.api.AlignmentViewPanel;
6 import jalview.datamodel.AlignmentAnnotation;
7 import jalview.datamodel.AlignmentI;
8 import jalview.datamodel.Annotation;
9 import jalview.datamodel.HiddenMarkovModel;
10 import jalview.datamodel.ProfilesI;
11 import jalview.datamodel.SequenceGroup;
12 import jalview.datamodel.SequenceI;
13 import jalview.util.MessageManager;
15 import java.util.ArrayList;
16 import java.util.List;
19 * This class calculates HMM Information Content annotations, based on any HMM
20 * consensus sequences and their HMM models. HMM consensus sequences may be
21 * present for the whole alignment, or subgroups of it.
24 public class InformationThread extends AlignCalcWorker
26 public static final String HMM_CALC_ID = "HMM";
31 * @param alignViewport
34 public InformationThread(AlignViewportI alignViewport,
35 AlignmentViewPanel alignPanel)
37 super(alignViewport, alignPanel);
41 public String getCalcName()
47 * Recomputes Information annotations for any HMM consensus sequences (for
48 * alignment and/or groups)
53 if (alignViewport.getAlignment().getHmmSequences().isEmpty())
57 if (alignViewport.isClosed())
63 AlignmentI alignment = alignViewport.getAlignment();
64 int aWidth = alignment == null ? -1 : alignment.getWidth();
71 * compute information profiles for any HMM consensus sequences
72 * for the alignment or sub-groups
74 computeProfiles(alignment);
77 * construct the corresponding annotations
83 ap.adjustAnnotationHeight();
84 ap.paintAlignment(true, true);
89 * Computes HMM profiles for any HMM consensus sequences (for alignment or
90 * subgroups). Any alignment profile computed is stored on the viewport, any
91 * group profile computed is stored on the respective sequence group.
94 * @see AlignViewportI#setHmmProfiles(ProfilesI)
96 protected void computeProfiles(AlignmentI alignment)
98 int width = alignment.getWidth();
101 * alignment HMM profile
103 List<SequenceI> seqs = alignment.getHmmSequences();
106 HiddenMarkovModel hmm = seqs.get(0).getHMM();
107 ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
108 0, width, alignViewport.isIgnoreBelowBackground(),
109 alignViewport.isInfoLetterHeight());
110 alignViewport.setHmmProfiles(hmmProfiles);
116 List<SequenceGroup> groups = alignment.getGroups();
117 for (SequenceGroup group : groups)
119 seqs = group.getHmmSequences();
122 HiddenMarkovModel hmm = seqs.get(0).getHMM();
123 ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
124 0, width, group.isIgnoreBelowBackground(),
125 group.isUseInfoLetterHeight());
126 group.setHmmProfiles(hmmProfiles);
132 * gets the sequences on the alignment on the viewport.
136 protected SequenceI[] getSequences()
138 return alignViewport.getAlignment().getSequencesArray();
142 * Get the Gap annotation for the alignment
146 protected AlignmentAnnotation getGapAnnotation()
148 return alignViewport.getAlignmentGapAnnotation();
152 * Computes Information Content annotation for any HMM consensus sequences
153 * (for alignment or groups), and updates (or adds) the annotation to the
154 * sequence and the alignment
157 public void updateAnnotation()
159 AlignmentI alignment = alignViewport.getAlignment();
161 float maxInformation = 0f;
162 List<AlignmentAnnotation> infos = new ArrayList<>();
165 * annotation for alignment HMM consensus if present
167 List<SequenceI> hmmSeqs = alignment.getHmmSequences();
168 if (!hmmSeqs.isEmpty())
170 ProfilesI profile = alignViewport.getHmmProfiles();
171 float m = updateInformationAnnotation(hmmSeqs.get(0), profile, null,
173 maxInformation = Math.max(maxInformation, m);
177 * annotation for group HMM consensus if present
179 for (SequenceGroup group : alignment.getGroups())
181 hmmSeqs = group.getHmmSequences();
182 if (!hmmSeqs.isEmpty())
184 ProfilesI profiles = group.getHmmProfiles();
185 float m = updateInformationAnnotation(hmmSeqs.get(0), profiles,
187 maxInformation = Math.max(maxInformation, m);
192 * maxInformation holds the maximum value of information score;
193 * set this as graphMax in all annotations to scale them all the same
195 for (AlignmentAnnotation ann : infos)
197 ann.graphMax = maxInformation;
202 * Updates (and first constructs if necessary) an HMM Profile information
203 * content annotation for a sequence. The <code>group</code> argument is null
204 * for the whole alignment annotation, not null for a subgroup annotation. The
205 * updated annotation is added to the <code>infos</code> list. Answers the
206 * maximum information content value of any annotation (for use as a scaling
207 * factor for display).
215 protected float updateInformationAnnotation(SequenceI seq,
216 ProfilesI profile, SequenceGroup group,
217 List<AlignmentAnnotation> infos)
219 if (seq == null || profile == null)
224 AlignmentAnnotation ann = findOrCreateAnnotation(seq, group);
226 seq.addAlignmentAnnotation(ann);
229 float max = AAFrequency.completeInformation(ann, profile,
230 profile.getStartColumn(), profile.getEndColumn() + 1);
236 * A helper method that first searches for the HMM annotation that matches the
237 * group reference (null for the whole alignment annotation). If found, its
238 * sequence reference is updated to the given sequence (the recomputed HMM
239 * consensus sequence). If not found, it is created. This supports both
240 * creating the annotation the first time hmmbuild is run, and updating it if
241 * hmmbuild is re-run.
247 AlignmentAnnotation findOrCreateAnnotation(SequenceI seq,
251 * can't use Alignment.findOrCreateAnnotation here because we
252 * want to update, rather than match on, the sequence ref
254 AlignmentAnnotation info = null;
256 AlignmentI alignment = alignViewport.getAlignment();
257 AlignmentAnnotation[] anns = alignment.getAlignmentAnnotation();
260 for (AlignmentAnnotation ann : anns)
262 if (HMM_CALC_ID.equals(ann.getCalcId()) && group == ann.groupRef)
265 info.setSequenceRef(seq);
266 info.label = seq.getName(); // in case group name changed!
274 int aWidth = alignment.getWidth();
275 String desc = MessageManager
276 .getString("label.information_description");
277 float graphMax = 6.52f; // todo where does this value derive from?
278 info = new AlignmentAnnotation(seq.getName(), desc,
279 new Annotation[aWidth], 0f, graphMax,
280 AlignmentAnnotation.BAR_GRAPH);
281 info.setCalcId(HMM_CALC_ID);
282 info.setSequenceRef(seq);
283 info.groupRef = group;
285 alignment.addAnnotation(info);