*/
package jalview.datamodel;
-import jalview.analysis.AlignmentUtils;
-import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
-import jalview.io.FastaFile;
-import jalview.util.Comparison;
-import jalview.util.LinkedIdentityHashSet;
-import jalview.util.MessageManager;
-
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
+import jalview.analysis.AlignmentUtils;
+import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
+import jalview.io.FastaFile;
+import jalview.util.Comparison;
+import jalview.util.LinkedIdentityHashSet;
+import jalview.util.MessageManager;
+
/**
* Data structure to hold and manipulate a multiple sequence alignment
*/
* @author JimP
*
*/
-public class Alignment implements AlignmentI
+public class Alignment implements AlignmentI, AutoCloseable
{
private Alignment dataset;
- protected List<SequenceI> sequences;
+ private List<SequenceI> sequences;
protected List<SequenceGroup> groups;
{
synchronized (sequences)
{
+
if (i > -1 && i < sequences.size())
{
return sequences.get(i);
}
}
+
return null;
}
}
@Override
- public void finalize() throws Throwable
+ public void close()
{
if (getDataset() != null)
{
- getDataset().removeAlignmentRef();
+ try
+ {
+ getDataset().removeAlignmentRef();
+ } catch (Throwable e)
+ {
+ e.printStackTrace();
+ }
}
nullReferences();
- super.finalize();
}
/**
int i = 0;
SequenceI sq = null;
String sqname = null;
+ int nseq = sequences.size();
if (startAfter != null)
{
// try to find the sequence in the alignment
boolean matched = false;
- while (i < sequences.size())
+ while (i < nseq)
{
if (getSequenceAt(i++) == startAfter)
{
i = 0;
}
}
- while (i < sequences.size())
+ while (i < nseq)
{
sq = getSequenceAt(i);
sqname = sq.getName();
for (int i = 0; i < sequences.size(); i++)
{
- if (getSequenceAt(i).getLength() > maxLength)
- {
- maxLength = getSequenceAt(i).getLength();
- }
+ maxLength = Math.max(maxLength, getSequenceAt(i).getLength());
}
-
return maxLength;
}
+ @Override
+ public int getVisibleWidth()
+ {
+ int w = getWidth();
+ if (hiddenCols != null)
+ {
+ w -= hiddenCols.getSize();
+ }
+ return w;
+ }
+
/**
* DOCUMENT ME!
*
int maxLength = -1;
SequenceI current;
- for (int i = 0; i < sequences.size(); i++)
+ int nseq = sequences.size();
+ for (int i = 0; i < nseq; i++)
{
current = getSequenceAt(i);
for (int j = current.getLength(); j > maxLength; j--)
maxLength++;
int cLength;
- for (int i = 0; i < sequences.size(); i++)
+ for (int i = 0; i < nseq; i++)
{
current = getSequenceAt(i);
cLength = current.getLength();
{
// TODO JAL-1270 needs test coverage
// currently tested for use in jalview.gui.SequenceFetcher
- boolean samegap = toappend.getGapCharacter() == getGapCharacter();
char oldc = toappend.getGapCharacter();
+ boolean samegap = oldc == getGapCharacter();
boolean hashidden = toappend.getHiddenSequences() != null
&& toappend.getHiddenSequences().hiddenSequences != null;
// get all sequences including any hidden ones
{
if (!samegap)
{
- char[] oldseq = addedsq.getSequence();
- for (int c = 0; c < oldseq.length; c++)
- {
- if (oldseq[c] == oldc)
- {
- oldseq[c] = gapCharacter;
- }
- }
+ addedsq.replace(oldc, gapCharacter);
}
toappendsq.add(addedsq);
}
AlignmentAnnotation annot = new AlignmentAnnotation(name, name,
new Annotation[1], 0f, 0f, AlignmentAnnotation.BAR_GRAPH);
annot.hasText = false;
- annot.setCalcId(new String(calcId));
+ if (calcId != null)
+ {
+ annot.setCalcId(new String(calcId));
+ }
annot.autoCalculated = autoCalc;
if (seqRef != null)
{
@Override
public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
{
- List<AlignmentAnnotation> aa = new ArrayList<>();
AlignmentAnnotation[] alignmentAnnotation = getAlignmentAnnotation();
if (alignmentAnnotation != null)
{
- for (AlignmentAnnotation a : alignmentAnnotation)
- {
- if (a.getCalcId() == calcId || (a.getCalcId() != null
- && calcId != null && a.getCalcId().equals(calcId)))
- {
- aa.add(a);
- }
- }
+ return AlignmentAnnotation.findAnnotation(
+ Arrays.asList(getAlignmentAnnotation()), calcId);
}
- return aa;
+ return Arrays.asList(new AlignmentAnnotation[] {});
}
@Override
public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
String calcId, String label)
{
- ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
- for (AlignmentAnnotation ann : getAlignmentAnnotation())
- {
- if ((calcId == null || (ann.getCalcId() != null
- && ann.getCalcId().equals(calcId)))
- && (seq == null || (ann.sequenceRef != null
- && ann.sequenceRef == seq))
- && (label == null
- || (ann.label != null && ann.label.equals(label))))
- {
- aa.add(ann);
- }
- }
- return aa;
+ return annotations == null ? null
+ : AlignmentAnnotation.findAnnotations(
+ Arrays.asList(getAlignmentAnnotation()), seq, calcId,
+ label);
}
@Override
}
@Override
- public void setHiddenColumns(HiddenColumns cols)
+ public boolean setHiddenColumns(HiddenColumns cols)
{
+ boolean changed = cols == null ? hiddenCols != null
+ : !cols.equals(hiddenCols);
hiddenCols = cols;
+ return changed;
+ }
+
+ @Override
+ public void setupJPredAlignment()
+ {
+ SequenceI repseq = getSequenceAt(0);
+ setSeqrep(repseq);
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideList(repseq.getInsertions());
+ setHiddenColumns(cs);
+ }
+
+ @Override
+ public HiddenColumns propagateInsertions(SequenceI profileseq,
+ AlignmentView input)
+ {
+ int profsqpos = 0;
+
+ char gc = getGapCharacter();
+ Object[] alandhidden = input.getAlignmentAndHiddenColumns(gc);
+ HiddenColumns nview = (HiddenColumns) alandhidden[1];
+ SequenceI origseq = ((SequenceI[]) alandhidden[0])[profsqpos];
+ return propagateInsertions(profileseq, origseq, nview);
+ }
+
+ /**
+ *
+ * @param profileseq
+ * sequence in al which corresponds to origseq
+ * @param al
+ * alignment which is to have gaps inserted into it
+ * @param origseq
+ * sequence corresponding to profileseq which defines gap map for
+ * modifying al
+ */
+ private HiddenColumns propagateInsertions(SequenceI profileseq,
+ SequenceI origseq, HiddenColumns hc)
+ {
+ // take the set of hidden columns, and the set of gaps in origseq,
+ // and remove all the hidden gaps from hiddenColumns
+
+ // first get the gaps as a Bitset
+ // then calculate hidden ^ not(gap)
+ BitSet gaps = origseq.gapBitset();
+ hc.andNot(gaps);
+
+ // for each sequence in the alignment, except the profile sequence,
+ // insert gaps corresponding to each hidden region but where each hidden
+ // column region is shifted backwards by the number of preceding visible
+ // gaps update hidden columns at the same time
+ HiddenColumns newhidden = new HiddenColumns();
+
+ int numGapsBefore = 0;
+ int gapPosition = 0;
+ Iterator<int[]> it = hc.iterator();
+ while (it.hasNext())
+ {
+ int[] region = it.next();
+
+ // get region coordinates accounting for gaps
+ // we can rely on gaps not being *in* hidden regions because we already
+ // removed those
+ while (gapPosition < region[0])
+ {
+ gapPosition++;
+ if (gaps.get(gapPosition))
+ {
+ numGapsBefore++;
+ }
+ }
+
+ int left = region[0] - numGapsBefore;
+ int right = region[1] - numGapsBefore;
+
+ newhidden.hideColumns(left, right);
+ padGaps(left, right, profileseq);
+ }
+ return newhidden;
+ }
+
+ /**
+ * Pad gaps in all sequences in alignment except profileseq
+ *
+ * @param left
+ * position of first gap to insert
+ * @param right
+ * position of last gap to insert
+ * @param profileseq
+ * sequence not to pad
+ */
+ private void padGaps(int left, int right, SequenceI profileseq)
+ {
+ char gc = getGapCharacter();
+
+ // make a string with number of gaps = length of hidden region
+ StringBuilder sb = new StringBuilder();
+ for (int g = 0; g < right - left + 1; g++)
+ {
+ sb.append(gc);
+ }
+
+ // loop over the sequences and pad with gaps where required
+ for (int s = 0, ns = getHeight(); s < ns; s++)
+ {
+ SequenceI sqobj = getSequenceAt(s);
+ if ((sqobj != profileseq) && (sqobj.getLength() >= left))
+ {
+ String sq = sqobj.getSequenceAsString();
+ sqobj.setSequence(
+ sq.substring(0, left) + sb.toString() + sq.substring(left));
+ }
+ }
+ }
+
+ ////
+ //// Contact Matrix Holder Boilerplate
+ ////
+ ContactMapHolder cmholder = new ContactMapHolder();
+
+ @Override
+ public Collection<ContactMatrixI> getContactMaps()
+ {
+ return cmholder.getContactMaps();
+ }
+
+ @Override
+ public ContactMatrixI getContactMatrixFor(AlignmentAnnotation _aa)
+ {
+ ContactMatrixI cm = cmholder.getContactMatrixFor(_aa);
+ if (cm==null && _aa.groupRef!=null)
+ {
+ cm = _aa.groupRef.getContactMatrixFor(_aa);
+ }
+ if (cm==null && _aa.sequenceRef!=null)
+ {
+ cm = _aa.sequenceRef.getContactMatrixFor(_aa);
+ if (cm==null)
+ {
+ // TODO fix up this logic and unify with getContactListFor
+ cm = _aa.sequenceRef.getDatasetSequence().getContactMatrixFor(_aa);
+ }
+ }
+ return cm;
+ }
+
+ @Override
+ public ContactListI getContactListFor(AlignmentAnnotation _aa, int column)
+ {
+ ContactListI cl = cmholder.getContactListFor(_aa, column);
+ if (cl == null && _aa.groupRef != null)
+ {
+ cl = _aa.groupRef.getContactListFor(_aa, column);
+ }
+ if (cl == null && _aa.sequenceRef != null)
+ {
+ if (_aa.annotations[column] != null)
+ {
+ // sequence associated
+ cl = _aa.sequenceRef.getContactListFor(_aa, column);
+ if (cl == null && _aa.sequenceRef.getDatasetSequence() != null)
+ {
+ int spos = _aa.sequenceRef.findPosition(column);
+ if (spos >= _aa.sequenceRef.getStart()
+ && spos <= 1 + _aa.sequenceRef.getEnd())
+ {
+ cl = _aa.sequenceRef.getDatasetSequence().getContactListFor(_aa,
+ spos-_aa.sequenceRef.getStart());
+ }
+ }
+ }
+ }
+ return cl;
+ }
+
+ @Override
+ public AlignmentAnnotation addContactList(ContactMatrixI cm)
+ {
+ AlignmentAnnotation aa = cmholder.addContactList(cm);
+
+ Annotation _aa[] = new Annotation[getWidth()];
+ Annotation dummy = new Annotation(0.0f);
+ for (int i = 0; i < _aa.length; _aa[i++] = dummy)
+ {
+ ;
+ }
+ aa.annotations = _aa;
+ addAnnotation(aa);
+ return aa;
+ }
+
+ @Override
+ public void addContactListFor(AlignmentAnnotation annotation,
+ ContactMatrixI cm)
+ {
+ cmholder.addContactListFor(annotation, cm);
+
}
}