package org.broadinstitute.sting.playground.indels; import org.broadinstitute.sting.playground.utils.Interval; /** This class represents an indel as an interval with respect to the original reference and, in addition, * stores the indel type ( (I)nsertion or (D)eletion ) and can return meaningful event size (see below). * Depending on the indel type, the positions on the reference are: * * * Given these definitions, the length of the interval, as returned by getLength() has the meaning of the length of * the event (affected bases) on the original reference: number of deleted bases for deletion and zero for insertion. * The length of the indel itself is returned by getIndelLength(), which is equal to getLength() for deletions and to * the actual number of inserted bases for insertions (while length on the reference, as returned by getLength() is zero). * * The overlaps are also meaningful with the above definitions: if an alignment to (or, in general, an interval on) * the original reference ends prior to start, or starts after stop, it does not overlap * with the indel event (neither spans over deleted region or contains any of the inserted bases). * */ public class Indel implements Interval { public static enum IndelType { I, D }; private long mStart; private long mLength; private IndelType mType; /** Creates nBases-long indel at specified start position; the object will be unusable * until indel type is set. * @param start start position on the reference * @param nBases number of inserted or deleted bases */ //public Indel(long start, long nBases) { // mType=null; // mStart=start; // mLength=nBases; // } /** Creates nBases-long indel of the specified type (insertion or deletion), at specified start position. * @param start start position on the reference * @param nBases number of inserted or deleted bases * @param type Indel type: I or D. */ public Indel(long start, long nBases, IndelType type) { mType=type; mStart=start; mLength=nBases; } /** Start coordinate on the reference; for deletions it is the position of the first deleted base, * for insertions it is the first base after the insertion. * This is the "left boundary" of the event on the original reference: every alignment that ends * befor this position on the reference does not overlap with the indel. * @return indel's left boundary */ public long getStart() { return mStart; } /** Sets start position of the interval. * * @param s start coordinate */ public void setStart(long s) { mStart = s; } /** Indel's stop coordinate on the reference; for deletions it is the position of the last deleted base, * for insertions it is the last base before the insertion site (which makes it equal to getStart() - 1). * This is the "right boundary" of the event: every alignment that starts after * this position on the reference * does not overlap with the indel. * @return indel's right boundary */ public long getStop() { if ( mType == IndelType.I ) return mStart - 1; else return mStart + mLength - 1; } /** This method is not supported in IndelInterval and will throw an exception. Use setIndelLength() instead. * * @param s stop coordinate */ public void setStop(long s) { throw new UnsupportedOperationException("Method setStop(long) is not supported in IndelInterval"); } /** Returns type of this indel ( I or D). * * @return I or D enum element */ public IndelType getType() { return mType; } /** Sets the number of bases in this indel (i.e. the actual number of inserted or * deleted bases). Stop position will be always correctly computed based on the indel length and indel type. * @param nBases length of the indel (not the length of the event on the original reference!) */ public void setIndelLength(long nBases) { mLength = nBases; } /** Returns actual number of inserted or deleted bases in the indel. * * @return number of bases (not the event length on the original reference). * @see #getLength() */ public long getIndelLength() { return mLength; } /** * Returns true if this interval overlaps with i as judjed by getStart() and getStop() positions of the * two interval objects. * * @param i Another interval * @return true iff intervals overlap */ public boolean overlapsP(Interval i) { return ! disjointP(i); //To change body of implemented methods use File | Settings | File Templates. } /** * Returns true if this interval does not overlap with i as judjed by getStart() and getStop() positions of the * two interval objects. * * @param i Another interval * @return true iff intervals do not overlap */ public boolean disjointP(Interval i) { return i.getStop() < this.getStart() || i.getStart() > this.getStop(); } /** Returns length of the region affected by the indel on the original reference. Note that an insertion * has length of 0. * @return length of the event on the original, unmodified reference */ public long getLength() { if ( mType == IndelType.I ) return 0; return mLength; } @Override public boolean equals(Object o) { if ( ! ( o instanceof Indel ) ) return false; Indel i = (Indel)o; return this.mType == i.mType && this.mStart == i.mStart && this.mLength == i.mLength ; } @Override public int hashCode() { return (int)( mStart << 6 + mStart + mLength ); } }