X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FSequenceGroup.java;h=861595c55887924cedcba261d7028fdcc5e17837;hb=afffa24481a7d3cb65ae41e0948c16a5f490f302;hp=fbcf3031ddccae71e49a0c607afd8569656734db;hpb=b1cf67d148cd9cca4a12d245b6dad85a0a7376c7;p=jalview.git
diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java
index fbcf303..861595c 100755
--- a/src/jalview/datamodel/SequenceGroup.java
+++ b/src/jalview/datamodel/SequenceGroup.java
@@ -1,29 +1,38 @@
/*
- * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
- * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
*
- * This program 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 2
- * of the License, or (at your option) any later version.
+ * This file is part of Jalview.
*
- * This program 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.
+ * 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.
+ *
+ * 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ * along with Jalview. If not, see .
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.datamodel;
-import java.util.*;
-
-import java.awt.*;
+import jalview.analysis.AAFrequency;
+import jalview.analysis.Conservation;
+import jalview.renderer.ResidueShader;
+import jalview.renderer.ResidueShaderI;
+import jalview.schemes.ColourSchemeI;
-import jalview.analysis.*;
-import jalview.schemes.*;
+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;
/**
* Collects a set contiguous ranges on a set of sequences
@@ -31,43 +40,77 @@ import jalview.schemes.*;
* @author $author$
* @version $Revision$
*/
-public class SequenceGroup
+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;
Conservation conserve;
- Vector aaFrequency;
-
boolean displayBoxes = true;
boolean displayText = true;
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 showUnconserved = false;
-
+ boolean showNonconserved = false;
+
/**
* group members
*/
- 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 */
- public ColourSchemeI cs;
+ * Colourscheme applied to group if any
+ */
+ 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;
@@ -82,20 +125,35 @@ public class SequenceGroup
/**
* consensus calculation property
*/
- private boolean ignoreGapsInConsensus=true;
+ private boolean ignoreGapsInConsensus = true;
+
/**
* consensus calculation property
*/
- private boolean showSequenceLogo=false;
+ private boolean showSequenceLogo = false;
/**
- * @return the includeAllConsSymbols
+ * flag indicating if logo should be rendered normalised
*/
- public boolean isShowSequenceLogo()
- {
- return showSequenceLogo;
- }
+ private boolean normaliseSequenceLogo;
+ /*
+ * visibility of rows or represented rows covered by group
+ */
+ private boolean hidereps = false;
+
+ /*
+ * visibility of columns intersecting this group
+ */
+ private boolean hidecols = false;
+
+ AlignmentAnnotation consensus = null;
+
+ AlignmentAnnotation conservation = null;
+
+ private boolean showConsensusHistogram;
+
+ private AnnotatedCollectionI context;
/**
* Creates a new SequenceGroup object.
@@ -103,6 +161,8 @@ public class SequenceGroup
public SequenceGroup()
{
groupName = "JGroup:" + this.hashCode();
+ cs = new ResidueShader();
+ sequences = new ArrayList<>();
}
/**
@@ -115,51 +175,59 @@ public class SequenceGroup
* @param displayText
* @param colourText
* @param start
- * first column of group
+ * first column of group
* @param end
- * last column of group
+ * 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();
}
+
/**
* copy constructor
+ *
* @param seqsel
*/
public SequenceGroup(SequenceGroup seqsel)
{
- if (seqsel!=null)
+ this();
+ if (seqsel != null)
{
- sequences=new Vector();
- Enumeration sq = seqsel.sequences.elements();
- while (sq.hasMoreElements()) {
- sequences.addElement(sq.nextElement());
- };
- if (seqsel.groupName!=null)
+ sequences = new ArrayList<>();
+ sequences.addAll(seqsel.sequences);
+ if (seqsel.groupName != null)
{
groupName = new String(seqsel.groupName);
}
displayBoxes = seqsel.displayBoxes;
displayText = seqsel.displayText;
colourText = seqsel.colourText;
+
startRes = seqsel.startRes;
endRes = seqsel.endRes;
- cs =seqsel.cs;
- if (seqsel.description!=null)
+ 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;
idColour = seqsel.idColour;
outlineColour = seqsel.outlineColour;
seqrep = seqsel.seqrep;
@@ -168,14 +236,30 @@ public class SequenceGroup
thresholdTextColour = seqsel.thresholdTextColour;
width = seqsel.width;
ignoreGapsInConsensus = seqsel.ignoreGapsInConsensus;
- if (seqsel.conserve!=null)
+ if (seqsel.conserve != null)
{
- recalcConservation(); // safer than
+ 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();
@@ -185,16 +269,15 @@ public class SequenceGroup
for (int i = 0, ipos = 0; i < inorder.length; i++)
{
SequenceI seq = inorder[i];
-
- seqs[ipos] = seq.getSubSequence(startRes, endRes + 1);
- if (seqs[ipos] != null)
+ SequenceI seqipos = seqs[ipos] = seq.getSubSequence(startRes, endRes + 1);
+ if (seqipos != null)
{
- seqs[ipos].setDescription(seq.getDescription());
- seqs[ipos].setDBRef(seq.getDBRef());
- seqs[ipos].setSequenceFeatures(seq.getSequenceFeatures());
+ seqipos.setDescription(seq.getDescription());
+ seqipos.setDBRefs(seq.getDBRefs());
+ seqipos.setSequenceFeatures(seq.getSequenceFeatures());
if (seq.getDatasetSequence() != null)
{
- seqs[ipos].setDatasetSequence(seq.getDatasetSequence());
+ seqipos.setDatasetSequence(seq.getDatasetSequence());
}
if (seq.getAnnotation() != null)
@@ -208,7 +291,7 @@ public class SequenceGroup
if (alann != null)
{
boolean found = false;
- for (int pos = 0; pos < alann.length; pos++)
+ for (int pos = 0, np = alann.length; pos < np; pos++)
{
if (alann[pos] == tocopy)
{
@@ -217,14 +300,16 @@ public class SequenceGroup
}
}
if (!found)
+ {
continue;
+ }
}
- AlignmentAnnotation newannot = new AlignmentAnnotation(seq
- .getAnnotation()[a]);
+ AlignmentAnnotation newannot = new AlignmentAnnotation(
+ seq.getAnnotation()[a]);
newannot.restrict(startRes, endRes);
newannot.setSequenceRef(seqs[ipos]);
newannot.adjustForAlignment();
- seqs[ipos].addAlignmentAnnotation(newannot);
+ seqipos.addAlignmentAnnotation(newannot);
}
}
ipos++;
@@ -248,7 +333,7 @@ public class SequenceGroup
* If sequence ends in gaps, the end residue can be correctly calculated here
*
* @param seq
- * SequenceI
+ * SequenceI
* @return int
*/
public int findEndRes(SequenceI seq)
@@ -273,29 +358,35 @@ public class SequenceGroup
return eres;
}
- public Vector getSequences(Hashtable hiddenReps)
+ @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, seq2;
- 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))
{
- SequenceGroup hsg = (SequenceGroup) hiddenReps.get(seq);
- for (int h = 0; h < hsg.getSize(); h++)
+ SequenceCollectionI hsg = hiddenReps.get(seq);
+ for (SequenceI seq2 : hsg.getSequences())
{
- seq2 = hsg.getSequenceAt(h);
if (seq2 != seq && !allSequences.contains(seq2))
{
- allSequences.addElement(seq2);
+ allSequences.add(seq2);
}
}
}
@@ -305,27 +396,22 @@ public class SequenceGroup
}
}
- public SequenceI[] getSequencesAsArray(Hashtable hiddenReps)
+ public SequenceI[] getSequencesAsArray(
+ Map map)
{
- Vector tmp = getSequences(hiddenReps);
+ List tmp = getSequences(map);
if (tmp == null)
{
return null;
}
- SequenceI[] result = new SequenceI[tmp.size()];
- for (int i = 0; i < result.length; i++)
- {
- result[i] = (SequenceI) tmp.elementAt(i);
- }
-
- return result;
+ return tmp.toArray(new SequenceI[tmp.size()]);
}
/**
* DOCUMENT ME!
*
* @param col
- * DOCUMENT ME!
+ * DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@@ -359,7 +445,7 @@ public class SequenceGroup
* DOCUMENT ME!
*
* @param col
- * DOCUMENT ME!
+ * DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
@@ -398,7 +484,7 @@ public class SequenceGroup
* DOCUMENT ME!
*
* @param name
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void setName(String name)
{
@@ -425,7 +511,7 @@ public class SequenceGroup
* DOCUMENT ME!
*
* @param c
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void setConservation(Conservation c)
{
@@ -433,201 +519,281 @@ public class SequenceGroup
}
/**
- * Add s to this sequence group
+ * Add s to this sequence group. If aligment sequence is already contained in
+ * group, it will not be added again, but recalculation may happen if the flag
+ * is set.
*
* @param s
- * alignment sequence to be added
+ * alignment sequence to be added
* @param recalc
- * true means Group's conservation should be recalculated
+ * true means Group's conservation should be recalculated
*/
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;
+
+ /**
+ * @return Max Gaps Threshold for performing a conservation calculation
+ */
+ public int getConsPercGaps()
+ {
+ 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
*/
- private int consPercGaps=25;
+ public boolean recalcConservation()
+ {
+ return recalcConservation(false);
+ }
+
/**
- * calculate residue conservation for group - but only if necessary.
+ * calculate residue conservation for group - but only if necessary. 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 void recalcConservation()
+ public boolean recalcConservation(boolean defer)
{
if (cs == null && consensus == null && conservation == null)
{
- return;
+ 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, endRes + 1, showSequenceLogo);
+ ProfilesI cnsns = AAFrequency.calculate(sequences, startRes,
+ endRes + 1, showSequenceLogo);
if (consensus != null)
{
- _updateConsensusRow(cnsns);
+ _updateConsensusRow(cnsns, sequences.size());
+ upd = true;
}
- if (cs!=null)
+ if (cs != null)
{
cs.setConsensus(cnsns);
-
- if (cs instanceof ClustalxColourScheme)
- {
- ((ClustalxColourScheme) cs).resetClustalX(sequences, getWidth());
- }
+ upd = true;
}
- if ((conservation!=null) || (cs!=null && cs.conservationApplied()))
+ 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);
- if (conservation!=null)
+ if (conservation != null)
{
_updateConservationRow(c);
}
- if (cs!=null)
+ if (cs != null)
{
- cs.setConservation(c);
-
- if (cs instanceof ClustalxColourScheme)
- {
- ((ClustalxColourScheme) cs).resetClustalX(sequences, getWidth());
- }
+ if (cs.conservationApplied())
+ {
+ cs.setConservation(c);
+ }
}
+ // 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)
{
- if (conservation==null)
+ if (conservation == null)
{
getConservation();
}
// update Labels
- conservation.label = "Conservation for "+getName();
- conservation.description = "Conservation for group "+getName()+" less than " + consPercGaps
- + "% gaps";
+ conservation.label = "Conservation for " + getName();
+ conservation.description = "Conservation for group " + getName()
+ + " less than " + consPercGaps + "% gaps";
// preserve width if already set
- int aWidth = (conservation.annotations!=null) ? (endRes 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;
}
/**
* DOCUMENT ME!
*
* @param c
- * DOCUMENT ME!
+ * DOCUMENT ME!
*/
public void setOutlineColour(Color c)
{
@@ -760,42 +918,66 @@ public class SequenceGroup
/**
*
* returns the sequences in the group ordered by the ordering given by al.
- * this used to return an array with null entries regardless, new behaviour is below.
- * TODO: verify that this does not affect use in applet or application
+ * this used to return an array with null entries regardless, new behaviour is
+ * below. TODO: verify that this does not affect use in applet or application
+ *
* @param al
- * Alignment
- * @return SequenceI[] intersection of sequences in group with al, ordered by al, or null if group does not intersect with al
+ * Alignment
+ * @return SequenceI[] intersection of sequences in group with al, ordered by
+ * al, or null if group does not intersect with al
*/
public SequenceI[] getSequencesInOrder(AlignmentI al)
{
- int sSize = sequences.size();
- int alHeight = al.getHeight();
-
- SequenceI[] seqs = new SequenceI[sSize];
+ return getSequencesInOrder(al, true);
+ }
- int index = 0;
- for (int i = 0; i < alHeight && index < sSize; i++)
+ /**
+ * return an array representing the intersection of the group with al,
+ * optionally returning an array the size of al.getHeight() where nulls mark
+ * the non-intersected sequences
+ *
+ * @param al
+ * @param trim
+ * @return null or array
+ */
+ public SequenceI[] getSequencesInOrder(AlignmentI al, boolean trim)
+ {
+ synchronized (sequences)
{
- if (sequences.contains(al.getSequenceAt(i)))
+ int sSize = sequences.size();
+ int alHeight = al.getHeight();
+
+ SequenceI[] seqs = new SequenceI[(trim) ? sSize : alHeight];
+
+ int index = 0;
+ for (int i = 0; i < alHeight && index < sSize; i++)
{
- seqs[index++] = al.getSequenceAt(i);
+ if (sequences.contains(al.getSequenceAt(i)))
+ {
+ seqs[(trim) ? index : i] = al.getSequenceAt(i);
+ index++;
+ }
}
- }
- if (index==0)
- {
- return null;
- }
- if (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;
}
/**
@@ -808,7 +990,7 @@ public class SequenceGroup
/**
* @param idColour
- * the idColour to set
+ * the idColour to set
*/
public void setIdColour(Color idColour)
{
@@ -818,61 +1000,66 @@ public class SequenceGroup
/**
* @return the representative sequence for this group
*/
+ @Override
public SequenceI getSeqrep()
{
return seqrep;
}
/**
- * set the representative sequence for this group.
- * Note - this affects the interpretation of the Hidereps attribute.
- * @param seqrep the seqrep to set (null means no sequence representative)
+ * set the representative sequence for this group. Note - this affects the
+ * interpretation of the Hidereps attribute.
+ *
+ * @param seqrep
+ * the seqrep to set (null means no sequence representative)
*/
+ @Override
public void setSeqrep(SequenceI seqrep)
{
this.seqrep = seqrep;
}
+
/**
*
* @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.
+ * set visibility of sequences covered by (if no sequence representative is
+ * defined) or represented by this group.
+ *
* @param visibility
*/
public void setHidereps(boolean visibility)
{
hidereps = visibility;
}
+
/**
*
- * @return true if sequences represented (or covered) by this group should be hidden
+ * @return true if sequences represented (or covered) by this group should be
+ * hidden
*/
public boolean isHidereps()
{
return hidereps;
}
- /**
- * visibility of columns intersecting this group
- */
- private boolean hidecols=false;
+
/**
* set intended visibility of columns covered by this group
+ *
* @param visibility
*/
public void setHideCols(boolean visibility)
{
hidecols = visibility;
}
+
/**
*
* @return true if columns covered by group should be hidden
@@ -881,62 +1068,68 @@ public class SequenceGroup
{
return hidecols;
}
+
/**
- * create a new sequence group from the intersection of this group
- * with an alignment Hashtable of hidden representatives
+ * create a new sequence group from the intersection of this group with an
+ * alignment Hashtable of hidden representatives
*
- * @param alignment (may not be null)
- * @param hashtable (may be null)
+ * @param alignment
+ * (may not be null)
+ * @param map
+ * (may be null)
* @return new group containing sequences common to this group and alignment
*/
- public SequenceGroup intersect(AlignmentI alignment, Hashtable hashtable)
+ public SequenceGroup intersect(AlignmentI alignment,
+ Map map)
{
SequenceGroup sgroup = new SequenceGroup(this);
- SequenceI[] insect=getSequencesInOrder(alignment);
- sgroup.sequences = new Vector();
- for (int s=0;insect!=null && s();
+ for (int s = 0; insect != null && s < insect.length; s++)
+ {
+ if (map == null || map.containsKey(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;
}
/**
* @return the showUnconserved
*/
- public boolean getShowunconserved()
+ public boolean getShowNonconserved()
{
- return showUnconserved;
+ return showNonconserved;
}
/**
- * @param showUnconserved the showUnconserved to set
+ * @param showNonconserved
+ * the showUnconserved to set
*/
- public void setShowunconserved(boolean displayNonconserved)
+ public void setShowNonconserved(boolean displayNonconserved)
{
- this.showUnconserved = displayNonconserved;
+ this.showNonconserved = displayNonconserved;
}
- AlignmentAnnotation consensus=null,conservation=null;
/**
- * flag indicating if consensus histogram should be rendered
+ * set this alignmentAnnotation object as the one used to render consensus
+ * annotation
+ *
+ * @param aan
*/
- private boolean showConsensusHistogram;
-
+ public void setConsensus(AlignmentAnnotation aan)
+ {
+ if (consensus == null)
+ {
+ consensus = aan;
+ }
+ }
/**
*
- * @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()
{
@@ -949,33 +1142,52 @@ public class SequenceGroup
{
return null;
}
- if (consensus==null)
+ if (consensus == null)
{
- consensus = new AlignmentAnnotation("","",
- new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+ consensus = new AlignmentAnnotation("", "", new Annotation[1], 0f,
+ 100f, AlignmentAnnotation.BAR_GRAPH);
consensus.hasText = true;
consensus.autoCalculated = true;
consensus.groupRef = this;
+ consensus.label = "Consensus for " + getName();
+ consensus.description = "Percent Identity";
}
- consensus.label = "Consensus for "+getName();
- consensus.description = "Percent Identity";
return consensus;
}
- /**
+
+ /**
+ * set this alignmentAnnotation object as the one used to render consensus
+ * annotation
+ *
+ * @param aan
+ */
+ public void setConservationRow(AlignmentAnnotation aan)
+ {
+ if (conservation == null)
+ {
+ conservation = aan;
+ }
+ }
+
+ /**
* get the conservation annotation row for this group
+ *
* @return autoCalculated annotation row
*/
- public AlignmentAnnotation getConservationRow() {
- if (conservation == null) {
- conservation = new AlignmentAnnotation("","", new Annotation[1], 0f, 11f,
- AlignmentAnnotation.BAR_GRAPH);
+ public AlignmentAnnotation getConservationRow()
+ {
+ if (conservation == null)
+ {
+ conservation = new AlignmentAnnotation("", "", new Annotation[1], 0f,
+ 11f, AlignmentAnnotation.BAR_GRAPH);
+ }
+
conservation.hasText = true;
conservation.autoCalculated = true;
conservation.groupRef = this;
- }
- conservation.label = "Conservation for "+getName();
- conservation.description = "Conservation for group "+getName()+" less than " + consPercGaps
- + "% gaps";
+ conservation.label = "Conservation for " + getName();
+ conservation.description = "Conservation for group " + getName()
+ + " less than " + consPercGaps + "% gaps";
return conservation;
}
@@ -983,10 +1195,10 @@ public class SequenceGroup
*
* @return true if annotation rows have been instantiated for this group
*/
- public boolean hasAnnotationRows()
- {
- return consensus!=null || conservation!=null;
- }
+ public boolean hasAnnotationRows()
+ {
+ return consensus != null || conservation != null;
+ }
public SequenceI getConsensusSeq()
{
@@ -996,9 +1208,10 @@ public class SequenceGroup
{
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
{
@@ -1007,51 +1220,60 @@ public class SequenceGroup
}
}
- SequenceI sq = new Sequence("Group"+getName()+" Consensus", seqs.toString());
+ SequenceI sq = new Sequence("Group" + getName() + " Consensus",
+ seqs.toString());
sq.setDescription("Percentage Identity Consensus "
+ ((ignoreGapsInConsensus) ? " without gaps" : ""));
- return sq;
+ return sq;
}
public void setIgnoreGapsConsensus(boolean state)
{
- if (this.ignoreGapsInConsensus!=state && consensus!=null)
+ if (this.ignoreGapsInConsensus != state && consensus != null)
{
ignoreGapsInConsensus = state;
recalcConservation();
}
ignoreGapsInConsensus = state;
}
+
public boolean getIgnoreGapsConsensus()
{
return ignoreGapsInConsensus;
}
+
/**
- * @param includeAllConsSymbols the includeAllConsSymbols to set
+ * @param showSequenceLogo
+ * indicates if a sequence logo is shown for consensus annotation
*/
- public void setIncludeAllConsSymbols(boolean includeAllConsSymbols)
+ public void setshowSequenceLogo(boolean showSequenceLogo)
{
- if (this.showSequenceLogo!=includeAllConsSymbols && consensus!=null) {
- this.showSequenceLogo = includeAllConsSymbols;
+ // TODO: decouple calculation from settings update
+ if (this.showSequenceLogo != showSequenceLogo && consensus != null)
+ {
+ this.showSequenceLogo = showSequenceLogo;
recalcConservation();
}
- this.showSequenceLogo = includeAllConsSymbols;
+ this.showSequenceLogo = showSequenceLogo;
}
-
/**
*
- * @param showConsHist flag indicating if the consensus histogram for this group should be rendered
+ * @param showConsHist
+ * flag indicating if the consensus histogram for this group should
+ * be rendered
*/
public void setShowConsensusHistogram(boolean showConsHist)
{
-
- if (showConsensusHistogram!=showConsHist && consensus!=null) {
+
+ if (showConsensusHistogram != showConsHist && consensus != null)
+ {
this.showConsensusHistogram = showConsHist;
recalcConservation();
}
this.showConsensusHistogram = showConsHist;
}
+
/**
* @return the showConsensusHistogram
*/
@@ -1059,4 +1281,208 @@ public class SequenceGroup
{
return showConsensusHistogram;
}
+
+ /**
+ * set flag indicating if logo should be normalised when rendered
+ *
+ * @param norm
+ */
+ public void setNormaliseSequenceLogo(boolean norm)
+ {
+ normaliseSequenceLogo = norm;
+ }
+
+ public boolean isNormaliseSequenceLogo()
+ {
+ return normaliseSequenceLogo;
+ }
+
+ @Override
+ /**
+ * returns a new array with all annotation involving this group
+ */
+ public AlignmentAnnotation[] getAlignmentAnnotation()
+ {
+ // TODO add in other methods like 'getAlignmentAnnotation(String label),
+ // etc'
+ ArrayList annot = new ArrayList<>();
+ synchronized (sequences)
+ {
+ for (SequenceI seq : sequences)
+ {
+ AlignmentAnnotation[] aa = seq.getAnnotation();
+ if (aa != null)
+ {
+ for (AlignmentAnnotation al : aa)
+ {
+ if (al.groupRef == this)
+ {
+ annot.add(al);
+ }
+ }
+ }
+ }
+ if (consensus != null)
+ {
+ annot.add(consensus);
+ }
+ if (conservation != null)
+ {
+ annot.add(conservation);
+ }
+ }
+ return annot.toArray(new AlignmentAnnotation[0]);
+ }
+
+ @Override
+ public Iterable findAnnotation(String calcId)
+ {
+ 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)
+ {
+ 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)
+ {
+ throw new IllegalArgumentException(
+ "Circular reference in SequenceGroup.context");
+ }
+ ref = ref.getContext();
+ }
+ this.context = ctx;
+ }
+
+ /*
+ * (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);
}
+}