Skip to content

Quality Control of NGS Reads with FastQC and MultiQC

By Bio Help Learning35 min readUpdated FREE

Chapter 3 of 5: Adapters and trimming

Why adapters appear at the end of reads

During library preparation, short adapter sequences are joined to both ends of every DNA fragment (the insert). The sequencer reads from the adapter into the insert. If the insert is longer than the read length, the read contains only insert. If the insert is shorter, the read runs through the whole insert and into the adapter on the other side.

Adapter read-through when the insert is shorter than the read length
Short inserts cause adapter read-through at the 3′ end.

How fastp finds adapters in paired-end data: read 1 and read 2 come from the same fragment, so when the insert is short they overlap. fastp aligns read 1 with the reverse complement of read 2. Where they overlap, it knows exactly where the insert ends, and any bases beyond that point are adapter. This works even if you do not know the adapter sequence. For single-end data, fastp looks at the first reads, finds k-mers that appear unusually often near read ends and assembles them into the likely adapter. With --detect_adapter_for_pe, it also runs this detection on paired-end data as a second check.

▸ Go deeper: the maths of adapter read-through, adapter sequences and dimers

A read contains adapter whenever the insert is shorter than the read length, and the adapter starts exactly at position insert length + 1. So FastQC’s adapter-content curve is really the cumulative distribution of your insert sizes: if 23% of fragments are shorter than 150 bp, about 23% of 150 bp reads will contain adapter by their last base. That is exactly what you will see in the tutorial dataset.

Library typeAdapter start (read 1)FastQC name
Illumina TruSeq and most ligation kitsAGATCGGAAGAGC…Illumina Universal Adapter
Nextera / tagmentation (incl. ATAC-seq)CTGTCTCTTATACACATCTNextera Transposase Sequence
Illumina small RNA 3′TGGAATTCTCGG…Illumina Small RNA 3′ Adapter

Adapter dimers form when two adapters join with no insert between them. Such reads start with adapter at position 1, appear as an overrepresented sequence beginning with the adapter, and become zero-length after trimming. A few percent is common; a large fraction means too little input DNA or poor size selection.

🔬 Researcher notes: how the main tools actually find adapters

  • fastp, paired-end: overlap analysis. Read 1 is aligned to the reverse complement of read 2; where they overlap, the insert end is known exactly, so no adapter sequence is needed. In the overlap, fastp also corrects a mismatched base when one read has high quality and the other very low (Chen et al. 2018).
  • fastp, single-end: adapter detection by assembling high-frequency read tails: frequent k-mers near read ends are used as seeds and extended into the full adapter. Adding --detect_adapter_for_pe to paired data typically finds about 0.1–0.5% more adapters, because overlap detection can fail when errors are present (fastp documentation).
  • Cutadapt: semiglobal (ends-free) alignment of the given adapter against each read, accepting matches up to a maximum error rate counted as mismatches plus indels (Martin 2011; Cutadapt documentation). It is precise but needs the adapter sequence.
  • Trimmomatic: “simple” mode aligns known adapters with seed-and-extend; “palindrome” mode detects read-through in pairs from the reverse-complement relationship of the two reads, which finds even very short adapter fragments (Bolger et al. 2014).
  • If your library has UMIs, extract them into the read name first (for example fastp --umi) so trimming does not destroy them.

Step 4: Trim adapters and low-quality bases with fastp

bashCopy disabled · Buy the study material or join membership to copy code
fastp -i sample_R1.fastq.gz -I sample_R2.fastq.gz \
      -o trim_R1.fastq.gz -O trim_R2.fastq.gz \
      --detect_adapter_for_pe \
      --cut_tail --cut_window_size 4 --cut_mean_quality 20 \
      --length_required 36 \
      -h fastp.html -j fastp.json -w 4

What each option does:

  • -i, -I: input read 1 and read 2; -o, -O: output files (pairs stay in sync)
  • --detect_adapter_for_pe: adds sequence-based adapter detection on top of the overlap method
  • --cut_tail --cut_window_size 4 --cut_mean_quality 20: sliding-window trimming from the 3′ end (see the algorithm below)
  • --length_required 36: drops reads shorter than 36 bp after trimming, because very short reads map to many places
  • -h, -j: fastp’s own HTML and JSON reports; MultiQC reads the JSON
  • -w 4: 4 worker threads

fastp also applies some filters by default: it removes reads with too many low-quality bases or too many N bases, and on NextSeq and NovaSeq data it trims poly-G tails (these two-colour instruments report “no signal” as G).

▸ Go deeper: fastp defaults you are using without knowing it, and the three cutting modes
  • Quality filter (on by default): a base below Q15 counts as “unqualified” (-q 15); a read is discarded if more than 40% of its bases are unqualified (-u 40) or it has more than 5 N bases (-n 5).
  • Length filter: default minimum 15 bp (-l 15); this tutorial raises it to 36.
  • Poly-G trimming: switched on automatically for NovaSeq and NextSeq data (-g forces it, -G disables it).
  • Pairs stay in sync: if one mate fails, both are dropped unless you ask fastp to keep unpaired reads (--unpaired1, --unpaired2).
fastp modeWhat it doesUse it when
--cut_tailWindow moves from the 3′ end towards the start; low-quality windows are dropped until a good one is foundStandard quality trimming (this tutorial)
--cut_frontThe same, from the 5′ end towards the 3′ endPoor first cycles
--cut_rightWindow moves from the 5′ end; at the first bad window, that window and everything to its right are removedStrict, Trimmomatic SLIDINGWINDOW-like; can cut reads short
TaskfastpTrimmomaticCutadapt
Adapters (paired)automatic, or --adapter_sequenceILLUMINACLIP:adapters.fa:2:30:10-a ADAPTER -A ADAPTER
3′ quality trimming--cut_tail --cut_mean_quality 20SLIDINGWINDOW:4:20-q 20
Minimum length-l 36MINLEN:36-m 36

The sliding-window trimming algorithm

Instead of cutting at the first bad base (one random low score would cut too much), fastp looks at the average quality of a small window of bases:

Sliding window tail trimming example with window size 4 and mean quality 20
A window of 4 bases moves from the 3′ end towards the start until its mean quality reaches the threshold.
textCopy disabled · Buy the study material or join membership to copy code
read  = list of quality scores, length n
w     = window size (4)
T     = mean quality threshold (20)

end = n
while end >= w:
    window = read[end - w : end]
    if mean(window) < T:
        end = end - w        # drop the bases in this window
    else:
        break                # good window found: stop
keep read[0 : end]
if end < length_required: discard the read (and its mate)

Because it averages, one low base inside good sequence is kept, while a run of bad bases at the end is removed. The same idea is used by Trimmomatic’s SLIDINGWINDOW option.

Expected outputSign in free to see the expected output. No payment needed.Sign in / Create free account
▸ Go deeper: the partial-sum algorithm used by Cutadapt and BWA

Cutadapt’s -q option uses the same algorithm as BWA: subtract the cutoff from every quality, add the results up from the 3′ end, and cut where that running sum is lowest. Worked example from the Cutadapt documentation, cutoff 10:

StepValues (5′ → 3′)
Qualities42, 40, 26, 27, 8, 7, 11, 4, 2, 3
Minus cutoff 1032, 30, 16, 17, −2, −3, 1, −6, −8, −7
Partial sums from the 3′ end(70), (38), 8, −8, −25, −23, −20, −21, −15, −7
ResultThe minimum, −25, sits at base 5, so the read keeps bases 1–4 (42, 40, 26, 27)

Notice the Q11 base: it is above the cutoff, but it sits inside a bad tail, so it is removed too. A simple “cut at the first base below 10” rule would have kept it. Trimmomatic’s MAXINFO mode goes further and balances read length against expected errors; its authors recommend it over SLIDINGWINDOW.

🔬 Researcher notes: does trimming actually help? What the evidence says

Trimming is not automatically good. Two widely cited studies:

  • Williams et al. 2016 (BMC Bioinformatics): with the most aggressive quality trimming, over 10% of genes changed their estimated expression significantly. Most of the effect came from very short reads mapping spuriously, and a minimum-length filter removed most of it. No or modest trimming gave the most biologically accurate estimates.
  • Liao & Shi 2020 (NAR Genomics and Bioinformatics): aligners that soft-clip handle adapters and poor read ends themselves. Gene-level quantification from untrimmed reads was comparable to, or slightly better than, trimmed reads when checked against RT-qPCR, and total analysis time fell by up to an order of magnitude.
  • MacManes 2014 (Frontiers in Genetics): for de novo transcriptome assembly, gentle quality trimming (about Phred 2–5) performed better than aggressive trimming.
ApplicationRecommended practice
Bulk RNA-seq gene countsAdapter trimming only (or none with a soft-clipping aligner); always use a minimum length filter
WGS / WES variant callingAdapter trimming plus light 3′ quality trimming (Q15–20); keep pairs; recalibrate base qualities later
De novo assemblyAdapter trimming plus gentle quality trimming
Small RNA, ampliconAdapter (and primer) trimming is essential
Low-quality or degraded samplesTrimming matters most here; check how many reads you lose