5 Quality Control and Preprocessing: Implementations
Everything on this page is generated from tools/qc.json. If something here is wrong or out of date, the fix belongs in that file, not in this prose.
For what QC can and cannot tell you, see Section 4.1.
5.1 Start here
Two tools cover the common case: one that reports and trims in a single pass, and one that collects the results across every sample into a report somebody will actually open.
Reports quality metrics and applies trimming in a single pass over the data, which is the practical argument for it: the alternative is reading every read twice with two tools that disagree about what they saw. It detects adapters rather than requiring you to name them, which removes the most common way this step is got wrong. (Chen et al. 2018)
Collects the output of the other tools on this page across every sample and renders one report. That is the difference between per-sample QC nobody opens and a plot in which the outlying sample is obvious, which is the only way QC actually gets looked at on a real study. (Ewels et al. 2016)
5.2 Looking at the reads
These report without changing anything, which is the right shape for the question in Section 4.1 — is this library what I think it is?
Three of the four below produce the same familiar set of plots and differ in speed and runtime; the fourth exists because long reads need different plots entirely, for the reason given in the same section. The last answers the identity question directly rather than by inference.
| Tool | Upstream | Languages | Why / why not |
|---|---|---|---|
| Falco | active | C++ |
A drop-in reimplementation of the analysis above, producing the same reports substantially faster and without a JVM. Worth adopting where read QC is a per-sample cost across a large study; the reason to stay with the original is familiarity rather than capability. (Sena Brandine and Smith 2019) |
| FastQ Screen | active | pl |
Answers the question the other QC tools cannot: is this library the organism you think it is? It maps a subsample against several reference genomes and reports where the reads went, which catches sample swaps, mislabeled libraries and contamination in one cheap step. (Wingett and Andrews 2018) |
| FastQC | maintained | java |
The tool that defined what read QC looks like, and the reason every other entry here emits compatible output. Its plots are what reviewers and collaborators expect. It is listed as viable rather than recommended because it only reports — anything it finds still needs a second tool to act on. |
| NanoPlot | active | py |
Long-read QC asks different questions, and this answers them: read length distribution, quality against length, yield above a length threshold. The short-read tools report per-base quality across a fixed cycle count, which is close to meaningless when reads vary from hundreds to millions of bases. (De Coster and Rademakers 2023) |
A red flag on an amplicon, small-RNA or bisulfite library is usually the check being wrong about your experiment rather than your experiment being wrong. The thresholds encode expectations for a generic shotgun library. Look at the plots.
5.3 Trimming
The recommended tool in Section 5.1 already trims, and detects adapters without being told what they are. The card below is for when that is not enough — non-standard libraries, primers to anchor, linked adapters, error rates you need to set yourself.
Section 4.4 is the thing to read before turning any of it up. Adapter removal is free; quality trimming is not, and the sliding-window advice embedded in a great many older pipelines has aged badly.
The adapter trimmer with the most precise control over what is removed: anchored and non-anchored adapters, linked adapters, error rates, minimum overlaps. Reach for it when the library is not a standard one — amplicons with primers, small RNA with 3’ adapters, anything where a detector’s guess is not good enough. (Martin 2011)
| Tool | Upstream | Languages | Why / why not |
|---|---|---|---|
| Trimmomatic | active | java |
Enormously used for a decade, and the reason a great many published pipelines specify a sliding-window quality trim. It is listed as legacy because a new pipeline gets the same work done in one pass by the tools above, not because it is broken — it released again in 2025 and 2026 after a long gap. (Bolger et al. 2014) |
5.4 Duplicates
Which of these applies is decided by the library, not by preference. If it carries unique molecular identifiers, duplicates can be observed rather than inferred, and the tag-aware tool is the correct choice. Without them, coordinate-based marking is the best available and its limitations are the ones in Section 4.5.
Both mark rather than delete. Keep it that way — a flag is recoverable and a removed read is not, and for expression data you will want them back.
| Tool | Upstream | Languages | Why / why not |
|---|---|---|---|
| Picard | active | java |
MarkDuplicates is the reference implementation of coordinate-based duplicate marking, and its output is what downstream tools were validated against. It marks rather than removes, which is the right default: the flag is recoverable and the read is not. |
| UMI-tools | active | py |
When the library carries unique molecular identifiers, duplicates can be identified by tag rather than inferred from coordinates, which is the only way to distinguish a PCR duplicate from two genuinely independent fragments at the same position. It models sequencing errors in the tags themselves rather than requiring exact matches. (Smith et al. 2017) |
5.5 What is not here
Base calling is upstream of everything on this page and is not surveyed. It is instrument-vendor software, it changes with each chemistry, and the practical choice is usually made for you by the platform — but note that basecaller version changes quality scores and error profiles, which makes it a variable worth recording alongside the reads.
Demultiplexing is absent for the same reason: it is normally done by the sequencing facility with vendor tooling before you receive anything.
5.6 Language coverage
This is the most mixed page in the book, and the reason is that these tools do little computation each. The per-pass work is trivial next to alignment or assembly, so implementation language was chosen for convenience rather than speed — Java, Python, Perl and C++ all appear, and two of the entries are reimplementations of a third in a faster language, which is the clearest evidence that the original choice was not performance-driven.
There are no bindings, and none are wanted. Every tool here is a step in a shell pipeline that reads files and writes files; there is no in-process use for them. The exception worth knowing is that the aggregation tool parses the others’ output files, so its input is their output format rather than their API — which is why adding a new tool to a report is a matter of it writing a recognized file, not of anyone integrating anything.