X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FSequenceGroup.java;fp=src%2Fjalview%2Fdatamodel%2FSequenceGroup.java;h=aebcbb3453a2c21dcd2ed5782c52d61aa7781437;hb=04a4d60a50394d846d0479c442facebe360b5b9c;hp=6b797d79a939a5c50af6b41e05916e96956185e5;hpb=653e250e0a2a5dd455ae4c52794c4ce0de340418;p=jalview.git diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index 6b797d7..aebcbb3 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -25,6 +25,8 @@ import jalview.analysis.Conservation; 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; @@ -43,116 +45,120 @@ 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 + // a subclass of ViewportProperties similarly to ViewportRanges. + // Done here as a quick fix for JAL-2665 public static final String SEQ_GROUP_CHANGED = "Sequence group changed"; - protected PropertyChangeSupport changeSupport = new PropertyChangeSupport( - this); + private String groupName; - public void addPropertyChangeListener(PropertyChangeListener listener) - { - changeSupport.addPropertyChangeListener(listener); - } + private String description; - public void removePropertyChangeListener(PropertyChangeListener listener) - { - changeSupport.removePropertyChangeListener(listener); - } - // end of event notification functionality initialisation + private AnnotatedCollectionI context; - String groupName; + private Conservation conservationData; - String description; + private ProfilesI consensusProfiles; - Conservation conserve; + private ProfilesI hmmProfiles; - boolean displayBoxes = true; + private boolean displayBoxes = true; - boolean displayText = true; + private boolean displayText = true; - boolean colourText = false; + private boolean colourText = false; - /** - * True if the group is defined as a group on the alignment, false if it is - * just a selection. + /* + * true if the group is defined as a group on the alignment, false if it is + * just a selection */ - boolean isDefined = false; + private boolean isDefined; - /** + /* * after Olivier's non-conserved only character display */ - boolean showNonconserved = false; + private boolean showNonconserved; - /** - * group members + /* + * sequences in the group */ private List sequences = new ArrayList<>(); - /** + /* * representative sequence for this group (if any) */ - private SequenceI seqrep = null; + private SequenceI seqrep; + + /* + * HMM consensus sequence for group (if any) + */ + private SequenceI hmmConsensus; - int width = -1; + private int width = -1; - /** - * Colourscheme applied to group if any + /* + * colour scheme applied to group if any */ public ResidueShaderI cs; // start column (base 0) - int startRes = 0; + private int startRes; // end column (base 0) - int endRes = 0; + private int endRes; public Color outlineColour = Color.black; - public Color idColour = null; + public Color idColour; - public int thresholdTextColour = 0; + public int thresholdTextColour; public Color textColour = Color.black; public Color textColour2 = Color.white; - /** - * consensus calculation property + /* + * properties for consensus annotation */ private boolean ignoreGapsInConsensus = true; - /** - * consensus calculation property - */ - private boolean showSequenceLogo = false; + private boolean showSequenceLogo; - /** - * flag indicating if logo should be rendered normalised - */ private boolean normaliseSequenceLogo; + private boolean showConsensusHistogram; + + /* + * properties for HMM information annotation + */ + private boolean hmmIgnoreBelowBackground = true; + + private boolean hmmUseInfoLetterHeight; + + private boolean hmmShowSequenceLogo; + + private boolean hmmNormaliseSequenceLogo; + + private boolean hmmShowHistogram; + /* * visibility of rows or represented rows covered by group */ - private boolean hidereps = false; + private boolean hidereps; /* * visibility of columns intersecting this group */ - private boolean hidecols = false; - - AlignmentAnnotation consensus = null; + private boolean hidecols; - AlignmentAnnotation conservation = null; + private AlignmentAnnotation consensus; - private boolean showConsensusHistogram; + private AlignmentAnnotation conservation; - private AnnotatedCollectionI context; + private AlignmentAnnotation hmmInformation; /** - * Creates a new SequenceGroup object. + * Constructor, assigning a generated default name of "JGroup:" with object + * hashcode appended */ public SequenceGroup() { @@ -222,6 +228,9 @@ public class SequenceGroup implements AnnotatedCollectionI showSequenceLogo = seqsel.showSequenceLogo; normaliseSequenceLogo = seqsel.normaliseSequenceLogo; showConsensusHistogram = seqsel.showConsensusHistogram; + hmmShowSequenceLogo = seqsel.hmmShowSequenceLogo; + hmmNormaliseSequenceLogo = seqsel.hmmNormaliseSequenceLogo; + hmmShowHistogram = seqsel.hmmShowHistogram; idColour = seqsel.idColour; outlineColour = seqsel.outlineColour; seqrep = seqsel.seqrep; @@ -230,7 +239,9 @@ public class SequenceGroup implements AnnotatedCollectionI thresholdTextColour = seqsel.thresholdTextColour; width = seqsel.width; ignoreGapsInConsensus = seqsel.ignoreGapsInConsensus; - if (seqsel.conserve != null) + hmmIgnoreBelowBackground = seqsel.hmmIgnoreBelowBackground; + hmmUseInfoLetterHeight = seqsel.hmmUseInfoLetterHeight; + if (seqsel.conservationData != null) { recalcConservation(); // safer than // aaFrequency = (Vector) seqsel.aaFrequency.clone(); // ?? @@ -238,6 +249,19 @@ public class SequenceGroup implements AnnotatedCollectionI } } + protected PropertyChangeSupport changeSupport = new PropertyChangeSupport( + this); + + public void addPropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.removePropertyChangeListener(listener); + } + public boolean isShowSequenceLogo() { return showSequenceLogo; @@ -259,6 +283,7 @@ public class SequenceGroup implements AnnotatedCollectionI 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()); @@ -488,7 +513,7 @@ public class SequenceGroup implements AnnotatedCollectionI */ public Conservation getConservation() { - return conserve; + return conservationData; } /** @@ -499,7 +524,7 @@ public class SequenceGroup implements AnnotatedCollectionI */ public void setConservation(Conservation c) { - conserve = c; + conservationData = c; } /** @@ -560,20 +585,22 @@ public class SequenceGroup implements AnnotatedCollectionI */ public boolean recalcConservation() { - return recalcConservation(false); + return recalcAnnotations(false); } /** - * calculate residue conservation for group - but only if necessary. returns - * true if the calculation resulted in a visible change to group + * Recalculates column consensus, conservation, and HMM annotation for the + * group (as applicable). Returns true if the calculation resulted in a + * visible change to group. * * @param defer * when set, colourschemes for this group are not refreshed after * recalculation */ - public boolean recalcConservation(boolean defer) + public boolean recalcAnnotations(boolean defer) { - if (cs == null && consensus == null && conservation == null) + if (cs == null && consensus == null && conservation == null + && hmmInformation == null) { return false; } @@ -584,6 +611,16 @@ public class SequenceGroup implements AnnotatedCollectionI { ProfilesI cnsns = AAFrequency.calculate(sequences, startRes, endRes + 1, showSequenceLogo); + if (hmmInformation != null) + { + HiddenMarkovModel hmm = hmmInformation.sequenceRef.getHMM(); + + ProfilesI info = AAFrequency.calculateHMMProfiles(hmm, + (endRes + 1) - startRes, startRes, endRes + 1, + hmmIgnoreBelowBackground, hmmUseInfoLetterHeight); + _updateInformationRow(info); + upd = true; + } if (consensus != null) { _updateConsensusRow(cnsns, sequences.size()); @@ -656,8 +693,6 @@ public class SequenceGroup implements AnnotatedCollectionI c.completeAnnotations(conservation, null, startRes, endRes + 1); } - public ProfilesI consensusData = null; - private void _updateConsensusRow(ProfilesI cnsns, long nseq) { if (consensus == null) @@ -666,7 +701,7 @@ public class SequenceGroup implements AnnotatedCollectionI } consensus.label = "Consensus for " + getName(); consensus.description = "Percent Identity"; - consensusData = cnsns; + consensusProfiles = cnsns; // preserve width if already set int aWidth = (consensus.annotations != null) ? (endRes < consensus.annotations.length @@ -684,6 +719,33 @@ public class SequenceGroup implements AnnotatedCollectionI } /** + * Recalculates the information content on the HMM annotation + * + * @param cnsns + */ + private void _updateInformationRow(ProfilesI cnsns) + { + if (hmmInformation == null) + { + createInformationAnnotation(); + } + hmmInformation.description = MessageManager + .getString("label.information_description"); + setHmmProfiles(cnsns); + // preserve width if already set + int aWidth = (hmmInformation.annotations != null) + ? (endRes < hmmInformation.annotations.length + ? hmmInformation.annotations.length : endRes + 1) + : endRes + 1; + hmmInformation.annotations = null; + hmmInformation.annotations = new Annotation[aWidth]; // should be alignment + // width + hmmInformation.setCalcId(InformationThread.HMM_CALC_ID); + AAFrequency.completeInformation(hmmInformation, cnsns, startRes, + endRes + 1); + } + + /** * @param s * sequence to either add or remove from group * @param recalc @@ -1137,6 +1199,22 @@ public class SequenceGroup implements AnnotatedCollectionI } /** + * Creates the Hidden Markov Model annotation for this group + */ + void createInformationAnnotation() + { + hmmInformation = new AlignmentAnnotation("", "", new Annotation[1], 0f, + 6.25f, AlignmentAnnotation.BAR_GRAPH); + hmmInformation.hasText = true; + hmmInformation.autoCalculated = false; + hmmInformation.groupRef = this; + hmmInformation.label = getName(); + hmmInformation.description = MessageManager + .getString("label.information_description"); + hmmInformation.setCalcId(InformationThread.HMM_CALC_ID); + } + + /** * set this alignmentAnnotation object as the one used to render consensus * annotation * @@ -1189,9 +1267,10 @@ public class SequenceGroup implements AnnotatedCollectionI { if (consensus.annotations[i] != null) { - if (consensus.annotations[i].description.charAt(0) == '[') + String desc = consensus.annotations[i].description; + if (desc.length() > 1 && desc.charAt(0) == '[') { - seqs.append(consensus.annotations[i].description.charAt(1)); + seqs.append(desc.charAt(1)); } else { @@ -1217,11 +1296,31 @@ public class SequenceGroup implements AnnotatedCollectionI ignoreGapsInConsensus = state; } - public boolean getIgnoreGapsConsensus() + public boolean isIgnoreGapsConsensus() { return ignoreGapsInConsensus; } + public void setIgnoreBelowBackground(boolean state) + { + hmmIgnoreBelowBackground = state; + } + + public boolean isIgnoreBelowBackground() + { + return hmmIgnoreBelowBackground; + } + + public void setInfoLetterHeight(boolean state) + { + hmmUseInfoLetterHeight = state; + } + + public boolean isUseInfoLetterHeight() + { + return hmmUseInfoLetterHeight; + } + /** * @param showSequenceLogo * indicates if a sequence logo is shown for consensus annotation @@ -1465,4 +1564,67 @@ public class SequenceGroup implements AnnotatedCollectionI { return (startRes <= apos && endRes >= apos) && sequences.contains(seq); } + + public boolean isShowInformationHistogram() + { + return hmmShowHistogram; + } + + public void setShowInformationHistogram(boolean state) + { + if (hmmShowHistogram != state && hmmInformation != null) + { + this.hmmShowHistogram = state; + // recalcConservation(); TODO don't know what to do here next + } + this.hmmShowHistogram = state; + } + + public boolean isShowHMMSequenceLogo() + { + return hmmShowSequenceLogo; + } + + public void setShowHMMSequenceLogo(boolean state) + { + hmmShowSequenceLogo = state; + } + + public boolean isNormaliseHMMSequenceLogo() + { + return hmmNormaliseSequenceLogo; + } + + public void setNormaliseHMMSequenceLogo(boolean state) + { + hmmNormaliseSequenceLogo = state; + } + + @Override + public SequenceI getHmmConsensus() + { + return hmmConsensus; + } + + @Override + public void setHmmConsensus(SequenceI hmmSeq) + { + this.hmmConsensus = hmmSeq; + } + + public ProfilesI getConsensusData() + { + return consensusProfiles; + } + + public ProfilesI getHmmProfiles() + { + return hmmProfiles; + } + + public void setHmmProfiles(ProfilesI hmmProfiles) + { + this.hmmProfiles = hmmProfiles; + } + }