X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FSequence.java;h=a61f0939e22f27f652aad0d07a7179b4c349449d;hb=b130d572dc4bef81e9287ef005d9cfce75f02c2f;hp=7efd4ae91e3ec29592f9a28ee8fa907eb3645371;hpb=24e842ef4b4fa929644b6ab4f79c7b61575c7b55;p=jalview.git diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index 7efd4ae..a61f093 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -20,16 +20,18 @@ */ package jalview.datamodel; +import jalview.analysis.AlignSeq; +import jalview.api.DBRefEntryI; +import jalview.util.StringUtils; + import java.util.ArrayList; +import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.Vector; import fr.orsay.lri.varna.models.rna.RNA; -import jalview.analysis.AlignSeq; -import jalview.util.StringUtils; - /** * * Implements the SequenceI interface for a char[] based sequence object. @@ -55,6 +57,8 @@ public class Sequence extends ASequence implements SequenceI String vamsasId; + DBRefEntryI sourceDBRef; + DBRefEntry[] dbrefs; RNA rna; @@ -182,12 +186,13 @@ public class Sequence extends ASequence implements SequenceI } /** - * Creates a new Sequence object with new features, DBRefEntries, - * AlignmentAnnotations, and PDBIds but inherits any existing dataset sequence - * reference. + * Creates a new Sequence object with new AlignmentAnnotations but inherits + * any existing dataset sequence reference. If non exists, everything is + * copied. * * @param seq - * DOCUMENT ME! + * if seq is a dataset sequence, behaves like a plain old copy + * constructor */ public Sequence(SequenceI seq) { @@ -210,29 +215,48 @@ public class Sequence extends ASequence implements SequenceI } + /** + * does the heavy lifting when cloning a dataset sequence, or coping data from + * dataset to a new derived sequence. + * + * @param seq + * - source of attributes. + * @param alAnnotation + * - alignment annotation present on seq that should be copied onto + * this sequence + */ protected void initSeqFrom(SequenceI seq, AlignmentAnnotation[] alAnnotation) { - initSeqAndName(seq.getName(), seq.getSequence(), seq.getStart(), + { + char[] oseq = seq.getSequence(); + initSeqAndName(seq.getName(), Arrays.copyOf(oseq, oseq.length), + seq.getStart(), seq.getEnd()); + } description = seq.getDescription(); - if (seq.getSequenceFeatures() != null) + sourceDBRef = seq.getSourceDBRef() == null ? null : new DBRefEntry( + seq.getSourceDBRef()); + if (seq != datasetSequence) { - SequenceFeature[] sf = seq.getSequenceFeatures(); - for (int i = 0; i < sf.length; i++) - { - addSequenceFeature(new SequenceFeature(sf[i])); - } + setDatasetSequence(seq.getDatasetSequence()); } - setDatasetSequence(seq.getDatasetSequence()); - if (datasetSequence == null && seq.getDBRef() != null) + if (datasetSequence == null && seq.getDBRefs() != null) { - // only copy DBRefs if we really are a dataset sequence - DBRefEntry[] dbr = seq.getDBRef(); + // only copy DBRefs and seqfeatures if we really are a dataset sequence + DBRefEntry[] dbr = seq.getDBRefs(); for (int i = 0; i < dbr.length; i++) { addDBRef(new DBRefEntry(dbr[i])); } + if (seq.getSequenceFeatures() != null) + { + SequenceFeature[] sf = seq.getSequenceFeatures(); + for (int i = 0; i < sf.length; i++) + { + addSequenceFeature(new SequenceFeature(sf[i])); + } + } } if (seq.getAnnotation() != null) { @@ -259,30 +283,40 @@ public class Sequence extends ASequence implements SequenceI } } } - if (seq.getPDBId() != null) + if (seq.getAllPDBEntries() != null) { - Vector ids = seq.getPDBId(); - Enumeration e = ids.elements(); - while (e.hasMoreElements()) + Vector ids = seq.getAllPDBEntries(); + for (PDBEntry pdb : ids) { - this.addPDBId(new PDBEntry((PDBEntry) e.nextElement())); + this.addPDBId(new PDBEntry(pdb)); } } } - /** - * DOCUMENT ME! - * - * @param v - * DOCUMENT ME! - */ + + @Override public void setSequenceFeatures(SequenceFeature[] features) { - sequenceFeatures = features; + if (datasetSequence == null) + { + sequenceFeatures = features; + } + else + { + System.err + .println("Warning: JAL-2046 side effect ? Possible implementation error: overwriting dataset sequence features by setting sequence features on alignment"); + datasetSequence.setSequenceFeatures(features); + } } + @Override public synchronized void addSequenceFeature(SequenceFeature sf) { + if (sequenceFeatures==null && datasetSequence != null) + { + datasetSequence.addSequenceFeature(sf); + return; + } if (sequenceFeatures == null) { sequenceFeatures = new SequenceFeature[0]; @@ -303,10 +337,14 @@ public class Sequence extends ASequence implements SequenceI sequenceFeatures = temp; } + @Override public void deleteFeature(SequenceFeature sf) { if (sequenceFeatures == null) { + if (datasetSequence!=null) { + datasetSequence.deleteFeature(sf); + } return; } @@ -352,6 +390,7 @@ public class Sequence extends ASequence implements SequenceI * * @return */ + @Override public SequenceFeature[] getSequenceFeatures() { SequenceFeature[] features = sequenceFeatures; @@ -367,6 +406,7 @@ public class Sequence extends ASequence implements SequenceI return features; } + @Override public void addPDBId(PDBEntry entry) { if (pdbIds == null) @@ -409,9 +449,9 @@ public class Sequence extends ASequence implements SequenceI * @return DOCUMENT ME! */ @Override - public Vector getPDBId() + public Vector getAllPDBEntries() { - return pdbIds; + return pdbIds == null ? new Vector() : pdbIds; } /** @@ -419,6 +459,7 @@ public class Sequence extends ASequence implements SequenceI * * @return DOCUMENT ME! */ + @Override public String getDisplayId(boolean jvsuffix) { StringBuffer result = new StringBuffer(name); @@ -436,6 +477,7 @@ public class Sequence extends ASequence implements SequenceI * @param name * DOCUMENT ME! */ + @Override public void setName(String name) { this.name = name; @@ -447,6 +489,7 @@ public class Sequence extends ASequence implements SequenceI * * @return DOCUMENT ME! */ + @Override public String getName() { return this.name; @@ -458,6 +501,7 @@ public class Sequence extends ASequence implements SequenceI * @param start * DOCUMENT ME! */ + @Override public void setStart(int start) { this.start = start; @@ -468,6 +512,7 @@ public class Sequence extends ASequence implements SequenceI * * @return DOCUMENT ME! */ + @Override public int getStart() { return this.start; @@ -479,6 +524,7 @@ public class Sequence extends ASequence implements SequenceI * @param end * DOCUMENT ME! */ + @Override public void setEnd(int end) { this.end = end; @@ -489,6 +535,7 @@ public class Sequence extends ASequence implements SequenceI * * @return DOCUMENT ME! */ + @Override public int getEnd() { return this.end; @@ -499,6 +546,7 @@ public class Sequence extends ASequence implements SequenceI * * @return DOCUMENT ME! */ + @Override public int getLength() { return this.sequence.length; @@ -510,22 +558,26 @@ public class Sequence extends ASequence implements SequenceI * @param seq * DOCUMENT ME! */ + @Override public void setSequence(String seq) { this.sequence = seq.toCharArray(); checkValidRange(); } + @Override public String getSequenceAsString() { return new String(sequence); } + @Override public String getSequenceAsString(int start, int end) { return new String(getSequence(start, end)); } + @Override public char[] getSequence() { return sequence; @@ -536,6 +588,7 @@ public class Sequence extends ASequence implements SequenceI * * @see jalview.datamodel.SequenceI#getSequence(int, int) */ + @Override public char[] getSequence(int start, int end) { if (start < 0) @@ -589,16 +642,15 @@ public class Sequence extends ASequence implements SequenceI } /** - * DOCUMENT ME! - * - * @param i - * DOCUMENT ME! + * Returns the character of the aligned sequence at the given position (base + * zero), or space if the position is not within the sequence's bounds * - * @return DOCUMENT ME! + * @return */ + @Override public char getCharAt(int i) { - if (i < sequence.length) + if (i >= 0 && i < sequence.length) { return sequence[i]; } @@ -614,6 +666,7 @@ public class Sequence extends ASequence implements SequenceI * @param desc * DOCUMENT ME! */ + @Override public void setDescription(String desc) { this.description = desc; @@ -624,6 +677,7 @@ public class Sequence extends ASequence implements SequenceI * * @return DOCUMENT ME! */ + @Override public String getDescription() { return this.description; @@ -634,6 +688,7 @@ public class Sequence extends ASequence implements SequenceI * * @see jalview.datamodel.SequenceI#findIndex(int) */ + @Override public int findIndex(int pos) { // returns the alignment position for a residue @@ -686,6 +741,7 @@ public class Sequence extends ASequence implements SequenceI * @return int[SequenceI.getEnd()-SequenceI.getStart()+1] or null if no * residues in SequenceI object */ + @Override public int[] gapMap() { String seq = jalview.analysis.AlignSeq.extractGaps( @@ -747,8 +803,7 @@ public class Sequence extends ASequence implements SequenceI { if (lastj != -1) { - map.add(new int[] - { lastj, j - 1 }); + map.add(new int[] { lastj, j - 1 }); lastj = -1; } } @@ -756,8 +811,7 @@ public class Sequence extends ASequence implements SequenceI } if (lastj != -1) { - map.add(new int[] - { lastj, j - 1 }); + map.add(new int[] { lastj, j - 1 }); lastj = -1; } return map; @@ -767,7 +821,7 @@ public class Sequence extends ASequence implements SequenceI public void deleteChars(int i, int j) { int newstart = start, newend = end; - if (i >= sequence.length) + if (i >= sequence.length || i < 0) { return; } @@ -887,18 +941,18 @@ public class Sequence extends ASequence implements SequenceI } @Override - public void setDBRef(DBRefEntry[] dbref) + public void setDBRefs(DBRefEntry[] dbref) { dbrefs = dbref; } @Override - public DBRefEntry[] getDBRef() + public DBRefEntry[] getDBRefs() { if (dbrefs == null && datasetSequence != null && this != datasetSequence) { - return datasetSequence.getDBRef(); + return datasetSequence.getDBRefs(); } return dbrefs; } @@ -906,6 +960,7 @@ public class Sequence extends ASequence implements SequenceI @Override public void addDBRef(DBRefEntry entry) { + // TODO add to dataset sequence instead if there is one? if (dbrefs == null) { dbrefs = new DBRefEntry[0]; @@ -939,6 +994,7 @@ public class Sequence extends ASequence implements SequenceI @Override public void setDatasetSequence(SequenceI seq) { + // TODO check for circular reference before setting? datasetSequence = seq; } @@ -955,7 +1011,6 @@ public class Sequence extends ASequence implements SequenceI .toArray(new AlignmentAnnotation[annotation.size()]); } - @Override public boolean hasAnnotation(AlignmentAnnotation ann) { @@ -976,6 +1031,7 @@ public class Sequence extends ASequence implements SequenceI annotation.setSequenceRef(this); } + @Override public void removeAlignmentAnnotation(AlignmentAnnotation annotation) { if (this.annotation != null) @@ -1011,31 +1067,24 @@ public class Sequence extends ASequence implements SequenceI @Override public SequenceI deriveSequence() { - SequenceI seq = new Sequence(this); - if (datasetSequence != null) - { - // duplicate current sequence with same dataset - seq.setDatasetSequence(datasetSequence); - } - else + Sequence seq=null; + if (datasetSequence == null) { if (isValidDatasetSequence()) { // Use this as dataset sequence + seq = new Sequence(getName(), "", 1, -1); seq.setDatasetSequence(this); + seq.initSeqFrom(this, getAnnotation()); + return seq; } else { // Create a new, valid dataset sequence - SequenceI ds = seq; - ds.setSequence(AlignSeq.extractGaps( - jalview.util.Comparison.GapChars, new String(sequence))); - setDatasetSequence(ds); - ds.setSequenceFeatures(getSequenceFeatures()); - seq = this; // and return this sequence as the derived sequence. + createDatasetSequence(); } } - return seq; + return new Sequence(this); } /* @@ -1043,24 +1092,32 @@ public class Sequence extends ASequence implements SequenceI * * @see jalview.datamodel.SequenceI#createDatasetSequence() */ + @Override public SequenceI createDatasetSequence() { if (datasetSequence == null) { - datasetSequence = new Sequence(getName(), AlignSeq.extractGaps( + Sequence dsseq = new Sequence(getName(), AlignSeq.extractGaps( jalview.util.Comparison.GapChars, getSequenceAsString()), getStart(), getEnd()); - datasetSequence.setSequenceFeatures(getSequenceFeatures()); - datasetSequence.setDescription(getDescription()); - setSequenceFeatures(null); - // move database references onto dataset sequence - datasetSequence.setDBRef(getDBRef()); - setDBRef(null); - datasetSequence.setPDBId(getPDBId()); - setPDBId(null); + + datasetSequence = dsseq; + + dsseq.setDescription(description); + // move features and database references onto dataset sequence + dsseq.sequenceFeatures = sequenceFeatures; + sequenceFeatures=null; + dsseq.dbrefs = dbrefs; + dbrefs=null; + // TODO: search and replace any references to this sequence with + // references to the dataset sequence in Mappings on dbref + dsseq.pdbIds = pdbIds; + pdbIds = null; datasetSequence.updatePDBIds(); if (annotation != null) { + // annotation is cloned rather than moved, to preserve what's currently + // on the alignment for (AlignmentAnnotation aa : annotation) { AlignmentAnnotation _aa = new AlignmentAnnotation(aa); @@ -1081,6 +1138,7 @@ public class Sequence extends ASequence implements SequenceI * jalview.datamodel.SequenceI#setAlignmentAnnotation(AlignmmentAnnotation[] * annotations) */ + @Override public void setAlignmentAnnotation(AlignmentAnnotation[] annotations) { if (annotation != null) @@ -1207,8 +1265,7 @@ public class Sequence extends ASequence implements SequenceI for (int si = 0; si < sfs.length; si++) { SequenceFeature sf[] = (mp != null) ? mp.locateFeature(sfs[si]) - : new SequenceFeature[] - { new SequenceFeature(sfs[si]) }; + : new SequenceFeature[] { new SequenceFeature(sfs[si]) }; if (sf != null && sf.length > 0) { for (int sfi = 0; sfi < sf.length; sfi++) @@ -1220,9 +1277,9 @@ public class Sequence extends ASequence implements SequenceI } // transfer PDB entries - if (entry.getPDBId() != null) + if (entry.getAllPDBEntries() != null) { - Enumeration e = entry.getPDBId().elements(); + Enumeration e = entry.getAllPDBEntries().elements(); while (e.hasMoreElements()) { PDBEntry pdb = (PDBEntry) e.nextElement(); @@ -1230,7 +1287,7 @@ public class Sequence extends ASequence implements SequenceI } } // transfer database references - DBRefEntry[] entryRefs = entry.getDBRef(); + DBRefEntry[] entryRefs = entry.getDBRefs(); if (entryRefs != null) { for (int r = 0; r < entryRefs.length; r++) @@ -1254,6 +1311,7 @@ public class Sequence extends ASequence implements SequenceI * @return The index (zero-based) on this sequence in the MSA. It returns * {@code -1} if this information is not available. */ + @Override public int getIndex() { return index; @@ -1267,16 +1325,19 @@ public class Sequence extends ASequence implements SequenceI * position for this sequence. This value is zero-based (zero for * this first sequence) */ + @Override public void setIndex(int value) { index = value; } + @Override public void setRNA(RNA r) { rna = r; } + @Override public RNA getRNA() { return rna; @@ -1301,4 +1362,41 @@ public class Sequence extends ASequence implements SequenceI return result; } + @Override + public String toString() + { + return getDisplayId(false); + } + + @Override + public PDBEntry getPDBEntry(String pdbIdStr) + { + if (getDatasetSequence() == null + || getDatasetSequence().getAllPDBEntries() == null) + { + return null; + } + List entries = getDatasetSequence().getAllPDBEntries(); + for (PDBEntry entry : entries) + { + if (entry.getId().equalsIgnoreCase(pdbIdStr)) + { + return entry; + } + } + return null; + } + + @Override + public void setSourceDBRef(DBRefEntryI dbRef) + { + this.sourceDBRef = dbRef; + } + + @Override + public DBRefEntryI getSourceDBRef() + { + return this.sourceDBRef; + } + }