I have a bam file aligned to a reference sequence. I am interested in finding the number of reads for read length 18 to 34, where the last base is mis-matched. I got this bam file from bowtie alignment allowing 3 mismatches (-v 0) option, so I am expecting some of the reads to have terminal bases mis-matched. How can we count the number of sequences of a specific length with terminal mismatch in bam file?


I have created a bowtie aligned .sam file with this command: bowtie -S -p 18 /media/owner/ref.fa test1.fastq test1.sam

which I then converted to .bam file like this: samtools view -bS -o test1.bam test1.sam

From this test1.bam, I was able to get the total number of plus and minus strand of reads aligned to the reference loci using bedtools coverage maping (for positives reads and negative reads) like this: bedtools coverage -a my_region.bed -b test1.bam -bed -d -s | gzip > test1_region_pos.tsv.gz

Since I used default bowtie option which allows for three mismatches, I want to know how many reads are aligned with terminal mismatches (i.e,last three, last two and last one base mismatched at 3' region of the aligned reads at their loci position).

  • $\begingroup$ Have you looked into using the R Bioconductor Rsamtools::scanBam function? It can import a BAM file into R and then you can easily get the CIGAR string and check the CIGAR string for mismatches? $\endgroup$ Feb 27 '18 at 13:54
  • $\begingroup$ Yes I tried using pileup package, but couldn't figure out how to get cigar string. $\endgroup$
    – MAPK
    Feb 27 '18 at 13:56

Could you provide some examples of lines that should be counted? I'm not sure how mismatches are encoded in the version of Bowtie you're using. As far as I remember, Bowtie doesn't distinguish between = and X in CIGARs (and uses M for both), therefore, mismatches must be detected from the MD tag.

You can use SAMsift for filtering the alignments. The following filtering criterion should keep only reads with read length from 18 to 34 that have an MD tag with 0 as the last character, which must be preceded by a non-number (this should signalise a mismatch at the last position).

samsift \
  -i test1.bam \
  -f '18 <= len(SEQ) <= 34 and MD[-1]=="0" and not MD[-2].isdigit()' \
  -m nonstop-remove

The obtained alignments can be counted by adding | samtools view | wc -l.


  • -f ... – filtering criterion
  • 18 <= len(SEQ) <= 34 – the allowed read lengths
  • MD[-1]=="0" – the last character of the MD tag is 0
  • not MD[-2].isdigit() – the penultimate character of the MD tag is not a digit
  • -m nonstop-remove – remove alignments without any MD tag (probably unaligned, they would cause an error).
  • $\begingroup$ Thanks for your answer. I have updated the question with how I created BAM file. $\endgroup$
    – MAPK
    Feb 27 '18 at 2:00
  • $\begingroup$ Could you explain this a bit please MD[-1]=="0" and not MD[-2].isdigit()? $\endgroup$
    – MAPK
    Feb 27 '18 at 2:01
  • $\begingroup$ Does this also consider for + and - strands? $\endgroup$
    – MAPK
    Feb 27 '18 at 2:02
  • $\begingroup$ Please, could you show at least one line that should pass the filter? I need it to verify the MD filtering step. Yes, it's possible to filter using +/- via FLAG. $\endgroup$ Feb 27 '18 at 2:04
  • $\begingroup$ The bowtie -v 1 option allows one mismatch, -v 2, alows 2 mismatches anywhere in the sequences. The default option allows maximum of 3 mismatches. $\endgroup$
    – MAPK
    Feb 27 '18 at 2:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.