import jalview.renderer.ResidueShader;
import jalview.renderer.ResidueShaderI;
import jalview.schemes.ColourSchemeI;
+import jalview.util.MessageManager;
+import jalview.workers.InformationThread;
import java.awt.Color;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
*/
public class SequenceGroup implements AnnotatedCollectionI
{
+ // TODO ideally this event notification functionality should be separated into
+ // a
+ // subclass of ViewportProperties similarly to ViewportRanges. Done here as
+ // quick fix for JAL-2665
+ public static final String SEQ_GROUP_CHANGED = "Sequence group changed";
+
+ protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(
+ this);
+
+ public void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
+ // end of event notification functionality initialisation
+
String groupName;
String description;
*/
private boolean ignoreGapsInConsensus = true;
+ private boolean ignoreBelowBackground = true;
+
+ private boolean infoLetterHeight = false;
+
/**
* consensus calculation property
*/
AlignmentAnnotation conservation = null;
+ AlignmentAnnotation information = null;
+
private boolean showConsensusHistogram;
private AnnotatedCollectionI context;
+ private boolean showHMMSequenceLogo;
+
+ private boolean normaliseHMMSequenceLogo;
+
+ private boolean showInformationHistogram;
+
/**
* Creates a new SequenceGroup object.
*/
colourText = seqsel.colourText;
startRes = seqsel.startRes;
endRes = seqsel.endRes;
- cs = seqsel.cs;// new ResidueShader(seqsel.getColourScheme());
+ cs = new ResidueShader((ResidueShader) seqsel.cs);
if (seqsel.description != null)
{
description = new String(seqsel.description);
showSequenceLogo = seqsel.showSequenceLogo;
normaliseSequenceLogo = seqsel.normaliseSequenceLogo;
showConsensusHistogram = seqsel.showConsensusHistogram;
+ showHMMSequenceLogo = seqsel.showHMMSequenceLogo;
+ normaliseHMMSequenceLogo = seqsel.normaliseHMMSequenceLogo;
+ showInformationHistogram = seqsel.showInformationHistogram;
idColour = seqsel.idColour;
outlineColour = seqsel.outlineColour;
seqrep = seqsel.seqrep;
thresholdTextColour = seqsel.thresholdTextColour;
width = seqsel.width;
ignoreGapsInConsensus = seqsel.ignoreGapsInConsensus;
+ ignoreBelowBackground = seqsel.ignoreBelowBackground;
+ infoLetterHeight = seqsel.infoLetterHeight;
if (seqsel.conserve != null)
{
recalcConservation(); // safer than
seqs[ipos].setDescription(seq.getDescription());
seqs[ipos].setDBRefs(seq.getDBRefs());
seqs[ipos].setSequenceFeatures(seq.getSequenceFeatures());
+ seqs[ipos].setIsHMMConsensusSequence(seq.isHMMConsensusSequence());
if (seq.getDatasetSequence() != null)
{
seqs[ipos].setDatasetSequence(seq.getDatasetSequence());
if (s != null && !sequences.contains(s))
{
sequences.add(s);
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED,
+ sequences.size() - 1, sequences.size());
}
if (recalc)
*/
public boolean recalcConservation(boolean defer)
{
- if (cs == null && consensus == null && conservation == null)
+ if (cs == null && consensus == null && conservation == null
+ && information == null)
{
return false;
}
{
ProfilesI cnsns = AAFrequency.calculate(sequences, startRes,
endRes + 1, showSequenceLogo);
+ if (information != null)
+ {
+ HiddenMarkovModel hmm = information.sequenceRef.getHMM();
+
+ ProfilesI info = AAFrequency.calculateHMMProfiles(hmm,
+ (endRes + 1) - startRes, startRes, endRes + 1,
+ showHMMSequenceLogo, ignoreBelowBackground,
+ infoLetterHeight);
+ _updateInformationRow(info, sequences.size());
+ upd = true;
+ }
if (consensus != null)
{
_updateConsensusRow(cnsns, sequences.size());
conservation.description = "Conservation for group " + getName()
+ " less than " + consPercGaps + "% gaps";
// preserve width if already set
- int aWidth = (conservation.annotations != null) ? (endRes < conservation.annotations.length ? conservation.annotations.length
- : endRes + 1)
+ int aWidth = (conservation.annotations != null)
+ ? (endRes < conservation.annotations.length
+ ? conservation.annotations.length
+ : endRes + 1)
: endRes + 1;
conservation.annotations = null;
conservation.annotations = new Annotation[aWidth]; // should be alignment
public ProfilesI consensusData = null;
+ public ProfilesI informationData = null;
+
private void _updateConsensusRow(ProfilesI cnsns, long nseq)
{
if (consensus == null)
consensus.description = "Percent Identity";
consensusData = cnsns;
// preserve width if already set
- int aWidth = (consensus.annotations != null) ? (endRes < consensus.annotations.length ? consensus.annotations.length
- : endRes + 1)
+ int aWidth = (consensus.annotations != null)
+ ? (endRes < consensus.annotations.length
+ ? consensus.annotations.length
+ : endRes + 1)
: endRes + 1;
consensus.annotations = null;
consensus.annotations = new Annotation[aWidth]; // should be alignment width
}
/**
+ * Recalculates the information content on the HMM annotation.
+ *
+ * @param cnsns
+ * @param nseq
+ */
+ private void _updateInformationRow(ProfilesI cnsns, long nseq)
+ {
+ if (information == null)
+ {
+ getInformation();
+ }
+ information.description = MessageManager
+ .getString("label.information_description");
+ informationData = cnsns;
+ // preserve width if already set
+ int aWidth = (information.annotations != null)
+ ? (endRes < information.annotations.length
+ ? information.annotations.length : endRes + 1)
+ : endRes + 1;
+ information.annotations = null;
+ information.annotations = new Annotation[aWidth]; // should be alignment
+ // width
+ information.setCalcId(InformationThread.HMM_CALC_ID);
+ AAFrequency.completeInformation(information, cnsns, startRes,
+ endRes + 1, nseq, 0f);
+ }
+
+ /**
* @param s
* sequence to either add or remove from group
* @param recalc
synchronized (sequences)
{
sequences.remove(s);
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED,
+ sequences.size() + 1, sequences.size());
if (recalc)
{
*/
public void setStartRes(int i)
{
+ int before = startRes;
startRes = i;
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, startRes);
}
/**
*/
public void setEndRes(int i)
{
+ int before = endRes;
endRes = i;
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, endRes);
}
/**
}
/**
+ * Answers the Hidden Markov Model annotation for this group (creating it if
+ * necessary)
+ *
+ * @return
+ */
+ public AlignmentAnnotation getInformation()
+ {
+ if (information == null)
+ {
+ information = new AlignmentAnnotation("", "", new Annotation[1], 0f,
+ 6.25f, AlignmentAnnotation.BAR_GRAPH);
+ information.hasText = true;
+ information.autoCalculated = false;
+ information.groupRef = this;
+ information.label = getName();
+ information.description = MessageManager
+ .getString("label.information_description");
+ information.setCalcId(InformationThread.HMM_CALC_ID);
+ }
+ return information;
+ }
+
+ /**
* set this alignmentAnnotation object as the one used to render consensus
* annotation
*
return ignoreGapsInConsensus;
}
+ public void setIgnoreBelowBackground(boolean state)
+ {
+ if (this.ignoreBelowBackground != state)
+ {
+ ignoreBelowBackground = state;
+ }
+ ignoreBelowBackground = state;
+ }
+
+ public boolean getIgnoreBelowBackground()
+ {
+ return ignoreBelowBackground;
+ }
+
+ public void setInfoLetterHeight(boolean state)
+ {
+ if (this.infoLetterHeight != state)
+ {
+ infoLetterHeight = state;
+ }
+ infoLetterHeight = state;
+ }
+
+ public boolean getInfoLetterHeight()
+ {
+ return infoLetterHeight;
+ }
+
/**
* @param showSequenceLogo
* indicates if a sequence logo is shown for consensus annotation
@Override
public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
{
- List<AlignmentAnnotation> aa = new ArrayList<>();
- if (calcId == null)
- {
- return aa;
- }
- for (AlignmentAnnotation a : getAlignmentAnnotation())
- {
- if (calcId.equals(a.getCalcId()))
- {
- aa.add(a);
- }
- }
- return aa;
+ return AlignmentAnnotation.findAnnotation(
+ Arrays.asList(getAlignmentAnnotation()), calcId);
}
@Override
public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
String calcId, String label)
{
- ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
- for (AlignmentAnnotation ann : getAlignmentAnnotation())
- {
- if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId()
- .equals(calcId)))
- && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq))
- && (label == null || (ann.label != null && ann.label
- .equals(label))))
- {
- aa.add(ann);
- }
- }
- return aa;
+ return AlignmentAnnotation.findAnnotations(
+ Arrays.asList(getAlignmentAnnotation()), seq, calcId, label);
}
/**
*/
public boolean hasAnnotation(String calcId)
{
- if (calcId != null && !"".equals(calcId))
- {
- for (AlignmentAnnotation a : getAlignmentAnnotation())
- {
- if (a.getCalcId() == calcId)
- {
- return true;
- }
- }
- }
- return false;
+ return AlignmentAnnotation
+ .hasAnnotation(Arrays.asList(getAlignmentAnnotation()), calcId);
}
/**
{
synchronized (sequences)
{
+ int before = sequences.size();
sequences.clear();
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before,
+ sequences.size());
}
}
@Override
public boolean isNucleotide()
{
- if (context != null) {
+ if (context != null)
+ {
return context.isNucleotide();
}
return false;
{
return (startRes <= apos && endRes >= apos) && sequences.contains(seq);
}
+
+ public boolean isShowInformationHistogram()
+ {
+ return showInformationHistogram;
+ }
+
+ public void setShowInformationHistogram(boolean state)
+ {
+ if (showInformationHistogram != state && information != null)
+ {
+ this.showInformationHistogram = state;
+ // recalcConservation(); TODO don't know what to do here next
+ }
+ this.showInformationHistogram = state;
+
+ }
+
+ public boolean isShowHMMSequenceLogo()
+ {
+ return showHMMSequenceLogo;
+ }
+
+ public void setshowHMMSequenceLogo(boolean state)
+ {
+ showHMMSequenceLogo = state;
+
+ }
+
+ public boolean isNormaliseHMMSequenceLogo()
+ {
+ return normaliseHMMSequenceLogo;
+ }
+
+ public void setNormaliseHMMSequenceLogo(boolean state)
+ {
+ normaliseSequenceLogo = state;
+ }
+
+ /**
+ * Returns all HMM consensus sequences. This will not return real sequences
+ * with HMMs.
+ */
+ @Override
+ public List<SequenceI> getHMMConsensusSequences()
+ {
+ List<SequenceI> seqs = new ArrayList<>();
+
+ for (int position = 0; position < sequences.size(); position++)
+ {
+ SequenceI seq = sequences.get(position);
+ if (seq.isHMMConsensusSequence())
+ {
+ seqs.add(seq);
+ }
+ }
+ return seqs;
+ }
+
}