    public void mergeAlignment() {
        final SAMRecordQueryNameComparator comparator = new SAMRecordQueryNameComparator();
        final SAMFileReader unmappedSam = new SAMFileReader(this.unmappedBamFile);
        final CloseableIterator<SAMRecord> unmappedIterator = unmappedSam.iterator();
        this.header.setReadGroups(unmappedSam.getFileHeader().getReadGroups());
        int aligned = 0;
        int unmapped = 0;
        final CloseableIterator<SAMRecord> alignedIterator = getQuerynameSortedAlignedRecords();
        SAMRecord nextAligned = alignedIterator.hasNext() ? alignedIterator.next() : null;
        final SortingCollection<SAMRecord> coordinateSorted = SortingCollection.newInstance(
            SAMRecord.class, new BAMRecordCodec(header), new SAMRecordCoordinateComparator(),
            MAX_RECORDS_IN_RAM);
        SAMRecord firstOfPair = null;
        while (unmappedIterator.hasNext()) {
            final SAMRecord rec = unmappedIterator.next();
            if (nextAligned != null && comparator.compare(rec, nextAligned) > 0) {
                throw new IllegalStateException("Aligned record iterator (" + nextAligned.getReadName() +
                        ") is behind the unmapped reads (" + rec.getReadName() + ")");
            }
            rec.setHeader(this.header);
            if (isMatch(rec, nextAligned)) {
                if (!(nextAligned.getReadUnmappedFlag() || ignoreAlignment(nextAligned))) {
                    setValuesFromAlignment(rec, nextAligned);
                    updateCigarForTrimmedOrClippedBases(rec, nextAligned);
                    if (this.programRecord != null) {
                        rec.setAttribute(ReservedTagConstants.PROGRAM_GROUP_ID,
                            this.programRecord.getProgramGroupId());
                    }
                    aligned++;
                }
                else {
                    unmapped++;
                }
                nextAligned = alignedIterator.hasNext() ? alignedIterator.next() : null;
            }
            else {
                unmapped++;
            }
            if (!rec.getReadPairedFlag()) {
                if (!rec.getReadUnmappedFlag() || !alignedReadsOnly) {
                    coordinateSorted.add(rec);
                }
            }
            else {
                if (firstOfPair == null) {
                    firstOfPair = rec;
                }
                else { 
                    if (!rec.getReadName().equals(firstOfPair.getReadName())) {
                        coordinateSorted.add(firstOfPair);
                        firstOfPair = rec;
                    }
                    else {
                        if ((!rec.getReadUnmappedFlag() || !firstOfPair.getReadUnmappedFlag()) || !alignedReadsOnly) {
                            clipForOverlappingReads(rec, firstOfPair);
                            SamPairUtil.setProperPairAndMateInfo(rec, firstOfPair, header, expectedOrientations);
                            coordinateSorted.add(firstOfPair);
                            coordinateSorted.add(rec);
                            firstOfPair = null;
                        }
                    }
                }
            }
        }
        unmappedIterator.close();
        if (alignedIterator.hasNext()) {
            throw new IllegalStateException("Reads remaining on alignment iterator: " + alignedIterator.next().getReadName() + "!");
        }
        alignedIterator.close();
        final SAMFileWriter writer = new SAMFileWriterFactory().makeSAMOrBAMWriter(header, true, this.targetBamFile);
        int count = 0;
        CloseableIterator<SAMRecord> it = coordinateSorted.iterator();
        while (it.hasNext()) {
            SAMRecord rec = it.next();
            if (!rec.getReadUnmappedFlag()) {
                if (refSeq != null) {
                    byte referenceBases[] = refSeq.get(sequenceDictionary.getSequenceIndex(rec.getReferenceName())).getBases();
                    rec.setAttribute(SAMTag.NM.name(),
                        SequenceUtil.calculateSamNmTag(rec, referenceBases, 0, bisulfiteSequence));
                    if (rec.getBaseQualities() != SAMRecord.NULL_QUALS) {
                        rec.setAttribute(SAMTag.UQ.name(),
                            SequenceUtil.sumQualitiesOfMismatches(rec, referenceBases, 0, bisulfiteSequence));
                    }
                }
            }
            writer.addAlignment(rec);
            if (++count % 1000000 == 0) {
                log.info(count + " SAMRecords written to " + targetBamFile.getName());
            }
        }
        writer.close();
        log.info("Wrote " + aligned + " alignment records and " + (alignedReadsOnly ? 0 : unmapped) + " unmapped reads.");
    }

    public void mergeAlignment() {
        final SAMRecordQueryNameComparator comparator = new SAMRecordQueryNameComparator();
        final SAMFileReader unmappedSam = new SAMFileReader(this.unmappedBamFile);
        final CloseableIterator<SAMRecord> unmappedIterator = unmappedSam.iterator();
        this.header.setReadGroups(unmappedSam.getFileHeader().getReadGroups());
        int aligned = 0;
        int unmapped = 0;
        final CloseableIterator<SAMRecord> alignedIterator = getQuerynameSortedAlignedRecords();
        SAMRecord nextAligned = alignedIterator.hasNext() ? alignedIterator.next() : null;
        final SortingCollection<SAMRecord> coordinateSorted = SortingCollection.newInstance(
            SAMRecord.class, new BAMRecordCodec(header), new SAMRecordCoordinateComparator(),
            MAX_RECORDS_IN_RAM);
        SAMRecord firstOfPair = null;
        while (unmappedIterator.hasNext()) {
            final SAMRecord rec = unmappedIterator.next();
            if (nextAligned != null && comparator.compare(rec, nextAligned) > 0) {
                throw new IllegalStateException("Aligned record iterator (" + nextAligned.getReadName() +
                        ") is behind the unmapped reads (" + rec.getReadName() + ")");
            }
            rec.setHeader(this.header);
            if (isMatch(rec, nextAligned)) {
                if (!(nextAligned.getReadUnmappedFlag() || ignoreAlignment(nextAligned))) {
                    setValuesFromAlignment(rec, nextAligned);
                    updateCigarForTrimmedOrClippedBases(rec, nextAligned);
                    if (this.programRecord != null) {
                        rec.setAttribute(ReservedTagConstants.PROGRAM_GROUP_ID,
                            this.programRecord.getProgramGroupId());
                    }
                    aligned++;
                }
                else {
                    unmapped++;
                }
                nextAligned = alignedIterator.hasNext() ? alignedIterator.next() : null;
            }
            else {
                unmapped++;
            }
            if (!rec.getReadPairedFlag()) {
                if (!rec.getReadUnmappedFlag() || !alignedReadsOnly) {
                    coordinateSorted.add(rec);
                }
            }
            else {
                if (firstOfPair == null) {
                    firstOfPair = rec;
                }
                else { 
                    if (!rec.getReadName().equals(firstOfPair.getReadName())) {
                        throw new PicardException("Second read from pair not found in unmapped bam: " +
                            rec.getReadName());
                    }
                    else {
                        if ((!rec.getReadUnmappedFlag() || !firstOfPair.getReadUnmappedFlag()) || !alignedReadsOnly) {
                            clipForOverlappingReads(rec, firstOfPair);
                            SamPairUtil.setProperPairAndMateInfo(rec, firstOfPair, header, expectedOrientations);
                            coordinateSorted.add(firstOfPair);
                            coordinateSorted.add(rec);
                            firstOfPair = null;
                        }
                    }
                }
            }
        }
        unmappedIterator.close();
        if (alignedIterator.hasNext()) {
            throw new IllegalStateException("Reads remaining on alignment iterator: " + alignedIterator.next().getReadName() + "!");
        }
        alignedIterator.close();
        final SAMFileWriter writer = new SAMFileWriterFactory().makeSAMOrBAMWriter(header, true, this.targetBamFile);
        int count = 0;
        CloseableIterator<SAMRecord> it = coordinateSorted.iterator();
        while (it.hasNext()) {
            SAMRecord rec = it.next();
            if (!rec.getReadUnmappedFlag()) {
                if (refSeq != null) {
                    byte referenceBases[] = refSeq.get(sequenceDictionary.getSequenceIndex(rec.getReferenceName())).getBases();
                    rec.setAttribute(SAMTag.NM.name(),
                        SequenceUtil.calculateSamNmTag(rec, referenceBases, 0, bisulfiteSequence));
                    if (rec.getBaseQualities() != SAMRecord.NULL_QUALS) {
                        rec.setAttribute(SAMTag.UQ.name(),
                            SequenceUtil.sumQualitiesOfMismatches(rec, referenceBases, 0, bisulfiteSequence));
                    }
                }
            }
            writer.addAlignment(rec);
            if (++count % 1000000 == 0) {
                log.info(count + " SAMRecords written to " + targetBamFile.getName());
            }
        }
        writer.close();
        log.info("Wrote " + aligned + " alignment records and " + (alignedReadsOnly ? 0 : unmapped) + " unmapped reads.");
    }
