import jalview.datamodel.Annotation;
import jalview.datamodel.HiddenMarkovModel;
import jalview.datamodel.ProfilesI;
+import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.renderer.ResidueShaderI;
+import jalview.util.MessageManager;
import java.util.List;
+/**
+ * This class calculates HMM Information Content annotations, based on any HMM
+ * consensus sequences and their HMM models. HMM consensus sequences may be
+ * present for the whole alignment, or subgroups of it.
+ *
+ */
public class InformationThread extends AlignCalcWorker
{
public static final String HMM_CALC_ID = "HMM";
private float max = 0f;
/**
- * Constructor for information thread.
+ * Constructor
*
* @param alignViewport
* @param alignPanel
super(alignViewport, alignPanel);
}
+ /**
+ * Recomputes Information annotations for any HMM consensus sequences (for
+ * alignment and/or groups)
+ */
@Override
public void run()
{
calcMan.notifyStart(this);
// long started = System.currentTimeMillis();
- List<AlignmentAnnotation> information = getInformationAnnotations();
try
{
- if ((information == null) || calcMan.isPending(this))
+ if (calcMan.isPending(this))
{
+ // another instance of this is waiting to run
calcMan.workerComplete(this);
return;
}
while (!calcMan.notifyWorking(this))
{
- // System.err.println("Thread
- // (Information"+Thread.currentThread().getName()+") Waiting around.");
+ // another thread in progress, wait my turn
try
{
if (ap != null)
}
AlignmentI alignment = alignViewport.getAlignment();
- int aWidth = -1;
+ int aWidth = alignment == null ? -1 : alignment.getWidth();
- if (alignment == null || (aWidth = alignment.getWidth()) < 0)
+ if (aWidth < 0)
{
calcMan.workerComplete(this);
return;
}
- eraseInformation(aWidth);
- computeInformation(alignment);
+ eraseAnnotations(alignment);
+ computeProfiles(alignment);
updateResultAnnotation(true);
if (ap != null)
{
+ ap.adjustAnnotationHeight();
ap.paintAlignment(true, true);
}
} catch (OutOfMemoryError error)
}
/**
- * Clear out any existing information annotations
+ * Deletes any existing information annotations. These are sequence-related
+ * annotations which relate to HMM consensus sequences for either the
+ * alignment or a subgroup.
*
- * @param aWidth
- * the width (number of columns) of the annotated alignment
+ * @param alignment
*/
- protected void eraseInformation(int aWidth)
+ protected void eraseAnnotations(AlignmentI alignment)
{
-
- List<AlignmentAnnotation> information = getInformationAnnotations();
- for (AlignmentAnnotation info : information)
+ Iterable<AlignmentAnnotation> anns = alignment
+ .findAnnotation(HMM_CALC_ID);
+ for (AlignmentAnnotation ann : anns)
{
- info.annotations = new Annotation[aWidth];
+ alignment.deleteAnnotation(ann);
}
}
/**
- * Computes the profiles from a HMM for an alignment.
+ * Computes HMM profiles for any HMM consensus sequences (for alignment or
+ * subgroups)
*
* @param alignment
*/
- protected void computeInformation(AlignmentI alignment)
+ protected void computeProfiles(AlignmentI alignment)
{
int width = alignment.getWidth();
- List<SequenceI> hmmSeqs = alignment.getHMMConsensusSequences();
- int index = 0;
- for (SequenceI seq : hmmSeqs)
+ /*
+ * alignment HMM profile
+ */
+ SequenceI seq = alignment.getHmmConsensus();
+ if (seq != null)
{
HiddenMarkovModel hmm = seq.getHMM();
- ProfilesI hinformation = AAFrequency.calculateHMMProfiles(hmm, width,
+ ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
0, width, true, alignViewport.isIgnoreBelowBackground(),
alignViewport.isInfoLetterHeight());
- alignViewport.setSequenceInformationHash(hinformation, index);
- // setColourSchemeInformation(hinformation);
- index++;
+ alignViewport.setHmmProfiles(hmmProfiles);
+ // setColourSchemeInformation(hmmProfiles);
+ }
+
+ /*
+ * group HMM profiles
+ */
+ List<SequenceGroup> groups = alignment.getGroups();
+ for (SequenceGroup group : groups)
+ {
+ seq = group.getHmmConsensus();
+ if (seq != null)
+ {
+ HiddenMarkovModel hmm = seq.getHMM();
+ ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
+ 0, width, true, group.isIgnoreBelowBackground(),
+ group.isUseInfoLetterHeight());
+ group.setHmmProfiles(hmmProfiles);
+ // setColourSchemeInformation(hmmProfiles);
+ }
}
}
}
/**
- * Get the Information annotation for the alignment
- *
- * @return
- */
- protected List<AlignmentAnnotation> getInformationAnnotations()
- {
- return alignViewport.getInformationAnnotations();
- }
-
- /**
* Get the Gap annotation for the alignment
*
* @return
*/
protected AlignmentAnnotation getGapAnnotation()
{
- return alignViewport.getAlignmentGapAnnotation();
+ return alignViewport.getOccupancyAnnotation();
}
/**
- * update the information annotation from the sequence profile data using
- * current visualization settings.
+ * Updates the information annotation from the sequence profile data using
+ * current visualisation settings
*/
@Override
public void updateAnnotation()
}
/**
- * Derives the information content for an information annotation.
+ * Constructs Information Content annotation for any HMM consensus sequences
+ * (for alignment or groups), and adds the annotation to the sequence and the
+ * alignment
*
* @param immediate
*/
public void updateResultAnnotation(boolean immediate)
{
- List<AlignmentAnnotation> annots = getInformationAnnotations();
- int index = 0;
- for (AlignmentAnnotation information : annots)
+ AlignmentI alignment = alignViewport.getAlignment();
+
+ /*
+ * annotation for alignment HMM consensus if present
+ */
+ SequenceI hmmSeq = alignment.getHmmConsensus();
+ ProfilesI profile = alignViewport.getHmmProfiles();
+ AlignmentAnnotation ann = makeInformationAnnotation(hmmSeq, profile);
+ if (ann != null)
+ {
+ alignment.addAnnotation(ann);
+ }
+
+ /*
+ * annotation for group HMM consensus if present
+ */
+ for (SequenceGroup group : alignment.getGroups())
{
- ProfilesI hinformation = getSequenceInformation(index);
- if (immediate || !calcMan.isWorking(this) && information != null
- && hinformation != null)
+ hmmSeq = group.getHmmConsensus();
+ ProfilesI profiles = group.getHmmProfiles();
+ ann = makeInformationAnnotation(hmmSeq, profiles);
+ if (ann != null)
{
- deriveInformation(information, hinformation);
+ ann.groupRef = group;
+ alignment.addAnnotation(ann);
}
- index++;
}
}
/**
+ * Constructs an HMM Profile information content annotation for a sequence
+ *
+ * @param seq
+ * @param profile
+ * @return
+ */
+ protected AlignmentAnnotation makeInformationAnnotation(SequenceI seq,
+ ProfilesI profile)
+ {
+ if (seq == null || profile == null)
+ {
+ return null;
+ }
+
+ AlignmentI alignment = alignViewport.getAlignment();
+ int aWidth = alignment == null ? 0 : alignment.getWidth();
+ AlignmentAnnotation ann = new AlignmentAnnotation(seq.getName(),
+ MessageManager.getString("label.information_description"),
+ new Annotation[aWidth], 0f, 6.52f,
+ AlignmentAnnotation.BAR_GRAPH);
+ ann.hasText = true;
+ ann.autoCalculated = false;
+ ann.sequenceRef = seq;
+ ann.setCalcId(InformationThread.HMM_CALC_ID);
+ seq.addAlignmentAnnotation(ann);
+
+ long nseq = getSequences().length;
+ max = AAFrequency.completeInformation(ann, profile,
+ profile.getStartColumn(), profile.getEndColumn() + 1, nseq,
+ max);
+
+ return ann;
+ }
+
+ /**
* Convert the computed information data into the desired annotation for
* display.
*
hinformation, hinformation.getStartColumn(),
hinformation.getEndColumn() + 1, nseq, max);
}
-
- /**
- * Get the information data stored on the viewport.
- *
- * @return
- */
- protected ProfilesI getSequenceInformation(int index)
- {
- return alignViewport.getSequenceInformationHash(index);
- }
}