2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3 * Copyright (C) 2014 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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
19 package jalview.datamodel;
24 * Data structure to hold and manipulate a multiple sequence alignment
30 public class Alignment implements AlignmentI
32 protected Alignment dataset;
34 protected List<SequenceI> sequences;
36 protected List<SequenceGroup> groups = java.util.Collections
37 .synchronizedList(new ArrayList<SequenceGroup>());
39 protected char gapCharacter = '-';
41 protected int type = NUCLEOTIDE;
43 public static final int PROTEIN = 0;
45 public static final int NUCLEOTIDE = 1;
47 public boolean hasRNAStructure = false;
50 public AlignmentAnnotation[] annotations;
52 HiddenSequences hiddenSequences = new HiddenSequences(this);
54 public Hashtable alignmentProperties;
56 private void initAlignment(SequenceI[] seqs)
60 if (jalview.util.Comparison.isNucleotide(seqs))
69 sequences = java.util.Collections
70 .synchronizedList(new ArrayList<SequenceI>());
72 for (i = 0; i < seqs.length; i++)
74 sequences.add(seqs[i]);
80 * Make an alignment from an array of Sequences.
84 public Alignment(SequenceI[] seqs)
90 * Make a new alignment from an array of SeqCigars
95 public Alignment(SeqCigar[] alseqs)
97 SequenceI[] seqs = SeqCigar.createAlignmentSequences(alseqs,
98 gapCharacter, new ColumnSelection(), null);
103 * Make a new alignment from an CigarArray JBPNote - can only do this when
104 * compactAlignment does not contain hidden regions. JBPNote - must also check
105 * that compactAlignment resolves to a set of SeqCigars - or construct them
108 * @param compactAlignment
111 public static AlignmentI createAlignment(CigarArray compactAlignment)
113 throw new Error("Alignment(CigarArray) not yet implemented");
114 // this(compactAlignment.refCigars);
120 * @return DOCUMENT ME!
123 public List<SequenceI> getSequences()
129 public List<SequenceI> getSequences(
130 Map<SequenceI, SequenceCollectionI> hiddenReps)
132 // TODO: in jalview 2.8 we don't do anything with hiddenreps - fix design to
138 public SequenceI[] getSequencesArray()
140 if (sequences == null)
142 synchronized (sequences)
144 return sequences.toArray(new SequenceI[sequences.size()]);
154 * @return DOCUMENT ME!
157 public SequenceI getSequenceAt(int i)
159 synchronized (sequences)
161 if (i > -1 && i < sequences.size())
163 return sequences.get(i);
170 * Adds a sequence to the alignment. Recalculates maxLength and size.
175 public void addSequence(SequenceI snew)
179 // maintain dataset integrity
180 if (snew.getDatasetSequence() != null)
182 getDataset().addSequence(snew.getDatasetSequence());
186 // derive new sequence
187 SequenceI adding = snew.deriveSequence();
188 getDataset().addSequence(adding.getDatasetSequence());
192 if (sequences == null)
194 initAlignment(new SequenceI[]
199 synchronized (sequences)
204 if (hiddenSequences != null)
205 hiddenSequences.adjustHeightSequenceAdded();
209 * Adds a sequence to the alignment. Recalculates maxLength and size.
214 public void setSequenceAt(int i, SequenceI snew)
216 SequenceI oldseq = getSequenceAt(i);
218 synchronized (sequences)
220 sequences.set(i, snew);
227 * @return DOCUMENT ME!
230 public List<SequenceGroup> getGroups()
236 public void finalize()
238 if (getDataset() != null)
239 getDataset().removeAlignmentRef();
245 hiddenSequences = null;
249 * decrement the alignmentRefs counter by one and call finalize if it goes to
252 private void removeAlignmentRef()
254 if (--alignmentRefs == 0)
267 public void deleteSequence(SequenceI s)
269 deleteSequence(findIndex(s));
279 public void deleteSequence(int i)
281 if (i > -1 && i < getHeight())
283 synchronized (sequences)
287 hiddenSequences.adjustHeightSequenceDeleted(i);
294 * @see jalview.datamodel.AlignmentI#findGroup(jalview.datamodel.SequenceI)
297 public SequenceGroup findGroup(SequenceI s)
299 synchronized (groups)
301 for (int i = 0; i < this.groups.size(); i++)
303 SequenceGroup sg = groups.get(i);
305 if (sg.getSequences(null).contains(s))
318 * jalview.datamodel.AlignmentI#findAllGroups(jalview.datamodel.SequenceI)
321 public SequenceGroup[] findAllGroups(SequenceI s)
323 ArrayList<SequenceGroup> temp = new ArrayList<SequenceGroup>();
325 synchronized (groups)
327 int gSize = groups.size();
328 for (int i = 0; i < gSize; i++)
330 SequenceGroup sg = groups.get(i);
331 if (sg == null || sg.getSequences(null) == null)
333 this.deleteGroup(sg);
338 if (sg.getSequences(null).contains(s))
344 SequenceGroup[] ret = new SequenceGroup[temp.size()];
345 return temp.toArray(ret);
350 public void addGroup(SequenceGroup sg)
352 synchronized (groups)
354 if (!groups.contains(sg))
356 if (hiddenSequences.getSize() > 0)
358 int i, iSize = sg.getSize();
359 for (i = 0; i < iSize; i++)
361 if (!sequences.contains(sg.getSequenceAt(i)))
363 sg.deleteSequence(sg.getSequenceAt(i), false);
369 if (sg.getSize() < 1)
381 * remove any annotation that references gp
384 * (if null, removes all group associated annotation)
386 private void removeAnnotationForGroup(SequenceGroup gp)
388 if (annotations == null || annotations.length == 0)
392 // remove annotation very quickly
393 AlignmentAnnotation[] t, todelete = new AlignmentAnnotation[annotations.length], tokeep = new AlignmentAnnotation[annotations.length];
397 for (i = 0, p = 0, k = 0; i < annotations.length; i++)
399 if (annotations[i].groupRef != null)
401 todelete[p++] = annotations[i];
405 tokeep[k++] = annotations[i];
411 for (i = 0, p = 0, k = 0; i < annotations.length; i++)
413 if (annotations[i].groupRef == gp)
415 todelete[p++] = annotations[i];
419 tokeep[k++] = annotations[i];
425 // clear out the group associated annotation.
426 for (i = 0; i < p; i++)
428 unhookAnnotation(todelete[i]);
431 t = new AlignmentAnnotation[k];
432 for (i = 0; i < k; i++)
441 public void deleteAllGroups()
443 synchronized (groups)
445 if (annotations != null)
447 removeAnnotationForGroup(null);
449 for (SequenceGroup sg:groups) {
458 public void deleteGroup(SequenceGroup g)
460 synchronized (groups)
462 if (groups.contains(g))
464 removeAnnotationForGroup(g);
473 public SequenceI findName(String name)
475 return findName(name, false);
481 * @see jalview.datamodel.AlignmentI#findName(java.lang.String, boolean)
484 public SequenceI findName(String token, boolean b)
486 return findName(null, token, b);
492 * @see jalview.datamodel.AlignmentI#findName(SequenceI, java.lang.String,
496 public SequenceI findName(SequenceI startAfter, String token, boolean b)
501 String sqname = null;
502 if (startAfter != null)
504 // try to find the sequence in the alignment
505 boolean matched = false;
506 while (i < sequences.size())
508 if (getSequenceAt(i++) == startAfter)
519 while (i < sequences.size())
521 sq = getSequenceAt(i);
522 sqname = sq.getName();
523 if (sqname.equals(token) // exact match
524 || (b && // allow imperfect matches - case varies
525 (sqname.equalsIgnoreCase(token))))
527 return getSequenceAt(i);
537 public SequenceI[] findSequenceMatch(String name)
539 Vector matches = new Vector();
542 while (i < sequences.size())
544 if (getSequenceAt(i).getName().equals(name))
546 matches.addElement(getSequenceAt(i));
551 SequenceI[] result = new SequenceI[matches.size()];
552 for (i = 0; i < result.length; i++)
554 result[i] = (SequenceI) matches.elementAt(i);
564 * @see jalview.datamodel.AlignmentI#findIndex(jalview.datamodel.SequenceI)
567 public int findIndex(SequenceI s)
571 while (i < sequences.size())
573 if (s == getSequenceAt(i))
588 * jalview.datamodel.AlignmentI#findIndex(jalview.datamodel.SearchResults)
591 public int findIndex(SearchResults results)
595 while (i < sequences.size())
597 if (results.involvesSequence(getSequenceAt(i)))
609 * @return DOCUMENT ME!
612 public int getHeight()
614 return sequences.size();
620 * @return DOCUMENT ME!
623 public int getWidth()
627 for (int i = 0; i < sequences.size(); i++)
629 if (getSequenceAt(i).getLength() > maxLength)
631 maxLength = getSequenceAt(i).getLength();
645 public void setGapCharacter(char gc)
648 synchronized (sequences)
650 for (SequenceI seq : sequences)
652 seq.setSequence(seq.getSequenceAsString().replace('.', gc)
653 .replace('-', gc).replace(' ', gc));
661 * @return DOCUMENT ME!
664 public char getGapCharacter()
672 * @see jalview.datamodel.AlignmentI#isAligned()
675 public boolean isAligned()
677 return isAligned(false);
683 * @see jalview.datamodel.AlignmentI#isAligned(boolean)
686 public boolean isAligned(boolean includeHidden)
688 int width = getWidth();
689 if (hiddenSequences == null || hiddenSequences.getSize() == 0)
691 includeHidden = true; // no hidden sequences to check against.
693 for (int i = 0; i < sequences.size(); i++)
695 if (includeHidden || !hiddenSequences.isHidden(getSequenceAt(i)))
697 if (getSequenceAt(i).getLength() != width)
710 * @seejalview.datamodel.AlignmentI#deleteAnnotation(jalview.datamodel.
711 * AlignmentAnnotation)
714 public boolean deleteAnnotation(AlignmentAnnotation aa)
716 return deleteAnnotation(aa, true);
720 public boolean deleteAnnotation(AlignmentAnnotation aa, boolean unhook)
724 if (annotations != null)
726 aSize = annotations.length;
734 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1];
736 boolean swap = false;
739 for (int i = 0; i < aSize; i++)
741 if (annotations[i] == aa)
746 if (tIndex < temp.length)
747 temp[tIndex++] = annotations[i];
755 unhookAnnotation(aa);
762 * remove any object references associated with this annotation
766 private void unhookAnnotation(AlignmentAnnotation aa)
768 if (aa.sequenceRef != null)
770 aa.sequenceRef.removeAlignmentAnnotation(aa);
772 if (aa.groupRef != null)
774 // probably need to do more here in the future (post 2.5.0)
782 * @seejalview.datamodel.AlignmentI#addAnnotation(jalview.datamodel.
783 * AlignmentAnnotation)
786 public void addAnnotation(AlignmentAnnotation aa)
788 addAnnotation(aa, -1);
794 * @seejalview.datamodel.AlignmentI#addAnnotation(jalview.datamodel.
795 * AlignmentAnnotation, int)
798 public void addAnnotation(AlignmentAnnotation aa, int pos)
800 if (aa.getRNAStruc() != null)
802 hasRNAStructure = true;
806 if (annotations != null)
808 aSize = annotations.length + 1;
811 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
813 if (pos == -1 || pos >= aSize)
815 temp[aSize - 1] = aa;
824 for (i = 0; i < (aSize - 1); i++, p++)
832 temp[p] = annotations[i];
841 public void setAnnotationIndex(AlignmentAnnotation aa, int index)
843 if (aa == null || annotations == null || annotations.length - 1 < index)
848 int aSize = annotations.length;
849 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
853 for (int i = 0; i < aSize; i++)
862 temp[i] = annotations[i];
866 temp[i] = annotations[i - 1];
875 * returns all annotation on the alignment
877 public AlignmentAnnotation[] getAlignmentAnnotation()
883 public void setNucleotide(boolean b)
896 public boolean isNucleotide()
898 if (type == NUCLEOTIDE)
909 public boolean hasRNAStructure()
911 // TODO can it happen that structure is removed from alignment?
912 return hasRNAStructure;
916 public void setDataset(Alignment data)
918 if (dataset == null && data == null)
920 // Create a new dataset for this alignment.
921 // Can only be done once, if dataset is not null
922 // This will not be performed
923 SequenceI[] seqs = new SequenceI[getHeight()];
924 SequenceI currentSeq;
925 for (int i = 0; i < getHeight(); i++)
927 currentSeq = getSequenceAt(i);
928 if (currentSeq.getDatasetSequence() != null)
930 seqs[i] = currentSeq.getDatasetSequence();
934 seqs[i] = currentSeq.createDatasetSequence();
938 dataset = new Alignment(seqs);
940 else if (dataset == null && data != null)
944 dataset.addAlignmentRef();
948 * reference count for number of alignments referencing this one.
950 int alignmentRefs = 0;
953 * increase reference count to this alignment.
955 private void addAlignmentRef()
961 public Alignment getDataset()
967 public boolean padGaps()
969 boolean modified = false;
971 // Remove excess gaps from the end of alignment
975 for (int i = 0; i < sequences.size(); i++)
977 current = getSequenceAt(i);
978 for (int j = current.getLength(); j > maxLength; j--)
981 && !jalview.util.Comparison.isGap(current.getCharAt(j)))
992 for (int i = 0; i < sequences.size(); i++)
994 current = getSequenceAt(i);
995 cLength = current.getLength();
997 if (cLength < maxLength)
999 current.insertCharAt(cLength, maxLength - cLength, gapCharacter);
1002 else if (current.getLength() > maxLength)
1004 current.deleteChars(maxLength, current.getLength());
1011 * Justify the sequences to the left or right by deleting and inserting gaps
1012 * before the initial residue or after the terminal residue
1015 * true if alignment padded to right, false to justify to left
1016 * @return true if alignment was changed
1019 public boolean justify(boolean right)
1021 boolean modified = false;
1023 // Remove excess gaps from the end of alignment
1025 int ends[] = new int[sequences.size() * 2];
1027 for (int i = 0; i < sequences.size(); i++)
1029 current = getSequenceAt(i);
1030 // This should really be a sequence method
1031 ends[i * 2] = current.findIndex(current.getStart());
1032 ends[i * 2 + 1] = current.findIndex(current.getStart()
1033 + current.getLength());
1034 boolean hitres = false;
1035 for (int j = 0, rs = 0, ssiz = current.getLength(); j < ssiz; j++)
1037 if (!jalview.util.Comparison.isGap(current.getCharAt(j)))
1046 ends[i * 2 + 1] = j;
1047 if (j - ends[i * 2] > maxLength)
1049 maxLength = j - ends[i * 2];
1057 // now edit the flanking gaps to justify to either left or right
1058 int cLength, extent, diff;
1059 for (int i = 0; i < sequences.size(); i++)
1061 current = getSequenceAt(i);
1063 cLength = 1 + ends[i * 2 + 1] - ends[i * 2];
1064 diff = maxLength - cLength; // number of gaps to indent
1065 extent = current.getLength();
1069 if (extent > ends[i * 2 + 1])
1071 current.deleteChars(ends[i * 2 + 1] + 1, extent);
1074 if (ends[i * 2] > diff)
1076 current.deleteChars(0, ends[i * 2] - diff);
1081 if (ends[i * 2] < diff)
1083 current.insertCharAt(0, diff - ends[i * 2], gapCharacter);
1091 if (ends[i * 2] > 0)
1093 current.deleteChars(0, ends[i * 2]);
1095 ends[i * 2 + 1] -= ends[i * 2];
1096 extent -= ends[i * 2];
1098 if (extent > maxLength)
1100 current.deleteChars(maxLength + 1, extent);
1105 if (extent < maxLength)
1107 current.insertCharAt(extent, maxLength - extent, gapCharacter);
1117 public HiddenSequences getHiddenSequences()
1119 return hiddenSequences;
1123 public CigarArray getCompactAlignment()
1125 synchronized (sequences)
1127 SeqCigar alseqs[] = new SeqCigar[sequences.size()];
1129 for (SequenceI seq : sequences)
1131 alseqs[i++] = new SeqCigar(seq);
1133 CigarArray cal = new CigarArray(alseqs);
1134 cal.addOperation(CigarArray.M, getWidth());
1140 public void setProperty(Object key, Object value)
1142 if (alignmentProperties == null)
1143 alignmentProperties = new Hashtable();
1145 alignmentProperties.put(key, value);
1149 public Object getProperty(Object key)
1151 if (alignmentProperties != null)
1152 return alignmentProperties.get(key);
1158 public Hashtable getProperties()
1160 return alignmentProperties;
1163 AlignedCodonFrame[] codonFrameList = null;
1169 * jalview.datamodel.AlignmentI#addCodonFrame(jalview.datamodel.AlignedCodonFrame
1173 public void addCodonFrame(AlignedCodonFrame codons)
1177 if (codonFrameList == null)
1179 codonFrameList = new AlignedCodonFrame[]
1183 AlignedCodonFrame[] t = new AlignedCodonFrame[codonFrameList.length + 1];
1184 System.arraycopy(codonFrameList, 0, t, 0, codonFrameList.length);
1185 t[codonFrameList.length] = codons;
1192 * @see jalview.datamodel.AlignmentI#getCodonFrame(int)
1195 public AlignedCodonFrame getCodonFrame(int index)
1197 return codonFrameList[index];
1204 * jalview.datamodel.AlignmentI#getCodonFrame(jalview.datamodel.SequenceI)
1207 public AlignedCodonFrame[] getCodonFrame(SequenceI seq)
1209 if (seq == null || codonFrameList == null)
1211 Vector cframes = new Vector();
1212 for (int f = 0; f < codonFrameList.length; f++)
1214 if (codonFrameList[f].involvesSequence(seq))
1215 cframes.addElement(codonFrameList[f]);
1217 if (cframes.size() == 0)
1219 AlignedCodonFrame[] cfr = new AlignedCodonFrame[cframes.size()];
1220 cframes.copyInto(cfr);
1227 * @see jalview.datamodel.AlignmentI#getCodonFrames()
1230 public AlignedCodonFrame[] getCodonFrames()
1232 return codonFrameList;
1238 * @seejalview.datamodel.AlignmentI#removeCodonFrame(jalview.datamodel.
1239 * AlignedCodonFrame)
1242 public boolean removeCodonFrame(AlignedCodonFrame codons)
1244 if (codons == null || codonFrameList == null)
1246 boolean removed = false;
1247 int i = 0, iSize = codonFrameList.length;
1250 if (codonFrameList[i] == codons)
1255 System.arraycopy(codonFrameList, i + 1, codonFrameList, i, iSize
1269 public void append(AlignmentI toappend)
1271 if (toappend == this)
1273 System.err.println("Self append may cause a deadlock.");
1275 // TODO test this method for a future 2.5 release
1276 // currently tested for use in jalview.gui.SequenceFetcher
1277 boolean samegap = toappend.getGapCharacter() == getGapCharacter();
1278 char oldc = toappend.getGapCharacter();
1279 boolean hashidden = toappend.getHiddenSequences() != null
1280 && toappend.getHiddenSequences().hiddenSequences != null;
1281 // get all sequences including any hidden ones
1282 List<SequenceI> sqs = (hashidden) ? toappend.getHiddenSequences()
1283 .getFullAlignment().getSequences() : toappend.getSequences();
1288 for (SequenceI addedsq : sqs)
1292 char[] oldseq = addedsq.getSequence();
1293 for (int c = 0; c < oldseq.length; c++)
1295 if (oldseq[c] == oldc)
1297 oldseq[c] = gapCharacter;
1301 addSequence(addedsq);
1305 AlignmentAnnotation[] alan = toappend.getAlignmentAnnotation();
1306 for (int a = 0; alan != null && a < alan.length; a++)
1308 addAnnotation(alan[a]);
1310 AlignedCodonFrame[] acod = toappend.getCodonFrames();
1311 for (int a = 0; acod != null && a < acod.length; a++)
1313 this.addCodonFrame(acod[a]);
1315 List<SequenceGroup> sg = toappend.getGroups();
1318 for (SequenceGroup _sg : sg)
1323 if (toappend.getHiddenSequences() != null)
1325 HiddenSequences hs = toappend.getHiddenSequences();
1326 if (hiddenSequences == null)
1328 hiddenSequences = new HiddenSequences(this);
1330 if (hs.hiddenSequences != null)
1332 for (int s = 0; s < hs.hiddenSequences.length; s++)
1334 // hide the newly appended sequence in the alignment
1335 if (hs.hiddenSequences[s] != null)
1337 hiddenSequences.hideSequence(hs.hiddenSequences[s]);
1342 if (toappend.getProperties() != null)
1344 // we really can't do very much here - just try to concatenate strings
1345 // where property collisions occur.
1346 Enumeration key = toappend.getProperties().keys();
1347 while (key.hasMoreElements())
1349 Object k = key.nextElement();
1350 Object ourval = this.getProperty(k);
1351 Object toapprop = toappend.getProperty(k);
1354 if (ourval.getClass().equals(toapprop.getClass())
1355 && !ourval.equals(toapprop))
1357 if (ourval instanceof String)
1360 this.setProperty(k, ((String) ourval) + "; "
1361 + ((String) toapprop));
1365 if (ourval instanceof Vector)
1368 Enumeration theirv = ((Vector) toapprop).elements();
1369 while (theirv.hasMoreElements())
1371 ((Vector) ourval).addElement(theirv);
1379 // just add new property directly
1380 setProperty(k, toapprop);
1388 public AlignmentAnnotation findOrCreateAnnotation(String name,
1389 String calcId, boolean autoCalc, SequenceI seqRef,
1390 SequenceGroup groupRef)
1392 assert (name != null);
1393 if (annotations != null)
1395 for (AlignmentAnnotation annot : getAlignmentAnnotation())
1397 if (annot.autoCalculated == autoCalc && (name.equals(annot.label))
1398 && (calcId == null || annot.getCalcId().equals(calcId))
1399 && annot.sequenceRef == seqRef
1400 && annot.groupRef == groupRef)
1406 AlignmentAnnotation annot = new AlignmentAnnotation(name, name,
1407 new Annotation[1], 0f, 0f, AlignmentAnnotation.BAR_GRAPH);
1408 annot.hasText = false;
1409 annot.setCalcId(new String(calcId));
1410 annot.autoCalculated = autoCalc;
1413 annot.setSequenceRef(seqRef);
1415 annot.groupRef = groupRef;
1416 addAnnotation(annot);
1422 public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
1424 ArrayList<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
1425 for (AlignmentAnnotation a : getAlignmentAnnotation())
1427 if (a.getCalcId() == calcId
1428 || (a.getCalcId() != null && calcId != null && a.getCalcId()
1438 public void moveSelectedSequencesByOne(SequenceGroup sg,
1439 Map<SequenceI, SequenceCollectionI> map, boolean up)
1441 synchronized (sequences)
1446 for (int i = 1, iSize = sequences.size(); i < iSize; i++)
1448 SequenceI seq = sequences.get(i);
1449 if (!sg.getSequences(map).contains(seq))
1454 SequenceI temp = sequences.get(i - 1);
1455 if (sg.getSequences(null).contains(temp))
1460 sequences.set(i, temp);
1461 sequences.set(i - 1, seq);
1466 for (int i = sequences.size() - 2; i > -1; i--)
1468 SequenceI seq = sequences.get(i);
1469 if (!sg.getSequences(map).contains(seq))
1474 SequenceI temp = sequences.get(i + 1);
1475 if (sg.getSequences(map).contains(temp))
1480 sequences.set(i, temp);
1481 sequences.set(i + 1, seq);
1488 public void validateAnnotation(AlignmentAnnotation alignmentAnnotation)
1490 alignmentAnnotation.validateRangeAndDisplay();
1491 if (isNucleotide() && alignmentAnnotation.isValidStruc())
1493 hasRNAStructure = true;
1497 public int getEndRes()
1499 return getWidth()-1;
1501 public int getStartRes()
1506 /* In the case of AlignmentI - returns the dataset for the alignment, if set
1508 * @see jalview.datamodel.AnnotatedCollectionI#getContext()
1511 public AnnotatedCollectionI getContext()