X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FSequenceGroup.java;h=2f524c68a18c9bf751f0c59f878fb9129438b713;hb=af7becd656cba3835394e2dc50c2ad8d189a6d46;hp=854b39ddec8e171b014ed6a2261b1e0abe09107a;hpb=d595e9cf7672de6d60165b536bc3def4b31f2352;p=jalview.git diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index 854b39d..2f524c6 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -26,9 +26,13 @@ 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; @@ -40,107 +44,121 @@ import java.util.Map; */ public class SequenceGroup implements AnnotatedCollectionI { - String groupName; + // TODO ideally this event notification functionality should be separated into + // 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"; - String description; + private String groupName; - Conservation conserve; + private String description; - boolean displayBoxes = true; + private AnnotatedCollectionI context; - boolean displayText = true; + private Conservation conservationData; - boolean colourText = false; + private ProfilesI consensusProfiles; - /** - * True if the group is defined as a group on the alignment, false if it is - * just a selection. + private ProfilesI hmmProfiles; + + private boolean displayBoxes = true; + + private boolean displayText = true; + + private boolean colourText = false; + + /* + * 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; - int width = -1; + /* + * HMM consensus sequence for group (if any) + */ + private SequenceI hmmConsensus; - /** - * Colourscheme applied to group if any + private int width = -1; + + /* + * 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; - private boolean ignoreBelowBackground = true; + private boolean showSequenceLogo; - /** - * consensus calculation property - */ - private boolean showSequenceLogo = false; - - /** - * flag indicating if logo should be rendered normalised - */ private boolean normaliseSequenceLogo; - /* - * visibility of rows or represented rows covered by group - */ - private boolean hidereps = false; + private boolean showConsensusHistogram; /* - * visibility of columns intersecting this group + * properties for HMM information annotation */ - private boolean hidecols = false; + private boolean hmmIgnoreBelowBackground = true; - AlignmentAnnotation consensus = null; + private boolean hmmUseInfoLetterHeight; - AlignmentAnnotation conservation = null; + private boolean showHMMSequenceLogo; - AlignmentAnnotation information = null; + private boolean hmmNormaliseSequenceLogo; - private boolean showConsensusHistogram; + private boolean hmmShowHistogram; - private AnnotatedCollectionI context; + /* + * visibility of rows or represented rows covered by group + */ + private boolean hidereps; - private boolean showHMMSequenceLogo; + /* + * visibility of columns intersecting this group + */ + private boolean hidecols; + + private AlignmentAnnotation consensus; - private boolean normaliseHMMSequenceLogo; + private AlignmentAnnotation conservation; - private boolean showInformationHistogram; + private AlignmentAnnotation hmmInformation; /** - * Creates a new SequenceGroup object. + * Constructor, assigning a generated default name of "JGroup:" with object + * hashcode appended */ public SequenceGroup() { @@ -211,8 +229,8 @@ public class SequenceGroup implements AnnotatedCollectionI normaliseSequenceLogo = seqsel.normaliseSequenceLogo; showConsensusHistogram = seqsel.showConsensusHistogram; showHMMSequenceLogo = seqsel.showHMMSequenceLogo; - normaliseHMMSequenceLogo = seqsel.normaliseHMMSequenceLogo; - showInformationHistogram = seqsel.showInformationHistogram; + hmmNormaliseSequenceLogo = seqsel.hmmNormaliseSequenceLogo; + hmmShowHistogram = seqsel.hmmShowHistogram; idColour = seqsel.idColour; outlineColour = seqsel.outlineColour; seqrep = seqsel.seqrep; @@ -221,8 +239,9 @@ public class SequenceGroup implements AnnotatedCollectionI thresholdTextColour = seqsel.thresholdTextColour; width = seqsel.width; ignoreGapsInConsensus = seqsel.ignoreGapsInConsensus; - ignoreBelowBackground = seqsel.ignoreBelowBackground; - if (seqsel.conserve != null) + hmmIgnoreBelowBackground = seqsel.hmmIgnoreBelowBackground; + hmmUseInfoLetterHeight = seqsel.hmmUseInfoLetterHeight; + if (seqsel.conservationData != null) { recalcConservation(); // safer than // aaFrequency = (Vector) seqsel.aaFrequency.clone(); // ?? @@ -230,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; @@ -251,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()); @@ -480,7 +513,7 @@ public class SequenceGroup implements AnnotatedCollectionI */ public Conservation getConservation() { - return conserve; + return conservationData; } /** @@ -491,7 +524,7 @@ public class SequenceGroup implements AnnotatedCollectionI */ public void setConservation(Conservation c) { - conserve = c; + conservationData = c; } /** @@ -511,6 +544,8 @@ public class SequenceGroup implements AnnotatedCollectionI if (s != null && !sequences.contains(s)) { sequences.add(s); + changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, + sequences.size() - 1, sequences.size()); } if (recalc) @@ -550,21 +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 - && information == null) + && hmmInformation == null) { return false; } @@ -575,14 +611,14 @@ public class SequenceGroup implements AnnotatedCollectionI { ProfilesI cnsns = AAFrequency.calculate(sequences, startRes, endRes + 1, showSequenceLogo); - if (information != null) + if (hmmInformation != null) { - HiddenMarkovModel hmm = information.sequenceRef.getHMM(); + HiddenMarkovModel hmm = hmmInformation.sequenceRef.getHMM(); ProfilesI info = AAFrequency.calculateHMMProfiles(hmm, (endRes + 1) - startRes, startRes, endRes + 1, - showHMMSequenceLogo, ignoreBelowBackground); - _updateInformationRow(info, sequences.size()); + hmmIgnoreBelowBackground, hmmUseInfoLetterHeight); + _updateInformationRow(info); upd = true; } if (consensus != null) @@ -657,10 +693,6 @@ public class SequenceGroup implements AnnotatedCollectionI c.completeAnnotations(conservation, null, startRes, endRes + 1); } - public ProfilesI consensusData = null; - - public ProfilesI informationData = null; - private void _updateConsensusRow(ProfilesI cnsns, long nseq) { if (consensus == null) @@ -669,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 @@ -687,35 +719,30 @@ public class SequenceGroup implements AnnotatedCollectionI } /** - * Recalculates the information content on the HMM annotation. + * Recalculates the information content on the HMM annotation * * @param cnsns - * @param nseq */ - private void _updateInformationRow(ProfilesI cnsns, long nseq) + private void _updateInformationRow(ProfilesI cnsns) { - if (information == null) + if (hmmInformation == null) { - getInformation(); + createInformationAnnotation(); } - information.description = MessageManager + hmmInformation.description = MessageManager .getString("label.information_description"); - informationData = cnsns; + setHmmProfiles(cnsns); // preserve width if already set - int aWidth = (information.annotations != null) - ? (endRes < information.annotations.length - ? information.annotations.length : endRes + 1) + int aWidth = (hmmInformation.annotations != null) + ? (endRes < hmmInformation.annotations.length + ? hmmInformation.annotations.length : endRes + 1) : endRes + 1; - information.annotations = null; - information.annotations = new Annotation[aWidth]; // should be alignment + hmmInformation.annotations = null; + hmmInformation.annotations = new Annotation[aWidth]; // should be alignment // width - information.calcId = "HMM"; - AAFrequency.completeInformation(information, cnsns, startRes, - endRes + 1, ignoreBelowBackground, showSequenceLogo, nseq); // TODO: - // setting - // container - // for - // ignoreGapsInInformationCalculation); + hmmInformation.setCalcId(InformationThread.HMM_CALC_ID); + AAFrequency.completeInformation(hmmInformation, cnsns, startRes, + endRes + 1); } /** @@ -753,6 +780,8 @@ public class SequenceGroup implements AnnotatedCollectionI synchronized (sequences) { sequences.remove(s); + changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, + sequences.size() + 1, sequences.size()); if (recalc) { @@ -789,7 +818,9 @@ public class SequenceGroup implements AnnotatedCollectionI */ public void setStartRes(int i) { + int before = startRes; startRes = i; + changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, startRes); } /** @@ -799,7 +830,9 @@ public class SequenceGroup implements AnnotatedCollectionI */ public void setEndRes(int i) { + int before = endRes; endRes = i; + changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, endRes); } /** @@ -1166,32 +1199,19 @@ public class SequenceGroup implements AnnotatedCollectionI } /** - * - * @return information content annotation. + * Creates the Hidden Markov Model annotation for this group */ - public AlignmentAnnotation getInformation() + void createInformationAnnotation() { - // TODO get or calculate and get information annotation row for this group - int aWidth = this.getWidth(); - // pointer - // possibility - // here. - if (aWidth < 0) - { - return null; - } - 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 = "Information content, measured in bits"; - information.calcId = "HMM"; - } - return information; + 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); } /** @@ -1247,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 { @@ -1275,23 +1296,29 @@ public class SequenceGroup implements AnnotatedCollectionI ignoreGapsInConsensus = state; } - public boolean getIgnoreGapsConsensus() + public boolean isIgnoreGapsConsensus() { return ignoreGapsInConsensus; } public void setIgnoreBelowBackground(boolean state) { - if (this.ignoreBelowBackground != state) - { - ignoreBelowBackground = state; - } - ignoreBelowBackground = state; + hmmIgnoreBelowBackground = state; } - public boolean getIgnoreBelowBackground() + public boolean isIgnoreBelowBackground() { - return true; + return hmmIgnoreBelowBackground; + } + + public void setInfoLetterHeight(boolean state) + { + hmmUseInfoLetterHeight = state; + } + + public boolean isUseInfoLetterHeight() + { + return hmmUseInfoLetterHeight; } /** @@ -1389,39 +1416,16 @@ public class SequenceGroup implements AnnotatedCollectionI @Override public Iterable findAnnotation(String calcId) { - List 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 findAnnotations(SequenceI seq, String calcId, String label) { - ArrayList 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); } /** @@ -1432,17 +1436,8 @@ public class SequenceGroup implements AnnotatedCollectionI */ 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); } /** @@ -1452,7 +1447,10 @@ public class SequenceGroup implements AnnotatedCollectionI { synchronized (sequences) { + int before = sequences.size(); sequences.clear(); + changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before, + sequences.size()); } } @@ -1569,23 +1567,22 @@ public class SequenceGroup implements AnnotatedCollectionI public boolean isShowInformationHistogram() { - return showInformationHistogram; + return hmmShowHistogram; } public void setShowInformationHistogram(boolean state) { - if (showInformationHistogram != state && information != null) + if (hmmShowHistogram != state && hmmInformation != null) { - this.showInformationHistogram = state; + this.hmmShowHistogram = state; // recalcConservation(); TODO don't know what to do here next } - this.showInformationHistogram = state; + this.hmmShowHistogram = state; } public boolean isShowHMMSequenceLogo() { - // TODO Auto-generated method stub return showHMMSequenceLogo; } @@ -1597,8 +1594,7 @@ public class SequenceGroup implements AnnotatedCollectionI public boolean isNormaliseHMMSequenceLogo() { - // TODO Auto-generated method stub - return normaliseHMMSequenceLogo; + return hmmNormaliseSequenceLogo; } public void setNormaliseHMMSequenceLogo(boolean state) @@ -1606,4 +1602,31 @@ public class SequenceGroup implements AnnotatedCollectionI normaliseSequenceLogo = 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; + } + }