private int calculateHardClippingAlignmentShift(CigarElement cigarElement, int clippedLength) { // Insertions should be discounted from the total hard clip count if (cigarElement.getOperator() == CigarOperator.INSERTION) return -clippedLength; // Deletions and Ns should be added to the total hard clip count (because we want to maintain the original alignment start) else if (cigarElement.getOperator() == CigarOperator.DELETION || cigarElement.getOperator() == CigarOperator.SKIPPED_REGION) return cigarElement.getLength(); // There is no shift if we are not clipping an indel return 0; }
private static void mergeAdjacent(List<CigarElement> list) { for (int i = list.size() - 1; i > 0; i--) { if (list.get(i).getOperator() == list.get(i - 1).getOperator()) { CigarElement replacement = new CigarElement(list.get(i).getLength() + list.get(i - 1).getLength(), list.get(i).getOperator()); list.set(i - 1, replacement); list.remove(i); } } } public static class CigarOperatorIterator implements Iterator<CigarOperator> {
/** * Is this element a deletion w.r.t. the reference genome? * * @return true if this is a deletion, false otherwise */ public boolean isDeletion() { return currentCigarElement.getOperator() == CigarOperator.D; }
@DataProvider public Object[][] elementsForEquals() { final CigarElement mElement = new CigarElement(10, CigarOperator.M); return new Object[][] { // same object {mElement, mElement, true}, // different equal objects {mElement, new CigarElement(mElement.getLength(), mElement.getOperator()), true}, // different lengths {mElement, new CigarElement(mElement.getLength() + 1, mElement.getOperator()), false}, // different operators {mElement, new CigarElement(mElement.getLength(), CigarOperator.X), false}, // different class {mElement, mElement.toString(), false} }; }
protected CigarElement makeElement(final State state, final int length) { CigarOperator op = null; switch (state) { case MATCH: op = CigarOperator.M; break; case INSERTION: op = CigarOperator.I; break; case DELETION: op = CigarOperator.D; break; case CLIP: op = CigarOperator.S; break; } return new CigarElement(length, op); }
static private void elementStraddlesClippedRead(List<CigarElement> newCigar, CigarElement c, int relativeClippedPosition, int clippedBases){ final CigarOperator op = c.getOperator(); int clipAmount = clippedBases; if (op.consumesReadBases()){ if (op.consumesReferenceBases() & relativeClippedPosition > 0){ newCigar.add(new CigarElement(relativeClippedPosition, op)); } if (!op.consumesReferenceBases()){ clipAmount = clippedBases + relativeClippedPosition; } } else if (relativeClippedPosition != 0){ throw new SAMException("Unexpected non-0 relativeClippedPosition " + relativeClippedPosition); } newCigar.add(new CigarElement(clipAmount, CigarOperator.S)); // S is always last element }
/** * Is the current position at the end of the current cigar? * * For example, if we are in element 3M, this function returns true if we are at offsetInCurrentCigar * of 2, but not 0 or 1. * * @return true if we're at the end of the current cigar */ public boolean atEndOfCurrentCigar() { return offsetInCurrentCigar == currentCigarElement.getLength() - 1; }
/** * Checks a Cigar for the presence of N operators. Reads with skipped bases may be spliced RNAseq reads * * @param cigar */ private boolean checkCigarForSkips(final Cigar cigar) { final List<CigarElement> elements = cigar.getCigarElements(); for (final CigarElement el : elements) { if (el.getOperator() == CigarOperator.N) return true; } return false; }
/** * @param cigarette CIGAR element (operator + length) encoded as an unsigned int. * @return Object representation of the CIGAR element. */ private static CigarElement binaryCigarToCigarElement(final int cigarette) { final int binaryOp = cigarette & 0xf; final int length = cigarette >> 4; return new CigarElement(length, CigarOperator.binaryToEnum(binaryOp)); } }
static private void elementStraddlesClippedRead(List<CigarElement> newCigar, CigarElement c, int relativeClippedPosition, int clippedBases){ final CigarOperator op = c.getOperator(); int clipAmount = clippedBases; if (op.consumesReadBases()){ if (op.consumesReferenceBases() & relativeClippedPosition > 0){ newCigar.add(new CigarElement(relativeClippedPosition, op)); } if (!op.consumesReferenceBases()){ clipAmount = clippedBases + relativeClippedPosition; } } else if (relativeClippedPosition != 0){ throw new SAMException("Unexpected non-0 relativeClippedPosition " + relativeClippedPosition); } newCigar.add(new CigarElement(clipAmount, CigarOperator.S)); // S is always last element }
@Override public boolean hasNext() { return it.hasNext() || currentElement != null && currentIndex < currentElement.getLength(); } @Override
@Override public CigarOperator next() { if (currentElement == null || currentIndex >= currentElement.getLength()) { currentElement = it.next(); currentIndex = 0; } currentIndex++; return currentElement.getOperator(); } }
public static void addStartSoftClip(List<CigarElement> cigar, int softClippedBaseCount) { assert(softClippedBaseCount >= 0); while (cigar.get(0).getOperator() == CigarOperator.H) { cigar.remove(0); } if (softClippedBaseCount == 0) return; if (cigar.get(0).getOperator() == CigarOperator.SOFT_CLIP) { cigar.set(0, new CigarElement(cigar.get(0).getLength() + softClippedBaseCount, CigarOperator.SOFT_CLIP)); } else { cigar.add(0, new CigarElement(softClippedBaseCount, CigarOperator.SOFT_CLIP)); } } public static void addEndSoftClip(List<CigarElement> cigar, int softClippedBaseCount) {
/** * Checks whether or not the read has any cigar element that is not H or S * * @param read the read * @return true if it has any M, I or D, false otherwise */ public static boolean readHasNonClippedBases(GATKSAMRecord read) { for (CigarElement cigarElement : read.getCigar().getCigarElements()) if (cigarElement.getOperator() != CigarOperator.SOFT_CLIP && cigarElement.getOperator() != CigarOperator.HARD_CLIP) return true; return false; }
/** * @param cigarette CIGAR element (operator + length) encoded as an unsigned int. * @return Object representation of the CIGAR element. */ private static CigarElement binaryCigarToCigarElement(final int cigarette) { final int binaryOp = cigarette & 0xf; final int length = cigarette >>> 4; return new CigarElement(length, CigarOperator.binaryToEnum(binaryOp)); } }
static private void elementStraddlesClippedRead(List<CigarElement> newCigar, CigarElement c, int relativeClippedPosition, int clippedBases){ final CigarOperator op = c.getOperator(); int clipAmount = clippedBases; if (op.consumesReadBases()){ if (op.consumesReferenceBases() & relativeClippedPosition > 0){ newCigar.add(new CigarElement(relativeClippedPosition, op)); } if (!op.consumesReferenceBases()){ clipAmount = clippedBases + relativeClippedPosition; } } else if (relativeClippedPosition != 0){ throw new SAMException("Unexpected non-0 relativeClippedPosition " + relativeClippedPosition); } newCigar.add(new CigarElement(clipAmount, CigarOperator.S)); // S is always last element }
private static void removeZeroWidthElements(List<CigarElement> list) { for (int i = list.size() - 1; i >= 0; i--) { if (list.get(i).getLength() == 0) { list.remove(i); } } } private static void mergeAdjacent(List<CigarElement> list) {
/** Returns the number of soft-clipped bases until a non-soft-clipping element is encountered. */ private static int lengthOfSoftClipping(Iterator<CigarElement> iterator) { int clipped = 0; while (iterator.hasNext()) { final CigarElement elem = iterator.next(); if (elem.getOperator() != CigarOperator.SOFT_CLIP && elem.getOperator() != CigarOperator.HARD_CLIP) { break; } if (elem.getOperator() == CigarOperator.SOFT_CLIP) { clipped = elem.getLength(); } } return clipped; }
public static void addEndSoftClip(List<CigarElement> cigar, int softClippedBaseCount) { assert(softClippedBaseCount >= 0); while (cigar.get(cigar.size() - 1).getOperator() == CigarOperator.H) { cigar.remove(cigar.size() - 1); } if (softClippedBaseCount == 0) return; if (cigar.get(cigar.size() - 1).getOperator() == CigarOperator.SOFT_CLIP) { cigar.set(cigar.size() - 1, new CigarElement(cigar.get(cigar.size() - 1).getLength() + softClippedBaseCount, CigarOperator.SOFT_CLIP)); } else { cigar.add(new CigarElement(softClippedBaseCount, CigarOperator.SOFT_CLIP)); } } public static List<CigarElement> trimClipping(List<CigarElement> cigar) {