samtools-markdup(1)

πŸ’… samtools-markdup(1) β€” the glam makeover your BAM never knew it needed

okay so this is samtools markdup, bestie, and it's literally the page about marking duplicate alignments in a coordinate sorted file. It's part of the whole bioinformatics tools situation (samtools-markdup(1)), and honestly it's giving "quietly essential". Let's get into it 🧚


✨ NAME ✨

samtools markdup β€” mark duplicate alignments in a coordinate sorted file πŸŽ€

🌸 SYNOPSIS 🌸

samtools markdup [-l length] [-r] [-T] [-S] [-s] [-f file] [--json] [-d
distance] [-c] [-t] [---duplicate-count] [-m] [--mode] [--include-fails]
[--no-PG] [-u] [--no-multi-dup] [--read-coords] [--coords-order]
[--barcode-tag] [--barcode-name] [--barcode-rgx] [--use-read-groups]
in.algsort.bam out.bam

(yes the [---duplicate-count] really has three dashes in there, that's not me being chaotic, that's just how it is, no cap πŸ’€)

πŸ¦‹ DESCRIPTION πŸ¦‹

So what this does: it marks duplicate alignments from a coordinate sorted file that's already been run through samtools fixmate with the -m option. Fr fr, this program depends on the MC and ms tags that fixmate gives you β€” no fixmate, no markdup. It's a whole dependency thing. 🫢

Duplicates get found by looking at the alignment data for each read (and its mate, for paired reads). Position and orientation β€” like which strand it aligns against and in what direction β€” are what's used to compare reads against each other. If two (or more) reads have the same values, then the one with the highest base qualities is held to be the original, and the others are the duplicates. The math is mathing ✨

Small but iconic note: samtools markdup looks for duplication first and then classifies the type of duplication afterwards. So if your process doesn't care whether the duplication is PCR or optical, it's faster if you don't use the optical duplicate option. Save yourself the time, bestie πŸ’…

Duplicates are marked by setting the alignment's DUP flag. Periodt.

For more details please see:

<http://www.htslib.org/algorithms/duplicate.html>

πŸ‘‘ OPTIONS πŸ‘‘

  • -l INT β€” expected maximum read length of INT bases. Default is [300], so don't come at it with a surprise 400bp read and expect zero drama.
  • -r β€” remove duplicate reads. Like, gone gone.
  • -T PREFIX β€” write temporary files to PREFIX.samtools.nnnn.mmmm.tmp. Yes, literally that naming pattern, that's the vibe.
  • -S β€” mark supplementary reads of duplicates as duplicates too. The duplicates' duplicates, basically. Recursive queen behavior.
  • -s β€” print some basic stats. Go check the STATISTICS section below, it's all laid out πŸ’–
  • -f file β€” write stats to the named file instead of just vibing in the terminal.
  • --json β€” output stats in JSON format. For the machine girlies πŸ€–
  • -d distance β€” the optical duplicate distance. Suggested settings: 100 for HiSeq style platforms, or about 2500 for NovaSeq ones. Default is 0, which means don't look for optical duplicates. When it's set, duplicate reads get tagged with dt:Z:SQ for optical duplicates and dt:Z:LB otherwise. Heads up though: calculating distance depends on coordinate data embedded in the read names produced by the Illumina sequencing machines. Optical duplicate detection will not work on non standard names without the use of --read-coords. So like, read that part twice, okay? 😭
  • -c β€” clear previous duplicate settings and tags. Fresh start, clean slate, new me.
  • -t β€” mark duplicates with the name of the original in a do tag. Like naming your kid after the ancestor.
  • --duplicate-count β€” record the original primary read duplication count (including itself) in a dc tag. Count your blessings, and also your dupes.
  • -m, --mode TYPE β€” the duplicate decision method for paired reads. Values are t or s. Mode t measures positions based on template start/end (this is the default). Mode s measures positions based on sequence start. While the two methods identify mostly the same reads as duplicates, mode s tends to return more results. Unpaired reads are treated identically by both modes. So it's a whole personality test for your pairs πŸ¦‹
  • -u β€” output uncompressed SAM, BAM or CRAM. Raw and unfiltered, we love that.
  • --include-fails β€” include quality checked failed reads. Give the fails a chance to shine ✨
  • --no-multi-dup β€” stop checking duplicates of duplicates for correctness. While still marking reads as duplicates, further checks to make sure all optical duplicates are found are not carried out. It also operates on -t tagging where reads may be tagged with a better quality read but not necessarily the best one. Using this option can speed up duplicate marking when there are a great many duplicates for each original read. Translation: chaos mode, but fast. πŸ”₯
  • --read-coords REGEX β€” this takes a POSIX regular expression for at least x and y to be used in optical duplicate marking. It can also include another part of the read name to test for equality, eg lane:tile elements. Elements wanted are captured with parentheses. Examples are down below, don't worry 🫢
  • --coords-order ORDER β€” the order of the elements captured in the regular expression. Default is txy where t is a part of the read name selected for string comparison and x/y are the coordinates used for optical duplicate detection. Valid orders are: txy, tyx, xyt, yxt, xty, ytx, xy and yx. So many options, so little time.
  • --barcode-tag TAG β€” duplicates must now also match the barcode tag. MatchingΒ².
  • --barcode-name β€” use the UMI/barcode embedded in the read name (the eigth colon delimited part). Yes it says "eigth", yes that's their typo, I'm leaving it, it's part of the lore πŸ’€
  • --barcode-rgx REGEX β€” regex for barcode in the readname. It's the alternative to --barcode-name, pick your fighter.
  • --move-umi-to-tag β€” move UMI from read name to RX tag (use with --barcode-name or --barcode-rgx). Relocation era ✈️
  • --umi-separator CHAR β€” character to use as separator for the UMI in the read name (default is :). If the UMI is at the end or beginning of the read name, the adjacent separator is removed. If the UMI is in the middle of the read name, it and one adjacent separator are removed, merging the remaining parts. Surgical separation bestie, precision work βœ‚οΈ
  • --use-read-groups β€” the @RG tags must now also match to be a duplicate. Group project rules apply.
  • --no-PG β€” do not add a PG line to the output file. No provenance, no problem.
  • -@, --threads INT β€” number of input/output compression threads to use in addition to the main thread, default [0]. More threads, more speed, more ✨

🌈 STATISTICS 🌈

When you flex the -s flag, these are the entries you get. Every single one, because we don't skip:

  • COMMAND: the command line. Screenshot of the crime.
  • READ: number of reads read in.
  • WRITTEN: reads written out.
  • EXCLUDED: reads ignored. See below πŸ‘‡
  • EXAMINED: reads examined for duplication.
  • PAIRED: reads that are part of a pair.
  • SINGLE: reads that are not part of a pair. Solo main character energy.
  • DUPLICATE PAIR: reads in a duplicate pair.
  • DUPLICATE SINGLE: single read duplicates.
  • DUPLICATE PAIR OPTICAL: optical duplicate paired reads.
  • DUPLICATE SINGLE OPTICAL: optical duplicate single reads.
  • DUPLICATE NON PRIMARY: supplementary/secondary duplicate reads.
  • DUPLICATE NON PRIMARY OPTICAL: supplementary/secondary optical duplicate reads.
  • DUPLICATE PRIMARY TOTAL: number of primary duplicate reads.
  • DUPLICATE TOTAL: total number of duplicate reads. The big number, the main event.
  • ESTIMATED LIBRARY SIZE: estimate of the number of unique fragments in the sequencing library.

πŸ“ about that estimated library size πŸ“

Okay so real talk β€” estimated library size makes various assumptions, e.g. that the library consists of unique fragments that are randomly selected (with replacement) with equal probability. That is... unlikely to be true in practice. πŸ™ˆ

However! It can still provide a useful guide into how many unique read pairs are likely to be available. In particular, it can be used to determine how much more data might be obtained by further sequencing of the library. So it's a vibe estimate, not a promise. Use it accordingly πŸ’œ

πŸ’€ excluded reads, explained πŸ’€

Excluded reads are those marked as secondary, supplementary or unmapped. By default, QC failed reads are also excluded β€” but you can include them as an option (--include-fails, hey bestie). Excluded reads are not used for calculating duplicates. They can optionally be marked as duplicates if they have a primary that is also a duplicate. So they're excluded from the math but not from the drama.


✨ EXAMPLES ✨

First things first: this first collate command can be omitted if the file is already name ordered or collated. Convenient!

samtools collate -o namecollate.bam example.bam

Add ms and MC tags for markdup to use later:

samtools fixmate -m namecollate.bam fixmate.bam

Markdup needs position order (it literally says coordinate sorted in the description, it was foreshadowing):

samtools sort -o positionsort.bam fixmate.bam

Finally, mark duplicates:

samtools markdup positionsort.bam markdup.bam

Typically the fixmate step would be applied immediately after sequence alignment, and the markdup step after sorting by chromosome and position. Thus, no additional sort steps are normally needed. So like, the pipeline basically assembles itself. Slay. πŸ”₯

πŸŽ€ regex era πŸŽ€

To use the regex to obtain coordinates from reads, two or three values have to be captured. To mimic the normal behaviour and match a read name of the format machine:run:flowcell:lane:tile:x:y, use:

--read-coords '([!-9;-?A-~]+:[0-9]+:[0-9]+:[0-9]+:[0-9]+):([0-9]+):([0-9]+)'
--coords-order txy

To match only the coordinates of x:y:randomstuff, use:

--read-coords '^([[:digit:]]+):([[:digit:]]+)'
--coords-order xy

To use a barcode from the read name matching the Illumina example of NDX550136:7:H2MTNBDXX:1:13302:3141:10799:AAGGATG+TCGGAGA, use:

--barcode-rgx '[0-9A-Za-z]+:[0-9]+:[0-9A-Za-z]+:[0-9]+:[0-9]+:[0-9]+:[0-9]+:([!-?A-~]+)'
⚠️ It is possible that complex regular expressions may slow the running of the program. It would be best to keep them simple. Your regex does not need to be a whole novel, bestie β€” keep it cute, keep it fast. 😭

πŸ’– AUTHOR πŸ’–

Written by Andrew Whitwham from the Sanger Institute. Icon behavior, honestly. πŸ‘‘

🫢 SEE ALSO 🫢

samtools(1), samtools-sort(1), samtools-collate(1), samtools-fixmate(1)

Samtools website: <http://www.htslib.org/>


and that's the whole page, bestie β€” this was samtools-1.24 from 9 July 2026, filed under samtools-markdup(1). Go forth and mark those dupes, you're gonna eat πŸ’…βœ¨

πŸ“¦ where this page comes from