Skip to content

migec 2.2.1 — the ctDNA ground truth was found, not built

Choose a tag to compare

@mikessh mikessh released this 13 Aug 21:36
· 78 commits to master since this release
d6573e3

The wheel is unchanged from 2.2.0. No command, flag, output file or number that migec itself
produces is different. Everything in this release is in the repository: a new documentation page,
the SLURM templates, the Nextflow downstream layer, two more notebooks, and the two scripts behind
them.

The ctDNA ground truth was found, not built

ROADMAP.md item 7 said a ctDNA ground truth had to be constructed, because the runs used by the
published UMI-aware caller benchmark carry no UMI. That is true of those two runs and not of the
archive. Screening SRA read structure instead turned up two studies that kept a real 12 nt inline
UMI — one that migec suggest recovers from base composition alone, with no knowledge of the
protocol:

study what it is
PRJNA788522 72 runs, cell-free DNA reference material at certified 0 / 0.125 / 0.25 / 1% VAF, crossed with 5/20/80 ng input and 3.3/10/30x depth, three replicates
PRJNA507366 28 runs, six polymerases on the same material, plus 0.031% and 0.0625% VAF

Run over all 100 (scripts/ctdna_titration.py): at 0.125% VAF the input mass decides the
outcome, not the caller.

input depth molecules at the site variant molecules P(at least 3 copies)
5 ng 3.3x 2,699 3.4 0.65
5 ng 10x 4,530 5.7 0.89
20 ng 3.3x 7,162 9.0 0.99
20 ng 10x 11,961 15.0 1.00

At 5 ng a 0.125% variant is a coin flip and no caller fixes it — a third of replicates simply do
not contain three copies of it. The WT arms are 33 runs and 6.1 M molecules in which the truth is
zero, which is a false-positive floor measured on real chemistry rather than on a simulation.

The barcode error rate tracks polymerase fidelity

PRJNA507366 varies the polymerase while holding template and protocol fixed, which makes it an
independent check on refine's barcode-error estimate. It separates the high-fidelity enzymes from
the standard ones by 3 Phred, a factor of two — Accuprime, Platinum and Phusion at Q30.8–31.4
against Platinum HiFi at Q34.0 and Platinum SuperFi at Q34.8–35.1 — from the barcodes alone, with
no reference, no alignment and no knowledge of which enzyme it was reading.

Also in this release

  • docs/variants.rst — which variant caller, and the molecule count that decides whether any
    of them can see it. Standard callers (Mutect2, LoFreq, FreeBayes, VarDict) compose with migec;
    UMI-aware ones (UMI-VarCal, UMIErrorCorrect) replace a stage. Never set a family-size filter
    after assemble: every family has size 1 by construction, so --min-family-size 3 discards the
    entire library and reports zero variants without an error.
  • integrations/slurm/ — two sbatch templates and a sample sheet. Both run as ordinary bash
    without SLURM, which is how they are tested and how a layout should be checked before a cohort is
    queued.
  • integrations/nextflow/ — a runnable entry point (--mode consensus | ctdna | airr) and a
    downstream layer (align, call variants, arda). The align module exits non-zero if MI:Z: does
    not reach the BAM, because that failure is otherwise silent.
  • scripts/sra_fetch.py — fetch benchmark runs on demand instead of mirroring them. NCBI S3 is
    33x faster than ENA here (6.7 MB/s on 8 connections against 200 kB/s), and some runs list their
    original submitted file ahead of the .sra, so fasterq-dump gets handed a gzipped FASTQ
    unless you select on the file type.
  • notebooks/exome_capture.py, airr_repertoire.py and a README. The PEP 723 headers
    were under-declared: altair renders a polars frame through pyarrow and then pandas, so a clean
    machine failed three imports deep with an error naming neither.

Corrected

"Sequencing deeper buys reads, not molecules" was wrong, and the data says so. The same 20 ng
library gives 6,310 / 10,299 / 16,809 molecules per amplicon at 3.3 / 10 / 30x — depth buys
molecules up to the input ceiling, past which it only raises reads per molecule.

Verified

bash setup.sh from a clean venv, ruff, 217 pytest, ctest and sphinx-build -W all clean; the
SLURM templates were run end to end. Nextflow was not run — it is not installed on the machine
this was written on — so those modules are reviewed against the nf-core module spec rather than
verified by a pipeline run.

Install: pip install migec or uv pip install migec. Wheels for CPython 3.10–3.13 on Linux
x86-64 and macOS arm64.