OmevraOmevra Omevra — all products

Omevra · Product four

NGS Pipeline Atlas

A reproducible bacterial whole-genome sequencing pipeline — paired-end reads in, per-sample QC-gated variant calls out — run on a public E. coli cohort, and run twice to prove it reproduces.

The pipeline, drawn

One Nextflow workflow (main.nf) takes a samplesheet of paired-end FASTQ files and a reference genome, and processes every sample through the same stages. The run cohort is ENA study PRJNA234495 — Escherichia coli K-12 whole-genome resequencing, Illumina HiSeq 2000 paired-end — aligned against the MG1655 complete genome, NC_000913.3. A sample that fails a gate has its BAM removed inside the gate step and never reaches variant calling; the reason is written to its gate log.

FETCHMD5-verifiedSANITIZEpair integrityFASTQC/FASTPQC + trimmingALIGNBWA-MEMGATE3 fixed gatesCALLbcftoolsREPORTown PythonSTOPPED AT THE GATE — 6 samplesBAM removed inside the gate step; never reaches calling

Every sample travels the same path. The only exit is the gate: pass all three thresholds and the sample is called; fail one and it stops there, with the reason logged.

Per-stage timing — median task time, run 1 trace

StageTasksMedian task time
FETCH336 s (local mirror)
SANITIZE3366 s
FASTQC3311 s
FASTP3320 s
ALIGN3344 s
GATE334 s
CALL2724 s
REPORT11 s

FETCH's median reflects the local mirror the reproducibility runs ingested from (see “Fetching from the archive” below), not the throttled archive itself.

QC gates — the cohort outcome

A sample passes only if all three hold — thresholds fixed before the cohort run, at standard bacterial WGS values: mean coverage ≥ 10.0× (samtools coverage), reads mapped ≥ 80% (samtools flagstat), Q30 bases ≥ 70% (fastp, post-filtering).

33Samples attempted — 32 screened cohort runs plus the deliberate bad input BADINPUT01
27Passed all three gates and reached variant calling
6Stopped at the gates — every one on the coverage gate
130,614Variant records across the passed samples — 81,810 unique sites

Passed vs stopped

27 of 33samples passed the gates
Passed all three gates — went on to variant calling27
Stopped at the coverage gate6

The six stops — mean coverage against the 10.0× gate

BADINPUT01 (deliberate bad input)0.01×SRR11218418.82×SRR11218959.03×SRR11219189.33×SRR11219239.70×SRR11219299.99×

Coverage was the deciding metric. All six stopped samples had ~98% of reads mapped and Q30 of 96% — they failed on depth alone, five genuine samples landing between 8.82× and 9.99×, just under the line.

SampleMean coverageCoverage gateNote
BADINPUT01 (deliberate bad input)0.01×≥ 10.0×deliberate bad input
SRR11218418.82×≥ 10.0×genuine cohort sample
SRR11218959.03×≥ 10.0×genuine cohort sample
SRR11219189.33×≥ 10.0×genuine cohort sample
SRR11219239.70×≥ 10.0×genuine cohort sample
SRR11219299.99×≥ 10.0×genuine cohort sample

The gate step's own log line for the deliberate bad input, verbatim — identical in both runs:

[GATE] BADINPUT01 STOPPED reason: mean_coverage=0.01x < gate 10.00x (mean_coverage=0.01x pct_mapped=97.42 q30_pct=96.00)

BADINPUT01 is the first 400 read pairs of a cohort sample (~0.02× coverage), included in the samplesheet to prove the coverage gate stops under-covered samples. No BADINPUT01 VCF exists in either run's output.

Variant totals

Calling (bcftools mpileup + call) ran on the 27 passed samples only. Across them the cohort holds 130,614 variant records at 81,810 unique sites, with per-sample counts from 3,259 to 7,689. The full per-sample table — coverage, mapped percentage, Q30 and variants called for all 33 samples — is in the cohort reports under Downloads.

Reproducibility — two runs, byte-identical

The pipeline was executed twice end to end from the same samplesheet, in fully separate work and output directories — run 2 in an isolated launch directory, so no task result could be reused from run 1's cache. Inputs are content-addressed (FETCH refuses any payload whose MD5 differs from the samplesheet) and the environment is locked to exact tool builds (environment-explicit.txt).

Given the MD5-pinned inputs and the locked environment, two independent executions produce identical variant calls and identical reports.

The sanitize finding — corruption inside authentic files

The legacy files in this study are corrupt in two ways, and the corruption is in the archive, not the transfer: the files' MD5 checksums match the archive's published values. A structural pre-screen of 50 candidate runs admitted 32 and rejected 18 — every rejection a mate-2 record-structure desync. A full-content validation pass then found in-line byte garbage (non-IUPAC bytes inside sequence lines, concentrated in mate 2) even inside admitted files, so that second corruption class is handled at read level by the pipeline's own sanitize stage (bin/sanitize_pairs.py): it parses tolerantly, validates every record — IUPAC sequence alphabet, printable quality bytes, matched lengths — drops corrupt pairs, writes canonical 4-line FASTQ, and counts everything it drops, per sample.

Read pairs processed27,175,960Pairs kept27,071,276Corrupt pairs dropped104,684 (0.39%)

104,684 corrupt pairs dropped (0.39%) out of 27,175,960 processed — identical totals in both runs, and 0 unparseable fragments. BADINPUT01: 400 pairs in, 390 kept.

Fetching from the archive — the honest note

The archive rate-limits sustained fetching hard: HTTP 403 pages under load, and transfers that occasionally truncate or stall. FETCH is built for exactly that — downloads retry with backoff until the payload is byte-identical to the samplesheet's MD5, and a payload that differs is refused, never silently accepted. Because the throttling was hard enough to stall the cohort's 66-file download set, the files were additionally staged in a local mirror with resumable, MD5-verified downloads; the reproducibility runs ingest from the mirror, while the canonical samples.tsv keeps the original archive URLs and FETCH performs the same MD5 verification either way.

Downloads

The project's own results documents, byte-identical to the files in the project:

What this does not claim

Every figure on this page is taken from the project's RESULTS.md and the two runs' cohort reports, and is cross-checked against both at build time.

Evaluations

The standalone proof page for this product: Evaluations — the protocol, the versioned results, and every result file as a download.