RNA-Seq Data Analysis

Lesson 4 of 13 · 11 min

Adapter and Quality Trimming

Your FastQC report flagged adapter contamination and a drop in per-base quality toward the 3' end of each read. Both are artifacts of the sequencing chemistry rather than biology: adapters get read through whenever the insert is shorter than the read length, and base quality decays as the run progresses. Trimming removes them so downstream alignment and quantification see cleaner sequence.

Trim Galore, paired end

bash
trim_galore \
  --paired \
  --quality 20 \
  --length 36 \
  --fastqc \
  --cores 4 \
  --output_dir trimmed/ \
  sample_R1.fastq.gz sample_R2.fastq.gz
Path to Cutadapt set as: 'cutadapt'
Cutadapt seems to be working fine (tested command 'cutadapt --version' returned '4.9')

Found perfect matches for the Illumina adapter AGATCGGAAGAGC (count: 138204)
Using Illumina adapter for trimming (count: 138204). Second best hit was smallRNA (count: 0)

=== Summary ===
Total reads processed:              5,000,000
Reads with adapters:                2,914,663 (58.3%)
Reads written (passing filters):    5,000,000 (100.0%)

Number of sequence pairs removed because at least one read was
shorter than the length cutoff (36 bp): 41,207 (0.82%)

Trim Galore auto-detects the adapter (Illumina, Nextera, or small-RNA) from the first reads, so you rarely pass it by hand. The -q 20 threshold (long form --quality) trims 3' bases below Phred 20 using the same algorithm as BWA, --length 36 discards any pair whose reads fall below 36 bp after trimming, and --paired keeps the two mates in sync by removing both reads if either gets too short. Validated reads land in trimmed/sample_R1_val_1.fq.gz and trimmed/sample_R2_val_2.fq.gz alongside a per-file trimming report.

The fastp alternative

bash
fastp \
  --in1 sample_R1.fastq.gz --in2 sample_R2.fastq.gz \
  --out1 sample_R1.trimmed.fastq.gz --out2 sample_R2.trimmed.fastq.gz \
  --detect_adapter_for_pe \
  --qualified_quality_phred 20 \
  --cut_tail --cut_tail_mean_quality 20 \
  --length_required 36 \
  --thread 4 \
  --html fastp.html --json fastp.json

fastp is a single C++ tool that trims, filters, and writes its own HTML report in one pass. For paired-end reads it already trims read-through adapters by overlap analysis of the two mates by default; --detect_adapter_for_pe additionally switches on tail-based adapter-sequence auto-detection, which catches pairs the overlap step misses. -q 20 (the long form is --qualified_quality_phred) marks low-quality bases, --cut_tail slides a window in from the 3' end and trims once its mean quality drops below 20, and --length_required 36 drops pairs that become too short. It streams gzip in and out, so on large libraries it is noticeably faster than the Cutadapt-based path.

Confirm with FastQC

bash
mkdir -p fastqc_after/
fastqc trimmed/sample_R1_val_1.fq.gz trimmed/sample_R2_val_2.fq.gz --outdir fastqc_after/

FastQC will not create the output directory, so make it first. Re-running should turn the Adapter Content and 3' per-base quality plots green; a newly ragged Sequence Length Distribution is expected after trimming, not a failure. Adapter removal almost always helps, and light quality trimming helps splice-aware aligners like STAR or HISAT2 place reads correctly. Before pseudo-aligners such as salmon or kallisto, keep trimming gentle: their k-mer matching tolerates a few low-quality bases, so aggressive quality trimming mainly deletes real signal, shrinks the mappable k-mer evidence, and can bias expression estimates.

Try it yourself: Take a small paired-end RNA-seq sample (for example SRR1039508, subsampled to about 1M read pairs with seqtk sample). Run FastQC on the raw R1/R2 files, then trim with trim_galore --paired -q 20 --length 36, and run FastQC again on the resulting *_val_1.fq.gz and *_val_2.fq.gz files. Compare the Per base sequence quality and Adapter Content modules before and after, and note how the Sequence Length Distribution shifts from a single fixed length to a range.