2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.datamodel;
23 import jalview.analysis.AlignSeq;
24 import jalview.api.DBRefEntryI;
25 import jalview.util.Comparison;
26 import jalview.util.DBRefUtils;
27 import jalview.util.MapList;
28 import jalview.util.StringUtils;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collections;
33 import java.util.Enumeration;
34 import java.util.List;
35 import java.util.Vector;
37 import fr.orsay.lri.varna.models.rna.RNA;
41 * Implements the SequenceI interface for a char[] based sequence object.
46 public class Sequence extends ASequence implements SequenceI
48 SequenceI datasetSequence;
52 private char[] sequence;
60 HiddenMarkovModel hmm;
62 Vector<PDBEntry> pdbIds;
71 * This annotation is displayed below the alignment but the positions are tied
72 * to the residues of this sequence
74 * TODO: change to List<>
76 Vector<AlignmentAnnotation> annotation;
79 * The index of the sequence in a MSA
83 /** array of sequence features - may not be null for a valid sequence object */
84 public SequenceFeature[] sequenceFeatures;
87 * Creates a new Sequence object.
92 * string to form a possibly gapped sequence out of
94 * first position of non-gap residue in the sequence
96 * last position of ungapped residues (nearly always only used for
99 public Sequence(String name, String sequence, int start, int end)
101 initSeqAndName(name, sequence.toCharArray(), start, end);
104 public Sequence(String name, char[] sequence, int start, int end)
106 initSeqAndName(name, sequence, start, end);
110 * Stage 1 constructor - assign name, sequence, and set start and end fields.
111 * start and end are updated values from name2 if it ends with /start-end
118 protected void initSeqAndName(String name2, char[] sequence2, int start2,
122 this.sequence = sequence2;
129 com.stevesoft.pat.Regex limitrx = new com.stevesoft.pat.Regex(
130 "[/][0-9]{1,}[-][0-9]{1,}$");
132 com.stevesoft.pat.Regex endrx = new com.stevesoft.pat.Regex("[0-9]{1,}$");
139 .println("POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor.");
142 // Does sequence have the /start-end signature?
143 if (limitrx.search(name))
145 name = limitrx.left();
146 endrx.search(limitrx.stringMatched());
147 setStart(Integer.parseInt(limitrx.stringMatched().substring(1,
148 endrx.matchedFrom() - 1)));
149 setEnd(Integer.parseInt(endrx.stringMatched()));
153 void checkValidRange()
156 // http://issues.jalview.org/browse/JAL-774?focusedCommentId=11239&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-11239
159 for (int j = 0; j < sequence.length; j++)
161 if (!jalview.util.Comparison.isGap(sequence[j]))
180 * Creates a new Sequence object.
187 public Sequence(String name, String sequence)
189 this(name, sequence, 1, -1);
193 * Creates a new Sequence object with new AlignmentAnnotations but inherits
194 * any existing dataset sequence reference. If non exists, everything is
198 * if seq is a dataset sequence, behaves like a plain old copy
201 public Sequence(SequenceI seq)
203 this(seq, seq.getAnnotation());
207 * Create a new sequence object with new features, DBRefEntries, and PDBIds
208 * but inherits any existing dataset sequence reference, and duplicate of any
209 * annotation that is present in the given annotation array.
212 * the sequence to be copied
213 * @param alAnnotation
214 * an array of annotation including some associated with seq
216 public Sequence(SequenceI seq, AlignmentAnnotation[] alAnnotation)
218 initSeqFrom(seq, alAnnotation);
223 * does the heavy lifting when cloning a dataset sequence, or coping data from
224 * dataset to a new derived sequence.
227 * - source of attributes.
228 * @param alAnnotation
229 * - alignment annotation present on seq that should be copied onto
232 protected void initSeqFrom(SequenceI seq,
233 AlignmentAnnotation[] alAnnotation)
236 char[] oseq = seq.getSequence();
237 initSeqAndName(seq.getName(), Arrays.copyOf(oseq, oseq.length),
238 seq.getStart(), seq.getEnd());
240 description = seq.getDescription();
241 if (seq != datasetSequence)
243 setDatasetSequence(seq.getDatasetSequence());
245 if (datasetSequence == null && seq.getDBRefs() != null)
247 // only copy DBRefs and seqfeatures if we really are a dataset sequence
248 DBRefEntry[] dbr = seq.getDBRefs();
249 for (int i = 0; i < dbr.length; i++)
251 addDBRef(new DBRefEntry(dbr[i]));
253 if (seq.getSequenceFeatures() != null)
255 SequenceFeature[] sf = seq.getSequenceFeatures();
256 for (int i = 0; i < sf.length; i++)
258 addSequenceFeature(new SequenceFeature(sf[i]));
262 if (seq.getAnnotation() != null)
264 AlignmentAnnotation[] sqann = seq.getAnnotation();
265 for (int i = 0; i < sqann.length; i++)
267 if (sqann[i] == null)
271 boolean found = (alAnnotation == null);
274 for (int apos = 0; !found && apos < alAnnotation.length; apos++)
276 found = (alAnnotation[apos] == sqann[i]);
281 // only copy the given annotation
282 AlignmentAnnotation newann = new AlignmentAnnotation(sqann[i]);
283 addAlignmentAnnotation(newann);
287 if (seq.getAllPDBEntries() != null)
289 Vector<PDBEntry> ids = seq.getAllPDBEntries();
290 for (PDBEntry pdb : ids)
292 this.addPDBId(new PDBEntry(pdb));
298 public void setSequenceFeatures(SequenceFeature[] features)
300 if (datasetSequence == null)
302 sequenceFeatures = features;
306 if (datasetSequence.getSequenceFeatures() != features
307 && datasetSequence.getSequenceFeatures() != null
308 && datasetSequence.getSequenceFeatures().length > 0)
311 "Warning: JAL-2046 side effect ? Possible implementation error: overwriting dataset sequence features by setting sequence features on alignment")
314 datasetSequence.setSequenceFeatures(features);
319 public synchronized boolean addSequenceFeature(SequenceFeature sf)
321 if (sequenceFeatures == null && datasetSequence != null)
323 return datasetSequence.addSequenceFeature(sf);
325 if (sequenceFeatures == null)
327 sequenceFeatures = new SequenceFeature[0];
330 for (int i = 0; i < sequenceFeatures.length; i++)
332 if (sequenceFeatures[i].equals(sf))
338 SequenceFeature[] temp = new SequenceFeature[sequenceFeatures.length + 1];
339 System.arraycopy(sequenceFeatures, 0, temp, 0, sequenceFeatures.length);
340 temp[sequenceFeatures.length] = sf;
342 sequenceFeatures = temp;
347 public void deleteFeature(SequenceFeature sf)
349 if (sequenceFeatures == null)
351 if (datasetSequence != null)
353 datasetSequence.deleteFeature(sf);
359 for (index = 0; index < sequenceFeatures.length; index++)
361 if (sequenceFeatures[index].equals(sf))
367 if (index == sequenceFeatures.length)
372 int sfLength = sequenceFeatures.length;
375 sequenceFeatures = null;
379 SequenceFeature[] temp = new SequenceFeature[sfLength - 1];
380 System.arraycopy(sequenceFeatures, 0, temp, 0, index);
382 if (index < sfLength)
384 System.arraycopy(sequenceFeatures, index + 1, temp, index,
385 sequenceFeatures.length - index - 1);
388 sequenceFeatures = temp;
393 * Returns the sequence features (if any), looking first on the sequence, then
394 * on its dataset sequence, and so on until a non-null value is found (or
395 * none). This supports retrieval of sequence features stored on the sequence
396 * (as in the applet) or on the dataset sequence (as in the Desktop version).
401 public SequenceFeature[] getSequenceFeatures()
403 SequenceFeature[] features = sequenceFeatures;
405 SequenceI seq = this;
406 int count = 0; // failsafe against loop in sequence.datasetsequence...
407 while (features == null && seq.getDatasetSequence() != null
410 seq = seq.getDatasetSequence();
411 features = ((Sequence) seq).sequenceFeatures;
417 public boolean addPDBId(PDBEntry entry)
421 pdbIds = new Vector<>();
426 for (PDBEntry pdbe : pdbIds)
428 if (pdbe.updateFrom(entry))
433 pdbIds.addElement(entry);
444 public void setPDBId(Vector<PDBEntry> id)
452 * @return DOCUMENT ME!
455 public Vector<PDBEntry> getAllPDBEntries()
457 return pdbIds == null ? new Vector<PDBEntry>() : pdbIds;
463 * @return DOCUMENT ME!
466 public String getDisplayId(boolean jvsuffix)
468 StringBuffer result = new StringBuffer(name);
471 result.append("/" + start + "-" + end);
474 return result.toString();
484 public void setName(String name)
493 * @return DOCUMENT ME!
496 public String getName()
508 public void setStart(int start)
516 * @return DOCUMENT ME!
519 public int getStart()
531 public void setEnd(int end)
539 * @return DOCUMENT ME!
550 * @return DOCUMENT ME!
553 public int getLength()
555 return this.sequence.length;
565 public void setSequence(String seq)
567 this.sequence = seq.toCharArray();
572 public String getSequenceAsString()
574 return new String(sequence);
578 public String getSequenceAsString(int start, int end)
580 return new String(getSequence(start, end));
584 public char[] getSequence()
592 * @see jalview.datamodel.SequenceI#getSequence(int, int)
595 public char[] getSequence(int start, int end)
601 // JBPNote - left to user to pad the result here (TODO:Decide on this
603 if (start >= sequence.length)
608 if (end >= sequence.length)
610 end = sequence.length;
613 char[] reply = new char[end - start];
614 System.arraycopy(sequence, start, reply, 0, end - start);
620 public SequenceI getSubSequence(int start, int end)
626 char[] seq = getSequence(start, end);
631 int nstart = findPosition(start);
632 int nend = findPosition(end) - 1;
633 // JBPNote - this is an incomplete copy.
634 SequenceI nseq = new Sequence(this.getName(), seq, nstart, nend);
635 nseq.setDescription(description);
636 if (datasetSequence != null)
638 nseq.setDatasetSequence(datasetSequence);
642 nseq.setDatasetSequence(this);
648 * Returns the character of the aligned sequence at the given position (base
649 * zero), or space if the position is not within the sequence's bounds
654 public char getCharAt(int i)
656 if (i >= 0 && i < sequence.length)
673 public void setDescription(String desc)
675 this.description = desc;
681 * @return DOCUMENT ME!
684 public String getDescription()
686 return this.description;
692 * @see jalview.datamodel.SequenceI#findIndex(int)
695 public int findIndex(int pos)
697 // returns the alignment position for a residue
700 // Rely on end being at least as long as the length of the sequence.
701 while ((i < sequence.length) && (j <= end) && (j <= pos))
703 if (!jalview.util.Comparison.isGap(sequence[i]))
711 if ((j == end) && (j < pos))
722 public int findPosition(int i)
726 int seqlen = sequence.length;
727 while ((j < i) && (j < seqlen))
729 if (!jalview.util.Comparison.isGap(sequence[j]))
741 * Returns an int array where indices correspond to each residue in the
742 * sequence and the element value gives its position in the alignment
744 * @return int[SequenceI.getEnd()-SequenceI.getStart()+1] or null if no
745 * residues in SequenceI object
748 public int[] gapMap()
750 String seq = jalview.analysis.AlignSeq.extractGaps(
751 jalview.util.Comparison.GapChars, new String(sequence));
752 int[] map = new int[seq.length()];
756 while (j < sequence.length)
758 if (!jalview.util.Comparison.isGap(sequence[j]))
770 public int[] findPositionMap()
772 int map[] = new int[sequence.length];
775 int seqlen = sequence.length;
779 if (!jalview.util.Comparison.isGap(sequence[j]))
790 public List<int[]> getInsertions()
792 ArrayList<int[]> map = new ArrayList<>();
793 int lastj = -1, j = 0;
795 int seqlen = sequence.length;
798 if (jalview.util.Comparison.isGap(sequence[j]))
809 map.add(new int[] { lastj, j - 1 });
817 map.add(new int[] { lastj, j - 1 });
824 public void deleteChars(int i, int j)
826 int newstart = start, newend = end;
827 if (i >= sequence.length || i < 0)
832 char[] tmp = StringUtils.deleteChars(sequence, i, j);
833 boolean createNewDs = false;
834 // TODO: take a (second look) at the dataset creation validation method for
835 // the very large sequence case
836 int eindex = -1, sindex = -1;
837 boolean ecalc = false, scalc = false;
838 for (int s = i; s < j; s++)
840 if (jalview.schemes.ResidueProperties.aaIndex[sequence[s]] != 23)
850 sindex = findIndex(start) - 1;
855 // delete characters including start of sequence
856 newstart = findPosition(j);
857 break; // don't need to search for any more residue characters.
861 // delete characters after start.
864 eindex = findIndex(end) - 1;
869 // delete characters at end of sequence
870 newend = findPosition(i - 1);
871 break; // don't need to search for any more residue characters.
876 newend--; // decrease end position by one for the deleted residue
877 // and search further
883 // deletion occured in the middle of the sequence
884 if (createNewDs && this.datasetSequence != null)
886 // construct a new sequence
887 Sequence ds = new Sequence(datasetSequence);
888 // TODO: remove any non-inheritable properties ?
889 // TODO: create a sequence mapping (since there is a relation here ?)
890 ds.deleteChars(i, j);
891 datasetSequence = ds;
899 public void insertCharAt(int i, int length, char c)
901 char[] tmp = new char[sequence.length + length];
903 if (i >= sequence.length)
905 System.arraycopy(sequence, 0, tmp, 0, sequence.length);
910 System.arraycopy(sequence, 0, tmp, 0, i);
920 if (i < sequence.length)
922 System.arraycopy(sequence, i, tmp, index, sequence.length - i);
929 public void insertCharAt(int i, char c)
931 insertCharAt(i, 1, c);
935 public String getVamsasId()
941 public void setVamsasId(String id)
947 public void setDBRefs(DBRefEntry[] dbref)
949 if (dbrefs == null && datasetSequence != null
950 && this != datasetSequence)
952 datasetSequence.setDBRefs(dbref);
958 DBRefUtils.ensurePrimaries(this);
963 public DBRefEntry[] getDBRefs()
965 if (dbrefs == null && datasetSequence != null
966 && this != datasetSequence)
968 return datasetSequence.getDBRefs();
974 public void addDBRef(DBRefEntry entry)
976 if (datasetSequence != null)
978 datasetSequence.addDBRef(entry);
984 dbrefs = new DBRefEntry[0];
987 for (DBRefEntryI dbr : dbrefs)
989 if (dbr.updateFrom(entry))
992 * found a dbref that either matched, or could be
993 * updated from, the new entry - no need to add it
1000 * extend the array to make room for one more
1002 // TODO use an ArrayList instead
1003 int j = dbrefs.length;
1004 DBRefEntry[] temp = new DBRefEntry[j + 1];
1005 System.arraycopy(dbrefs, 0, temp, 0, j);
1006 temp[temp.length - 1] = entry;
1010 DBRefUtils.ensurePrimaries(this);
1014 public void setDatasetSequence(SequenceI seq)
1018 throw new IllegalArgumentException(
1019 "Implementation Error: self reference passed to SequenceI.setDatasetSequence");
1021 if (seq != null && seq.getDatasetSequence() != null)
1023 throw new IllegalArgumentException(
1024 "Implementation error: cascading dataset sequences are not allowed.");
1026 datasetSequence = seq;
1030 public SequenceI getDatasetSequence()
1032 return datasetSequence;
1036 public AlignmentAnnotation[] getAnnotation()
1038 return annotation == null ? null : annotation
1039 .toArray(new AlignmentAnnotation[annotation.size()]);
1043 public boolean hasAnnotation(AlignmentAnnotation ann)
1045 return annotation == null ? false : annotation.contains(ann);
1049 public void addAlignmentAnnotation(AlignmentAnnotation annotation)
1051 if (this.annotation == null)
1053 this.annotation = new Vector<>();
1055 if (!this.annotation.contains(annotation))
1057 this.annotation.addElement(annotation);
1059 annotation.setSequenceRef(this);
1063 public void removeAlignmentAnnotation(AlignmentAnnotation annotation)
1065 if (this.annotation != null)
1067 this.annotation.removeElement(annotation);
1068 if (this.annotation.size() == 0)
1070 this.annotation = null;
1076 * test if this is a valid candidate for another sequence's dataset sequence.
1079 private boolean isValidDatasetSequence()
1081 if (datasetSequence != null)
1085 for (int i = 0; i < sequence.length; i++)
1087 if (jalview.util.Comparison.isGap(sequence[i]))
1096 public SequenceI deriveSequence()
1098 Sequence seq = null;
1099 if (datasetSequence == null)
1101 if (isValidDatasetSequence())
1103 // Use this as dataset sequence
1104 seq = new Sequence(getName(), "", 1, -1);
1105 seq.setDatasetSequence(this);
1106 seq.initSeqFrom(this, getAnnotation());
1111 // Create a new, valid dataset sequence
1112 createDatasetSequence();
1115 return new Sequence(this);
1118 private boolean _isNa;
1120 private long _seqhash = 0;
1123 * Answers false if the sequence is more than 85% nucleotide (ACGTU), else
1127 public boolean isProtein()
1129 if (datasetSequence != null)
1131 return datasetSequence.isProtein();
1133 if (_seqhash != sequence.hashCode())
1135 _seqhash = sequence.hashCode();
1136 _isNa = Comparison.isNucleotide(this);
1144 * @see jalview.datamodel.SequenceI#createDatasetSequence()
1147 public SequenceI createDatasetSequence()
1149 if (datasetSequence == null)
1151 Sequence dsseq = new Sequence(getName(), AlignSeq.extractGaps(
1152 jalview.util.Comparison.GapChars, getSequenceAsString()),
1153 getStart(), getEnd());
1155 datasetSequence = dsseq;
1157 dsseq.setDescription(description);
1158 // move features and database references onto dataset sequence
1159 dsseq.sequenceFeatures = sequenceFeatures;
1160 sequenceFeatures = null;
1161 dsseq.dbrefs = dbrefs;
1163 // TODO: search and replace any references to this sequence with
1164 // references to the dataset sequence in Mappings on dbref
1165 dsseq.pdbIds = pdbIds;
1167 datasetSequence.updatePDBIds();
1168 if (annotation != null)
1170 // annotation is cloned rather than moved, to preserve what's currently
1172 for (AlignmentAnnotation aa : annotation)
1174 AlignmentAnnotation _aa = new AlignmentAnnotation(aa);
1175 _aa.sequenceRef = datasetSequence;
1176 _aa.adjustForAlignment(); // uses annotation's own record of
1177 // sequence-column mapping
1178 datasetSequence.addAlignmentAnnotation(_aa);
1182 return datasetSequence;
1189 * jalview.datamodel.SequenceI#setAlignmentAnnotation(AlignmmentAnnotation[]
1193 public void setAlignmentAnnotation(AlignmentAnnotation[] annotations)
1195 if (annotation != null)
1197 annotation.removeAllElements();
1199 if (annotations != null)
1201 for (int i = 0; i < annotations.length; i++)
1203 if (annotations[i] != null)
1205 addAlignmentAnnotation(annotations[i]);
1212 public AlignmentAnnotation[] getAnnotation(String label)
1214 if (annotation == null || annotation.size() == 0)
1219 Vector subset = new Vector();
1220 Enumeration e = annotation.elements();
1221 while (e.hasMoreElements())
1223 AlignmentAnnotation ann = (AlignmentAnnotation) e.nextElement();
1224 if (ann.label != null && ann.label.equals(label))
1226 subset.addElement(ann);
1229 if (subset.size() == 0)
1233 AlignmentAnnotation[] anns = new AlignmentAnnotation[subset.size()];
1235 e = subset.elements();
1236 while (e.hasMoreElements())
1238 anns[i++] = (AlignmentAnnotation) e.nextElement();
1240 subset.removeAllElements();
1245 public boolean updatePDBIds()
1247 if (datasetSequence != null)
1249 // TODO: could merge DBRefs
1250 return datasetSequence.updatePDBIds();
1252 if (dbrefs == null || dbrefs.length == 0)
1256 boolean added = false;
1257 for (DBRefEntry dbr : dbrefs)
1259 if (DBRefSource.PDB.equals(dbr.getSource()))
1262 * 'Add' any PDB dbrefs as a PDBEntry - add is only performed if the
1263 * PDB id is not already present in a 'matching' PDBEntry
1264 * Constructor parses out a chain code if appended to the accession id
1265 * (a fudge used to 'store' the chain code in the DBRef)
1267 PDBEntry pdbe = new PDBEntry(dbr);
1268 added |= addPDBId(pdbe);
1275 public void transferAnnotation(SequenceI entry, Mapping mp)
1277 if (datasetSequence != null)
1279 datasetSequence.transferAnnotation(entry, mp);
1282 if (entry.getDatasetSequence() != null)
1284 transferAnnotation(entry.getDatasetSequence(), mp);
1287 // transfer any new features from entry onto sequence
1288 if (entry.getSequenceFeatures() != null)
1291 SequenceFeature[] sfs = entry.getSequenceFeatures();
1292 for (int si = 0; si < sfs.length; si++)
1294 SequenceFeature sf[] = (mp != null) ? mp.locateFeature(sfs[si])
1295 : new SequenceFeature[] { new SequenceFeature(sfs[si]) };
1296 if (sf != null && sf.length > 0)
1298 for (int sfi = 0; sfi < sf.length; sfi++)
1300 addSequenceFeature(sf[sfi]);
1306 // transfer PDB entries
1307 if (entry.getAllPDBEntries() != null)
1309 Enumeration e = entry.getAllPDBEntries().elements();
1310 while (e.hasMoreElements())
1312 PDBEntry pdb = (PDBEntry) e.nextElement();
1316 // transfer database references
1317 DBRefEntry[] entryRefs = entry.getDBRefs();
1318 if (entryRefs != null)
1320 for (int r = 0; r < entryRefs.length; r++)
1322 DBRefEntry newref = new DBRefEntry(entryRefs[r]);
1323 if (newref.getMap() != null && mp != null)
1325 // remap ref using our local mapping
1327 // we also assume all version string setting is done by dbSourceProxy
1329 * if (!newref.getSource().equalsIgnoreCase(dbSource)) {
1330 * newref.setSource(dbSource); }
1338 * @return The index (zero-based) on this sequence in the MSA. It returns
1339 * {@code -1} if this information is not available.
1342 public int getIndex()
1348 * Defines the position of this sequence in the MSA. Use the value {@code -1}
1349 * if this information is undefined.
1352 * position for this sequence. This value is zero-based (zero for
1353 * this first sequence)
1356 public void setIndex(int value)
1362 public void setRNA(RNA r)
1374 public List<AlignmentAnnotation> getAlignmentAnnotations(String calcId,
1377 List<AlignmentAnnotation> result = new ArrayList<>();
1378 if (this.annotation != null)
1380 for (AlignmentAnnotation ann : annotation)
1382 if (ann.calcId != null && ann.calcId.equals(calcId)
1383 && ann.label != null && ann.label.equals(label))
1393 public String toString()
1395 return getDisplayId(false);
1399 public PDBEntry getPDBEntry(String pdbIdStr)
1401 if (getDatasetSequence() != null)
1403 return getDatasetSequence().getPDBEntry(pdbIdStr);
1409 List<PDBEntry> entries = getAllPDBEntries();
1410 for (PDBEntry entry : entries)
1412 if (entry.getId().equalsIgnoreCase(pdbIdStr))
1421 public List<DBRefEntry> getPrimaryDBRefs()
1423 if (datasetSequence != null)
1425 return datasetSequence.getPrimaryDBRefs();
1427 if (dbrefs == null || dbrefs.length == 0)
1429 return Collections.emptyList();
1431 synchronized (dbrefs)
1433 List<DBRefEntry> primaries = new ArrayList<>();
1434 DBRefEntry[] tmp = new DBRefEntry[1];
1435 for (DBRefEntry ref : dbrefs)
1437 if (!ref.isPrimaryCandidate())
1443 MapList mp = ref.getMap().getMap();
1444 if (mp.getFromLowest() > start || mp.getFromHighest() < end)
1446 // map only involves a subsequence, so cannot be primary
1450 // whilst it looks like it is a primary ref, we also sanity check type
1451 if (DBRefUtils.getCanonicalName(DBRefSource.PDB).equals(
1452 DBRefUtils.getCanonicalName(ref.getSource())))
1454 // PDB dbrefs imply there should be a PDBEntry associated
1455 // TODO: tighten PDB dbrefs
1456 // formally imply Jalview has actually downloaded and
1457 // parsed the pdb file. That means there should be a cached file
1458 // handle on the PDBEntry, and a real mapping between sequence and
1459 // extracted sequence from PDB file
1460 PDBEntry pdbentry = getPDBEntry(ref.getAccessionId());
1461 if (pdbentry != null && pdbentry.getFile() != null)
1467 // check standard protein or dna sources
1469 DBRefEntry[] res = DBRefUtils.selectDbRefs(!isProtein(), tmp);
1470 if (res != null && res[0] == tmp[0])
1481 public HiddenMarkovModel getHMM()
1487 public void setHMM(HiddenMarkovModel hmm)