/** * Hard clip bases from read, from start to stop in base coordinates * * <p>If start == 0, then we will clip from the front of the read, otherwise we clip from the * right. If start == 0 and stop == 10, this would clip out the first 10 bases of the read. * * <p>Note that this function works with reads with negative alignment starts, in order to allow * us to hardClip reads that have had their soft clips reverted and so might have negative * alignment starts * * <p>Works properly with reduced reads and insertion/deletion base qualities * * @param read a non-null read * @param start a start >= 0 and < read.length * @param stop a stop >= 0 and < read.length. * @return a cloned version of read that has been properly trimmed down */ private GATKSAMRecord hardClip(GATKSAMRecord read, int start, int stop) { // If the read is unmapped there is no Cigar string and neither should we create a new cigar // string final CigarShift cigarShift = (read.getReadUnmappedFlag()) ? new CigarShift(new Cigar(), 0, 0) : hardClipCigar(read.getCigar(), start, stop); // the cigar may force a shift left or right (or both) in case we are left with insertions // starting or ending the read after applying the hard clip on start/stop. final int newLength = read.getReadLength() - (stop - start + 1) - cigarShift.shiftFromStart - cigarShift.shiftFromEnd; final byte[] newBases = new byte[newLength]; final byte[] newQuals = new byte[newLength]; final int copyStart = (start == 0) ? stop + 1 + cigarShift.shiftFromStart : cigarShift.shiftFromStart; System.arraycopy(read.getReadBases(), copyStart, newBases, 0, newLength); System.arraycopy(read.getBaseQualities(), copyStart, newQuals, 0, newLength); final GATKSAMRecord hardClippedRead = (GATKSAMRecord) read.clone(); hardClippedRead .resetSoftStartAndEnd(); // reset the cached soft start and end because they may have // changed now that the read was hard clipped. No need to calculate // them now. They'll be lazily calculated on the next call to // getSoftStart()/End() hardClippedRead.setBaseQualities(newQuals); hardClippedRead.setReadBases(newBases); hardClippedRead.setCigar(cigarShift.cigar); if (start == 0) hardClippedRead.setAlignmentStart( read.getAlignmentStart() + calculateAlignmentStartShift(read.getCigar(), cigarShift.cigar)); if (read.hasBaseIndelQualities()) { final byte[] newBaseInsertionQuals = new byte[newLength]; final byte[] newBaseDeletionQuals = new byte[newLength]; System.arraycopy( read.getBaseInsertionQualities(), copyStart, newBaseInsertionQuals, 0, newLength); System.arraycopy( read.getBaseDeletionQualities(), copyStart, newBaseDeletionQuals, 0, newLength); hardClippedRead.setBaseQualities(newBaseInsertionQuals, EventType.BASE_INSERTION); hardClippedRead.setBaseQualities(newBaseDeletionQuals, EventType.BASE_DELETION); } return hardClippedRead; }