/*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
package jalview.datamodel;
import jalview.analysis.AlignSeq;
+import jalview.util.StringUtils;
import java.util.ArrayList;
import java.util.Enumeration;
* @author $author$
* @version $Revision$
*/
-public class Sequence implements SequenceI
+public class Sequence extends ASequence implements SequenceI
{
SequenceI datasetSequence;
int end;
- Vector pdbIds;
+ Vector<PDBEntry> pdbIds;
String vamsasId;
RNA rna;
+
/**
* This annotation is displayed below the alignment but the positions are tied
* to the residues of this sequence
*/
public Sequence(String name, String sequence, int start, int end)
{
- this.name = name;
- this.sequence = sequence.toCharArray();
- this.start = start;
- this.end = end;
- parseId();
- checkValidRange();
+ initSeqAndName(name, sequence.toCharArray(), start, end);
}
public Sequence(String name, char[] sequence, int start, int end)
{
- this.name = name;
- this.sequence = sequence;
- this.start = start;
- this.end = end;
+ initSeqAndName(name, sequence, start, end);
+ }
+
+ /**
+ * Stage 1 constructor - assign name, sequence, and set start and end fields.
+ * start and end are updated values from name2 if it ends with /start-end
+ *
+ * @param name2
+ * @param sequence2
+ * @param start2
+ * @param end2
+ */
+ protected void initSeqAndName(String name2, char[] sequence2, int start2,
+ int end2)
+ {
+ this.name = name2;
+ this.sequence = sequence2;
+ this.start = start2;
+ this.end = end2;
parseId();
checkValidRange();
}
.println("POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor.");
name = "";
}
- // Does sequence have the /start-end signiature?
+ // Does sequence have the /start-end signature?
if (limitrx.search(name))
{
name = limitrx.left();
*/
public Sequence(SequenceI seq, AlignmentAnnotation[] alAnnotation)
{
- this(seq.getName(), seq.getSequence(), seq.getStart(), seq.getEnd());
+ initSeqFrom(seq, alAnnotation);
+
+ }
+
+ protected void initSeqFrom(SequenceI seq,
+ AlignmentAnnotation[] alAnnotation)
+ {
+ initSeqAndName(seq.getName(), seq.getSequence(), seq.getStart(),
+ seq.getEnd());
description = seq.getDescription();
if (seq.getSequenceFeatures() != null)
{
}
/**
- * DOCUMENT ME!
+ * Returns the sequence features (if any), looking first on the sequence, then
+ * on its dataset sequence, and so on until a non-null value is found (or
+ * none). This supports retrieval of sequence features stored on the sequence
+ * (as in the applet) or on the dataset sequence (as in the Desktop version).
*
- * @return DOCUMENT ME!
+ * @return
*/
public SequenceFeature[] getSequenceFeatures()
{
- return sequenceFeatures;
+ SequenceFeature[] features = sequenceFeatures;
+
+ SequenceI seq = this;
+ int count = 0; // failsafe against loop in sequence.datasetsequence...
+ while (features == null && seq.getDatasetSequence() != null
+ && count++ < 10)
+ {
+ seq = seq.getDatasetSequence();
+ features = ((Sequence) seq).sequenceFeatures;
+ }
+ return features;
}
public void addPDBId(PDBEntry entry)
{
if (pdbIds == null)
{
- pdbIds = new Vector();
+ pdbIds = new Vector<PDBEntry>();
}
- if (!pdbIds.contains(entry))
+ if (pdbIds.contains(entry))
+ {
+ updatePDBEntry(pdbIds.get(pdbIds.indexOf(entry)), entry);
+ }
+ else
{
pdbIds.addElement(entry);
}
}
+ private static void updatePDBEntry(PDBEntry oldEntry, PDBEntry newEntry)
+ {
+ if (newEntry.getFile() != null)
+ {
+ oldEntry.setFile(newEntry.getFile());
+ }
+ }
+
/**
* DOCUMENT ME!
*
* @param id
* DOCUMENT ME!
*/
- public void setPDBId(Vector id)
+ @Override
+ public void setPDBId(Vector<PDBEntry> id)
{
pdbIds = id;
}
*
* @return DOCUMENT ME!
*/
- public Vector getPDBId()
+ @Override
+ public Vector<PDBEntry> getPDBId()
{
return pdbIds;
}
}
@Override
- public void deleteChars(int i, int j)
+ public List<int[]> getInsertions()
{
- int newstart = start, newend = end;
- if (i >= sequence.length)
+ ArrayList<int[]> map = new ArrayList<int[]>();
+ int lastj = -1, j = 0;
+ int pos = start;
+ int seqlen = sequence.length;
+ while ((j < seqlen))
{
- return;
+ if (jalview.util.Comparison.isGap(sequence[j]))
+ {
+ if (lastj == -1)
+ {
+ lastj = j;
+ }
+ }
+ else
+ {
+ if (lastj != -1)
+ {
+ map.add(new int[]
+ { lastj, j - 1 });
+ lastj = -1;
+ }
+ }
+ j++;
}
-
- char[] tmp;
-
- if (j >= sequence.length)
+ if (lastj != -1)
{
- tmp = new char[i];
- System.arraycopy(sequence, 0, tmp, 0, i);
- j = sequence.length;
+ map.add(new int[]
+ { lastj, j - 1 });
+ lastj = -1;
}
- else
+ return map;
+ }
+
+ @Override
+ public void deleteChars(int i, int j)
+ {
+ int newstart = start, newend = end;
+ if (i >= sequence.length || i < 0)
{
- tmp = new char[sequence.length - j + i];
- System.arraycopy(sequence, 0, tmp, 0, i);
- System.arraycopy(sequence, j, tmp, i, sequence.length - j);
+ return;
}
+
+ char[] tmp = StringUtils.deleteChars(sequence, i, j);
boolean createNewDs = false;
- // TODO: take a look at the new dataset creation validation method below -
- // this could become time comsuming for large sequences - consider making it
- // more efficient
+ // TODO: take a (second look) at the dataset creation validation method for
+ // the very large sequence case
+ int eindex = -1, sindex = -1;
+ boolean ecalc = false, scalc = false;
for (int s = i; s < j; s++)
{
if (jalview.schemes.ResidueProperties.aaIndex[sequence[s]] != 23)
}
else
{
- int sindex = findIndex(start) - 1;
+ if (!scalc)
+ {
+ sindex = findIndex(start) - 1;
+ scalc = true;
+ }
if (sindex == s)
{
// delete characters including start of sequence
else
{
// delete characters after start.
- int eindex = findIndex(end) - 1;
+ if (!ecalc)
+ {
+ eindex = findIndex(end) - 1;
+ ecalc = true;
+ }
if (eindex < j)
{
// delete characters at end of sequence
{
if (this.annotation == null)
{
- this.annotation = new Vector();
+ this.annotation = new Vector<AlignmentAnnotation>();
}
if (!this.annotation.contains(annotation))
{
AlignmentAnnotation _aa = new AlignmentAnnotation(aa);
_aa.sequenceRef = datasetSequence;
_aa.adjustForAlignment(); // uses annotation's own record of
- // sequence-column mapping
+ // sequence-column mapping
datasetSequence.addAlignmentAnnotation(_aa);
}
}
String label)
{
List<AlignmentAnnotation> result = new ArrayList<AlignmentAnnotation>();
- if (this.annotation != null) {
- for (AlignmentAnnotation ann : annotation) {
+ if (this.annotation != null)
+ {
+ for (AlignmentAnnotation ann : annotation)
+ {
if (ann.calcId != null && ann.calcId.equals(calcId)
&& ann.label != null && ann.label.equals(label))
{
return result;
}
+
}