X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FSequence.java;h=a8cff264d2e5cd8c65b4ddb4dae0bace3e42691b;hb=6568287d7ca9ab336a83e27b9bfbd548a10cf748;hp=a61f0939e22f27f652aad0d07a7179b4c349449d;hpb=a5ef4fc9d498934033e294ce80ddfe6486a41518;p=jalview.git diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index a61f093..a8cff26 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -22,10 +22,15 @@ package jalview.datamodel; import jalview.analysis.AlignSeq; import jalview.api.DBRefEntryI; +import jalview.util.Comparison; +import jalview.util.DBRefUtils; +import jalview.util.MapList; import jalview.util.StringUtils; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; +import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.Vector; @@ -57,8 +62,6 @@ public class Sequence extends ASequence implements SequenceI String vamsasId; - DBRefEntryI sourceDBRef; - DBRefEntry[] dbrefs; RNA rna; @@ -231,12 +234,9 @@ public class Sequence extends ASequence implements SequenceI { char[] oseq = seq.getSequence(); initSeqAndName(seq.getName(), Arrays.copyOf(oseq, oseq.length), - seq.getStart(), - seq.getEnd()); + seq.getStart(), seq.getEnd()); } description = seq.getDescription(); - sourceDBRef = seq.getSourceDBRef() == null ? null : new DBRefEntry( - seq.getSourceDBRef()); if (seq != datasetSequence) { setDatasetSequence(seq.getDatasetSequence()); @@ -293,7 +293,6 @@ public class Sequence extends ASequence implements SequenceI } } - @Override public void setSequenceFeatures(SequenceFeature[] features) { @@ -303,19 +302,24 @@ public class Sequence extends ASequence implements SequenceI } else { - System.err - .println("Warning: JAL-2046 side effect ? Possible implementation error: overwriting dataset sequence features by setting sequence features on alignment"); + if (datasetSequence.getSequenceFeatures() != features + && datasetSequence.getSequenceFeatures() != null + && datasetSequence.getSequenceFeatures().length > 0) + { + new Exception( + "Warning: JAL-2046 side effect ? Possible implementation error: overwriting dataset sequence features by setting sequence features on alignment") + .printStackTrace(); + } datasetSequence.setSequenceFeatures(features); } } @Override - public synchronized void addSequenceFeature(SequenceFeature sf) + public synchronized boolean addSequenceFeature(SequenceFeature sf) { - if (sequenceFeatures==null && datasetSequence != null) + if (sequenceFeatures == null && datasetSequence != null) { - datasetSequence.addSequenceFeature(sf); - return; + return datasetSequence.addSequenceFeature(sf); } if (sequenceFeatures == null) { @@ -326,7 +330,7 @@ public class Sequence extends ASequence implements SequenceI { if (sequenceFeatures[i].equals(sf)) { - return; + return false; } } @@ -335,6 +339,7 @@ public class Sequence extends ASequence implements SequenceI temp[sequenceFeatures.length] = sf; sequenceFeatures = temp; + return true; } @Override @@ -342,8 +347,9 @@ public class Sequence extends ASequence implements SequenceI { if (sequenceFeatures == null) { - if (datasetSequence!=null) { - datasetSequence.deleteFeature(sf); + if (datasetSequence != null) + { + datasetSequence.deleteFeature(sf); } return; } @@ -407,28 +413,24 @@ public class Sequence extends ASequence implements SequenceI } @Override - public void addPDBId(PDBEntry entry) + public boolean addPDBId(PDBEntry entry) { if (pdbIds == null) { pdbIds = new Vector(); + pdbIds.add(entry); + return true; } - 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) + for (PDBEntry pdbe : pdbIds) { - oldEntry.setFile(newEntry.getFile()); + if (pdbe.updateFrom(entry)) + { + return false; + } } + pdbIds.addElement(entry); + return true; } /** @@ -818,6 +820,40 @@ public class Sequence extends ASequence implements SequenceI } @Override + public BitSet getInsertionsAsBits() + { + BitSet map = new BitSet(); + int lastj = -1, j = 0; + int pos = start; + int seqlen = sequence.length; + while ((j < seqlen)) + { + if (jalview.util.Comparison.isGap(sequence[j])) + { + if (lastj == -1) + { + lastj = j; + } + } + else + { + if (lastj != -1) + { + map.set(lastj, j - 1); + lastj = -1; + } + } + j++; + } + if (lastj != -1) + { + map.set(lastj, j - 1); + lastj = -1; + } + return map; + } + + @Override public void deleteChars(int i, int j) { int newstart = start, newend = end; @@ -943,7 +979,17 @@ public class Sequence extends ASequence implements SequenceI @Override public void setDBRefs(DBRefEntry[] dbref) { + if (dbrefs == null && datasetSequence != null + && this != datasetSequence) + { + datasetSequence.setDBRefs(dbref); + return; + } dbrefs = dbref; + if (dbrefs != null) + { + DBRefUtils.ensurePrimaries(this); + } } @Override @@ -960,41 +1006,56 @@ public class Sequence extends ASequence implements SequenceI @Override public void addDBRef(DBRefEntry entry) { - // TODO add to dataset sequence instead if there is one? + if (datasetSequence != null) + { + datasetSequence.addDBRef(entry); + return; + } + if (dbrefs == null) { dbrefs = new DBRefEntry[0]; } - int i, iSize = dbrefs.length; - - for (i = 0; i < iSize; i++) + for (DBRefEntryI dbr : dbrefs) { - if (dbrefs[i].equalRef(entry)) + if (dbr.updateFrom(entry)) { - if (entry.getMap() != null) - { - if (dbrefs[i].getMap() == null) - { - // overwrite with 'superior' entry that contains a mapping. - dbrefs[i] = entry; - } - } + /* + * found a dbref that either matched, or could be + * updated from, the new entry - no need to add it + */ return; } } - DBRefEntry[] temp = new DBRefEntry[iSize + 1]; - System.arraycopy(dbrefs, 0, temp, 0, iSize); + /* + * extend the array to make room for one more + */ + // TODO use an ArrayList instead + int j = dbrefs.length; + DBRefEntry[] temp = new DBRefEntry[j + 1]; + System.arraycopy(dbrefs, 0, temp, 0, j); temp[temp.length - 1] = entry; dbrefs = temp; + + DBRefUtils.ensurePrimaries(this); } @Override public void setDatasetSequence(SequenceI seq) { - // TODO check for circular reference before setting? + if (seq == this) + { + throw new IllegalArgumentException( + "Implementation Error: self reference passed to SequenceI.setDatasetSequence"); + } + if (seq != null && seq.getDatasetSequence() != null) + { + throw new IllegalArgumentException( + "Implementation error: cascading dataset sequences are not allowed."); + } datasetSequence = seq; } @@ -1067,7 +1128,7 @@ public class Sequence extends ASequence implements SequenceI @Override public SequenceI deriveSequence() { - Sequence seq=null; + Sequence seq = null; if (datasetSequence == null) { if (isValidDatasetSequence()) @@ -1081,12 +1142,35 @@ public class Sequence extends ASequence implements SequenceI else { // Create a new, valid dataset sequence - createDatasetSequence(); + createDatasetSequence(); } } return new Sequence(this); } + private boolean _isNa; + + private long _seqhash = 0; + + /** + * Answers false if the sequence is more than 85% nucleotide (ACGTU), else + * true + */ + @Override + public boolean isProtein() + { + if (datasetSequence != null) + { + return datasetSequence.isProtein(); + } + if (_seqhash != sequence.hashCode()) + { + _seqhash = sequence.hashCode(); + _isNa = Comparison.isNucleotide(this); + } + return !_isNa; + }; + /* * (non-Javadoc) * @@ -1106,9 +1190,9 @@ public class Sequence extends ASequence implements SequenceI dsseq.setDescription(description); // move features and database references onto dataset sequence dsseq.sequenceFeatures = sequenceFeatures; - sequenceFeatures=null; + sequenceFeatures = null; dsseq.dbrefs = dbrefs; - dbrefs=null; + dbrefs = null; // TODO: search and replace any references to this sequence with // references to the dataset sequence in Mappings on dbref dsseq.pdbIds = pdbIds; @@ -1202,46 +1286,22 @@ public class Sequence extends ASequence implements SequenceI { return false; } - Vector newpdb = new Vector(); - for (int i = 0; i < dbrefs.length; i++) + boolean added = false; + for (DBRefEntry dbr : dbrefs) { - if (DBRefSource.PDB.equals(dbrefs[i].getSource())) + if (DBRefSource.PDB.equals(dbr.getSource())) { - PDBEntry pdbe = new PDBEntry(); - pdbe.setId(dbrefs[i].getAccessionId()); - if (pdbIds == null || pdbIds.size() == 0) - { - newpdb.addElement(pdbe); - } - else - { - Enumeration en = pdbIds.elements(); - boolean matched = false; - while (!matched && en.hasMoreElements()) - { - PDBEntry anentry = (PDBEntry) en.nextElement(); - if (anentry.getId().equals(pdbe.getId())) - { - matched = true; - } - } - if (!matched) - { - newpdb.addElement(pdbe); - } - } - } - } - if (newpdb.size() > 0) - { - Enumeration en = newpdb.elements(); - while (en.hasMoreElements()) - { - addPDBId((PDBEntry) en.nextElement()); + /* + * 'Add' any PDB dbrefs as a PDBEntry - add is only performed if the + * PDB id is not already present in a 'matching' PDBEntry + * Constructor parses out a chain code if appended to the accession id + * (a fudge used to 'store' the chain code in the DBRef) + */ + PDBEntry pdbe = new PDBEntry(dbr); + added |= addPDBId(pdbe); } - return true; } - return false; + return added; } @Override @@ -1371,12 +1431,15 @@ public class Sequence extends ASequence implements SequenceI @Override public PDBEntry getPDBEntry(String pdbIdStr) { - if (getDatasetSequence() == null - || getDatasetSequence().getAllPDBEntries() == null) + if (getDatasetSequence() != null) + { + return getDatasetSequence().getPDBEntry(pdbIdStr); + } + if (pdbIds == null) { return null; } - List entries = getDatasetSequence().getAllPDBEntries(); + List entries = getAllPDBEntries(); for (PDBEntry entry : entries) { if (entry.getId().equalsIgnoreCase(pdbIdStr)) @@ -1388,15 +1451,63 @@ public class Sequence extends ASequence implements SequenceI } @Override - public void setSourceDBRef(DBRefEntryI dbRef) - { - this.sourceDBRef = dbRef; - } - - @Override - public DBRefEntryI getSourceDBRef() + public List getPrimaryDBRefs() { - return this.sourceDBRef; + if (datasetSequence != null) + { + return datasetSequence.getPrimaryDBRefs(); + } + if (dbrefs == null || dbrefs.length == 0) + { + return Collections.emptyList(); + } + synchronized (dbrefs) + { + List primaries = new ArrayList(); + DBRefEntry[] tmp = new DBRefEntry[1]; + for (DBRefEntry ref : dbrefs) + { + if (!ref.isPrimaryCandidate()) + { + continue; + } + if (ref.hasMap()) + { + MapList mp = ref.getMap().getMap(); + if (mp.getFromLowest() > start || mp.getFromHighest() < end) + { + // map only involves a subsequence, so cannot be primary + continue; + } + } + // whilst it looks like it is a primary ref, we also sanity check type + if (DBRefUtils.getCanonicalName(DBRefSource.PDB).equals( + DBRefUtils.getCanonicalName(ref.getSource()))) + { + // PDB dbrefs imply there should be a PDBEntry associated + // TODO: tighten PDB dbrefs + // formally imply Jalview has actually downloaded and + // parsed the pdb file. That means there should be a cached file + // handle on the PDBEntry, and a real mapping between sequence and + // extracted sequence from PDB file + PDBEntry pdbentry = getPDBEntry(ref.getAccessionId()); + if (pdbentry != null && pdbentry.getFile() != null) + { + primaries.add(ref); + } + continue; + } + // check standard protein or dna sources + tmp[0] = ref; + DBRefEntry[] res = DBRefUtils.selectDbRefs(!isProtein(), tmp); + if (res != null && res[0] == tmp[0]) + { + primaries.add(ref); + continue; + } + } + return primaries; + } } }