X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fdatamodel%2FSequenceGroup.java;h=59cb4bba01f851e4cacbbeab3f84b1cefd23657c;hb=3a7dc7069f6983ef56b5440b57cd3e62eeb383c7;hp=0bd7266e69abff83cbdca3e0873bb56837ec83f7;hpb=cfd4c0f73bdba694e2d854684a8a3f679ccdba27;p=jalview.git
diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java
index 0bd7266..59cb4bb 100755
--- a/src/jalview/datamodel/SequenceGroup.java
+++ b/src/jalview/datamodel/SequenceGroup.java
@@ -1,29 +1,40 @@
/*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
- * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along with Jalview. If not, see .
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see .
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.datamodel;
-import java.util.*;
+import jalview.analysis.AAFrequency;
+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;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-
-import java.awt.*;
-
-import jalview.analysis.*;
-import jalview.schemes.*;
+import java.util.Map;
/**
* Collects a set contiguous ranges on a set of sequences
@@ -33,13 +44,36 @@ import jalview.schemes.*;
*/
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 a 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;
-
+
Conservation conserve;
- Vector aaFrequency;
+ Conservation conservationData;
+
+ ProfilesI consensusProfiles;
+
+ ProfilesI hmmProfiles;
boolean displayBoxes = true;
@@ -47,31 +81,43 @@ public class SequenceGroup implements AnnotatedCollectionI
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;
+
+ /*
* after Olivier's non-conserved only character display
*/
boolean showNonconserved = false;
- /**
- * group members
+ /*
+ * sequences in the group
*/
- private Vector sequences = new Vector();
+ private List sequences;
- /**
+ /*
* representative sequence for this group (if any)
*/
private SequenceI seqrep = null;
int width = -1;
- /**
- * Colourscheme applied to group if any
+ /*
+ * colour scheme applied to group if any
*/
- public ColourSchemeI cs;
+ public ResidueShaderI cs;
- int startRes = 0;
+ /**
+ * start column (base 0)
+ */
+ private int startRes = 0;
- int endRes = 0;
+ /**
+ * end column (base 0)
+ */
+ private int endRes = 0;
public Color outlineColour = Color.black;
@@ -83,35 +129,58 @@ public class SequenceGroup implements AnnotatedCollectionI
public Color textColour2 = Color.white;
- /**
- * consensus calculation property
+ /*
+ * properties for consensus annotation
*/
private boolean ignoreGapsInConsensus = true;
- /**
- * consensus calculation property
- */
private boolean showSequenceLogo = false;
- /**
- * flag indicating if logo should be rendered normalised
- */
private boolean normaliseSequenceLogo;
- /**
- * @return the includeAllConsSymbols
+ /*
+ * properties for HMM information annotation
*/
- public boolean isShowSequenceLogo()
- {
- return showSequenceLogo;
- }
+ 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;
+
+ /*
+ * visibility of columns intersecting this group
+ */
+ private boolean hidecols;
+
+ AlignmentAnnotation consensus = null;
+
+ AlignmentAnnotation conservation = null;
+
+ private AlignmentAnnotation hmmInformation;
+
+ private boolean showConsensusHistogram;
+
+ private AnnotatedCollectionI context;
+
/**
- * Creates a new SequenceGroup object.
+ * Constructor, assigning a generated default name of "JGroup:" with object
+ * hashcode appended
*/
public SequenceGroup()
{
groupName = "JGroup:" + this.hashCode();
+ cs = new ResidueShader();
+ sequences = new ArrayList<>();
}
/**
@@ -128,16 +197,17 @@ public class SequenceGroup implements AnnotatedCollectionI
* @param end
* last column of group
*/
- public SequenceGroup(Vector sequences, String groupName,
+ public SequenceGroup(List sequences, String groupName,
ColourSchemeI scheme, boolean displayBoxes, boolean displayText,
boolean colourText, int start, int end)
{
+ this();
this.sequences = sequences;
this.groupName = groupName;
this.displayBoxes = displayBoxes;
this.displayText = displayText;
this.colourText = colourText;
- this.cs = scheme;
+ this.cs = new ResidueShader(scheme);
startRes = start;
endRes = end;
recalcConservation();
@@ -147,18 +217,17 @@ public class SequenceGroup implements AnnotatedCollectionI
* copy constructor
*
* @param seqsel
+ * @param keepsequences
+ * if false do not add sequences from seqsel to new instance
*/
public SequenceGroup(SequenceGroup seqsel)
{
+ this();
+
if (seqsel != null)
{
- sequences = new Vector();
- Enumeration sq = seqsel.sequences.elements();
- while (sq.hasMoreElements())
- {
- sequences.addElement(sq.nextElement());
- }
- ;
+ sequences = new ArrayList<>();
+ sequences.addAll(seqsel.sequences);
if (seqsel.groupName != null)
{
groupName = new String(seqsel.groupName);
@@ -166,13 +235,23 @@ public class SequenceGroup implements AnnotatedCollectionI
displayBoxes = seqsel.displayBoxes;
displayText = seqsel.displayText;
colourText = seqsel.colourText;
+
startRes = seqsel.startRes;
endRes = seqsel.endRes;
- cs = seqsel.cs;
+ cs = new ResidueShader((ResidueShader) seqsel.cs);
if (seqsel.description != null)
+ {
description = new String(seqsel.description);
+ }
hidecols = seqsel.hidecols;
hidereps = seqsel.hidereps;
+ showNonconserved = seqsel.showNonconserved;
+ 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;
@@ -181,14 +260,34 @@ public class SequenceGroup implements AnnotatedCollectionI
thresholdTextColour = seqsel.thresholdTextColour;
width = seqsel.width;
ignoreGapsInConsensus = seqsel.ignoreGapsInConsensus;
+ hmmIgnoreBelowBackground = seqsel.hmmIgnoreBelowBackground;
+ hmmUseInfoLetterHeight = seqsel.hmmUseInfoLetterHeight;
if (seqsel.conserve != null)
{
+ // todo avoid doing this if we don't actually want derived calculations
+ // !
recalcConservation(); // safer than
// aaFrequency = (Vector) seqsel.aaFrequency.clone(); // ??
}
}
}
+ /**
+ * Constructor that copies the given list of sequences
+ *
+ * @param seqs
+ */
+ public SequenceGroup(List seqs)
+ {
+ this();
+ this.sequences.addAll(seqs);
+ }
+
+ public boolean isShowSequenceLogo()
+ {
+ return showSequenceLogo;
+ }
+
public SequenceI[] getSelectionAsNewSequences(AlignmentI align)
{
int iSize = sequences.size();
@@ -203,7 +302,7 @@ public class SequenceGroup implements AnnotatedCollectionI
if (seqs[ipos] != null)
{
seqs[ipos].setDescription(seq.getDescription());
- seqs[ipos].setDBRef(seq.getDBRef());
+ seqs[ipos].setDBRefs(seq.getDBRefs());
seqs[ipos].setSequenceFeatures(seq.getSequenceFeatures());
if (seq.getDatasetSequence() != null)
{
@@ -230,7 +329,9 @@ public class SequenceGroup implements AnnotatedCollectionI
}
}
if (!found)
+ {
continue;
+ }
}
AlignmentAnnotation newannot = new AlignmentAnnotation(
seq.getAnnotation()[a]);
@@ -286,26 +387,27 @@ public class SequenceGroup implements AnnotatedCollectionI
return eres;
}
+ @Override
public List getSequences()
{
return sequences;
}
+ @Override
public List getSequences(
Map hiddenReps)
{
if (hiddenReps == null)
{
+ // TODO: need a synchronizedCollection here ?
return sequences;
}
else
{
- Vector allSequences = new Vector();
- SequenceI seq;
- for (int i = 0; i < sequences.size(); i++)
+ List allSequences = new ArrayList<>();
+ for (SequenceI seq : sequences)
{
- seq = (SequenceI) sequences.elementAt(i);
- allSequences.addElement(seq);
+ allSequences.add(seq);
if (hiddenReps.containsKey(seq))
{
SequenceCollectionI hsg = hiddenReps.get(seq);
@@ -313,7 +415,7 @@ public class SequenceGroup implements AnnotatedCollectionI
{
if (seq2 != seq && !allSequences.contains(seq2))
{
- allSequences.addElement(seq2);
+ allSequences.add(seq2);
}
}
}
@@ -457,55 +559,103 @@ public class SequenceGroup implements AnnotatedCollectionI
*/
public void addSequence(SequenceI s, boolean recalc)
{
- if (s != null && !sequences.contains(s))
+ synchronized (sequences)
{
- sequences.addElement(s);
- }
+ if (s != null && !sequences.contains(s))
+ {
+ sequences.add(s);
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED,
+ sequences.size() - 1, sequences.size());
+ }
- if (recalc)
- {
- recalcConservation();
+ if (recalc)
+ {
+ recalcConservation();
+ }
}
}
/**
- * Max Gaps Threshold for performing a conservation calculation TODO: make
- * this a configurable property - or global to an alignment view
+ * Max Gaps Threshold (percent) for performing a conservation calculation
*/
private int consPercGaps = 25;
/**
- * calculate residue conservation for group - but only if necessary.
+ * @return Max Gaps Threshold for performing a conservation calculation
*/
- public void recalcConservation()
+ public int getConsPercGaps()
{
- if (cs == null && consensus == null && conservation == null)
- {
- return;
- }
- if (cs != null)
+ return consPercGaps;
+ }
+
+ /**
+ * set Max Gaps Threshold (percent) for performing a conservation calculation
+ *
+ * @param consPercGaps
+ */
+ public void setConsPercGaps(int consPercGaps)
+ {
+ this.consPercGaps = consPercGaps;
+ }
+
+ /**
+ * calculate residue conservation and colourschemes for group - but only if
+ * necessary. returns true if the calculation resulted in a visible change to
+ * group
+ */
+ public boolean recalcConservation()
+ {
+ return recalcConservation(false);
+ }
+
+ /**
+ * 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)
+ {
+ if (cs == null && consensus == null && conservation == null
+ && hmmInformation == null)
{
- cs.alignmentChanged(this, null);
+ return false;
}
+ // TODO: try harder to detect changes in state in order to minimise
+ // recalculation effort
+ boolean upd = false;
try
{
- Hashtable cnsns[] = AAFrequency.calculate(sequences, startRes,
+ 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);
+ _updateConsensusRow(cnsns, sequences.size());
+ upd = true;
}
if (cs != null)
{
cs.setConsensus(cnsns);
- cs.alignmentChanged(this, null);
+ upd = true;
}
if ((conservation != null)
|| (cs != null && cs.conservationApplied()))
{
- Conservation c = new Conservation(groupName,
- ResidueProperties.propHash, 3, sequences, startRes,
+ Conservation c = new Conservation(groupName, sequences, startRes,
endRes + 1);
c.calculate();
c.verdict(false, consPercGaps);
@@ -518,16 +668,27 @@ public class SequenceGroup implements AnnotatedCollectionI
if (cs.conservationApplied())
{
cs.setConservation(c);
- cs.alignmentChanged(this, null);
}
}
+ // eager update - will cause a refresh of overview regardless
+ upd = true;
+ }
+ if (cs != null && !defer)
+ {
+ // TODO: JAL-2034 should cs.alignmentChanged modify return state
+ cs.alignmentChanged(context != null ? context : this, null);
+ return true;
+ }
+ else
+ {
+ return upd;
}
} catch (java.lang.OutOfMemoryError err)
{
// TODO: catch OOM
System.out.println("Out of memory loading groups: " + err);
}
-
+ return upd;
}
private void _updateConservationRow(Conservation c)
@@ -541,8 +702,10 @@ public class SequenceGroup implements AnnotatedCollectionI
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
@@ -550,9 +713,9 @@ public class SequenceGroup implements AnnotatedCollectionI
c.completeAnnotations(conservation, null, startRes, endRes + 1);
}
- public Hashtable[] consensusData = null;
+ public ProfilesI consensusData = null;
- private void _updateConsensusRow(Hashtable[] cnsns)
+ private void _updateConsensusRow(ProfilesI cnsns, long nseq)
{
if (consensus == null)
{
@@ -562,16 +725,46 @@ public class SequenceGroup implements AnnotatedCollectionI
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
AAFrequency.completeConsensus(consensus, cnsns, startRes, endRes + 1,
- ignoreGapsInConsensus, showSequenceLogo); // TODO: setting container
- // for
- // ignoreGapsInConsensusCalculation);
+ ignoreGapsInConsensus, showSequenceLogo, nseq); // TODO: setting
+ // container
+ // for
+ // ignoreGapsInConsensusCalculation);
+ }
+
+ /**
+ * 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);
}
/**
@@ -583,31 +776,39 @@ public class SequenceGroup implements AnnotatedCollectionI
*/
public void addOrRemove(SequenceI s, boolean recalc)
{
- if (sequences.contains(s))
+ synchronized (sequences)
{
- deleteSequence(s, recalc);
- }
- else
- {
- addSequence(s, recalc);
+ if (sequences.contains(s))
+ {
+ deleteSequence(s, recalc);
+ }
+ else
+ {
+ addSequence(s, recalc);
+ }
}
}
/**
- * DOCUMENT ME!
+ * remove
*
* @param s
- * DOCUMENT ME!
+ * to be removed
* @param recalc
- * DOCUMENT ME!
+ * true means recalculate conservation
*/
public void deleteSequence(SequenceI s, boolean recalc)
{
- sequences.removeElement(s);
-
- if (recalc)
+ synchronized (sequences)
{
- recalcConservation();
+ sequences.remove(s);
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED,
+ sequences.size() + 1, sequences.size());
+
+ if (recalc)
+ {
+ recalcConservation();
+ }
}
}
@@ -616,6 +817,7 @@ public class SequenceGroup implements AnnotatedCollectionI
*
* @return the first column selected by this group. Runs from 0<=i 0)
- {
- width = ((SequenceI) sequences.elementAt(0)).getLength();
- }
-
- for (int i = 1; i < sequences.size(); i++)
+ synchronized (sequences)
{
- SequenceI seq = (SequenceI) sequences.elementAt(i);
-
- if (seq.getLength() > width)
+ // MC This needs to get reset when characters are inserted and deleted
+ boolean first = true;
+ for (SequenceI seq : sequences)
{
- width = seq.getLength();
+ if (first || seq.getLength() > width)
+ {
+ width = seq.getLength();
+ first = false;
+ }
}
+ return width;
}
-
- return width;
}
/**
@@ -810,39 +1010,42 @@ public class SequenceGroup implements AnnotatedCollectionI
*/
public SequenceI[] getSequencesInOrder(AlignmentI al, boolean trim)
{
- int sSize = sequences.size();
- int alHeight = al.getHeight();
+ synchronized (sequences)
+ {
+ int sSize = sequences.size();
+ int alHeight = al.getHeight();
- SequenceI[] seqs = new SequenceI[(trim) ? sSize : alHeight];
+ SequenceI[] seqs = new SequenceI[(trim) ? sSize : alHeight];
- int index = 0;
- for (int i = 0; i < alHeight && index < sSize; i++)
- {
- if (sequences.contains(al.getSequenceAt(i)))
+ int index = 0;
+ for (int i = 0; i < alHeight && index < sSize; i++)
{
- seqs[(trim) ? index : i] = al.getSequenceAt(i);
- index++;
+ if (sequences.contains(al.getSequenceAt(i)))
+ {
+ seqs[(trim) ? index : i] = al.getSequenceAt(i);
+ index++;
+ }
}
- }
- if (index == 0)
- {
- return null;
- }
- if (!trim)
- {
- return seqs;
- }
- if (index < seqs.length)
- {
- SequenceI[] dummy = seqs;
- seqs = new SequenceI[index];
- while (--index >= 0)
+ if (index == 0)
+ {
+ return null;
+ }
+ if (!trim)
{
- seqs[index] = dummy[index];
- dummy[index] = null;
+ return seqs;
}
+ if (index < seqs.length)
+ {
+ SequenceI[] dummy = seqs;
+ seqs = new SequenceI[index];
+ while (--index >= 0)
+ {
+ seqs[index] = dummy[index];
+ dummy[index] = null;
+ }
+ }
+ return seqs;
}
- return seqs;
}
/**
@@ -865,6 +1068,7 @@ public class SequenceGroup implements AnnotatedCollectionI
/**
* @return the representative sequence for this group
*/
+ @Override
public SequenceI getSeqrep()
{
return seqrep;
@@ -877,6 +1081,7 @@ public class SequenceGroup implements AnnotatedCollectionI
* @param seqrep
* the seqrep to set (null means no sequence representative)
*/
+ @Override
public void setSeqrep(SequenceI seqrep)
{
this.seqrep = seqrep;
@@ -886,17 +1091,13 @@ public class SequenceGroup implements AnnotatedCollectionI
*
* @return true if group has a sequence representative
*/
+ @Override
public boolean hasSeqrep()
{
return seqrep != null;
}
/**
- * visibility of rows or represented rows covered by group
- */
- private boolean hidereps = false;
-
- /**
* set visibility of sequences covered by (if no sequence representative is
* defined) or represented by this group.
*
@@ -918,11 +1119,6 @@ public class SequenceGroup implements AnnotatedCollectionI
}
/**
- * visibility of columns intersecting this group
- */
- private boolean hidecols = false;
-
- /**
* set intended visibility of columns covered by this group
*
* @param visibility
@@ -956,23 +1152,14 @@ public class SequenceGroup implements AnnotatedCollectionI
{
SequenceGroup sgroup = new SequenceGroup(this);
SequenceI[] insect = getSequencesInOrder(alignment);
- sgroup.sequences = new Vector();
+ sgroup.sequences = new ArrayList<>();
for (int s = 0; insect != null && s < insect.length; s++)
{
if (map == null || map.containsKey(insect[s]))
{
- sgroup.sequences.addElement(insect[s]);
+ sgroup.sequences.add(insect[s]);
}
}
- // Enumeration en =getSequences(hashtable).elements();
- // while (en.hasMoreElements())
- // {
- // SequenceI elem = (SequenceI) en.nextElement();
- // if (alignment.getSequences().contains(elem))
- // {
- // sgroup.addSequence(elem, false);
- // }
- // }
return sgroup;
}
@@ -993,13 +1180,6 @@ public class SequenceGroup implements AnnotatedCollectionI
this.showNonconserved = displayNonconserved;
}
- AlignmentAnnotation consensus = null, conservation = null;
-
- /**
- * flag indicating if consensus histogram should be rendered
- */
- private boolean showConsensusHistogram;
-
/**
* set this alignmentAnnotation object as the one used to render consensus
* annotation
@@ -1016,7 +1196,8 @@ public class SequenceGroup implements AnnotatedCollectionI
/**
*
- * @return automatically calculated consensus row
+ * @return automatically calculated consensus row note: the row is a stub if a
+ * consensus calculation has not yet been performed on the group
*/
public AlignmentAnnotation getConsensus()
{
@@ -1043,6 +1224,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
*
@@ -1095,9 +1292,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
{
@@ -1128,6 +1326,26 @@ public class SequenceGroup implements AnnotatedCollectionI
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
@@ -1191,24 +1409,31 @@ public class SequenceGroup implements AnnotatedCollectionI
{
// TODO add in other methods like 'getAlignmentAnnotation(String label),
// etc'
- ArrayList annot = new ArrayList();
- for (SequenceI seq : (Vector) sequences)
+ ArrayList annot = new ArrayList<>();
+ synchronized (sequences)
{
- for (AlignmentAnnotation al : seq.getAnnotation())
+ for (SequenceI seq : sequences)
{
- if (al.groupRef == this)
+ AlignmentAnnotation[] aa = seq.getAnnotation();
+ if (aa != null)
{
- annot.add(al);
+ for (AlignmentAnnotation al : aa)
+ {
+ if (al.groupRef == this)
+ {
+ annot.add(al);
+ }
+ }
}
}
- }
- if (consensus != null)
- {
- annot.add(consensus);
- }
- if (conservation != null)
- {
- annot.add(conservation);
+ if (consensus != null)
+ {
+ annot.add(consensus);
+ }
+ if (conservation != null)
+ {
+ annot.add(conservation);
+ }
}
return annot.toArray(new AlignmentAnnotation[0]);
}
@@ -1216,19 +1441,218 @@ public class SequenceGroup implements AnnotatedCollectionI
@Override
public Iterable findAnnotation(String calcId)
{
- ArrayList aa = new ArrayList();
- for (AlignmentAnnotation a : getAlignmentAnnotation())
+ return AlignmentAnnotation.findAnnotation(
+ Arrays.asList(getAlignmentAnnotation()), calcId);
+ }
+
+ @Override
+ public Iterable findAnnotations(SequenceI seq,
+ String calcId, String label)
+ {
+ return AlignmentAnnotation.findAnnotations(
+ Arrays.asList(getAlignmentAnnotation()), seq, calcId, label);
+ }
+
+ /**
+ * Answer true if any annotation matches the calcId passed in (if not null).
+ *
+ * @param calcId
+ * @return
+ */
+ public boolean hasAnnotation(String calcId)
+ {
+ return AlignmentAnnotation
+ .hasAnnotation(Arrays.asList(getAlignmentAnnotation()), calcId);
+ }
+
+ /**
+ * Remove all sequences from the group (leaving other properties unchanged).
+ */
+ public void clear()
+ {
+ synchronized (sequences)
{
- if (a.getCalcId() == calcId)
+ int before = sequences.size();
+ sequences.clear();
+ changeSupport.firePropertyChange(SEQ_GROUP_CHANGED, before,
+ sequences.size());
+ }
+ }
+
+ /**
+ * Sets the alignment or group context for this group, and whether it is
+ * defined as a group
+ *
+ * @param ctx
+ * the context for the group
+ * @param defined
+ * whether the group is defined on the alignment or is just a
+ * selection
+ * @throws IllegalArgumentException
+ * if setting the context would result in a circular reference chain
+ */
+ public void setContext(AnnotatedCollectionI ctx, boolean defined)
+ {
+ setContext(ctx);
+ this.isDefined = defined;
+ }
+
+ /**
+ * Sets the alignment or group context for this group
+ *
+ * @param ctx
+ * the context for the group
+ * @throws IllegalArgumentException
+ * if setting the context would result in a circular reference chain
+ */
+ public void setContext(AnnotatedCollectionI ctx)
+ {
+ AnnotatedCollectionI ref = ctx;
+ while (ref != null)
+ {
+ if (ref == this || ref.getContext() == ctx)
{
- aa.add(a);
+ throw new IllegalArgumentException(
+ "Circular reference in SequenceGroup.context");
}
+ ref = ref.getContext();
}
- return aa;
+ this.context = ctx;
}
- public void clear()
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.datamodel.AnnotatedCollectionI#getContext()
+ */
+ @Override
+ public AnnotatedCollectionI getContext()
+ {
+ return context;
+ }
+
+ public boolean isDefined()
+ {
+ return isDefined;
+ }
+
+ public void setColourScheme(ColourSchemeI scheme)
+ {
+ if (cs == null)
+ {
+ cs = new ResidueShader();
+ }
+ cs.setColourScheme(scheme);
+ }
+
+ public void setGroupColourScheme(ResidueShaderI scheme)
+ {
+ cs = scheme;
+ }
+
+ public ColourSchemeI getColourScheme()
+ {
+ return cs == null ? null : cs.getColourScheme();
+ }
+
+ public ResidueShaderI getGroupColourScheme()
+ {
+ return cs;
+ }
+
+ @Override
+ public boolean isNucleotide()
+ {
+ if (context != null)
+ {
+ return context.isNucleotide();
+ }
+ return false;
+ }
+
+ /**
+ * @param seq
+ * @return true if seq is a member of the group
+ */
+
+ public boolean contains(SequenceI seq1)
+ {
+ return sequences.contains(seq1);
+ }
+
+ /**
+ * @param seq
+ * @param apos
+ * @return true if startRes<=apos and endRes>=apos and seq is in the group
+ */
+ public boolean contains(SequenceI seq, int apos)
+ {
+ return (startRes <= apos && endRes >= apos) && sequences.contains(seq);
+ }
+
+ public boolean isShowInformationHistogram()
{
- sequences.clear();
+ 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;
+ }
+
+ public ProfilesI getConsensusData()
+ {
+ return consensusProfiles;
+ }
+
+ public ProfilesI getHmmProfiles()
+ {
+ return hmmProfiles;
+ }
+
+ public void setHmmProfiles(ProfilesI hmmProfiles)
+ {
+ this.hmmProfiles = hmmProfiles;
+ }
+
+ @Override
+ public List getHmmSequences()
+ {
+ List result = new ArrayList<>();
+ for (int i = 0; i < sequences.size(); i++)
+ {
+ SequenceI seq = sequences.get(i);
+ if (seq.hasHMMProfile())
+ {
+ result.add(seq);
+ }
+ }
+ return result;
+ }
+
}