Version 0.9.14
CNVkit now has a purity subcommand for estimating tumor purity and ploidy directly. This new command's output is compatible with the existing call command where purity and ploidy are used for absolute copy number determination. You can also continue to use purity and ploidy values from other tools like PureCN, or histopathology visual estimates. Thanks again to Wei Gu Lab at Stanford for support and helpful discussions.
The non-default segmentation methods by hidden Markov model (segment -m hmm, hmm-tumor, hmm-germline) and Haar wavelet (-m haar) are both greatly improved. Simple benchmarking on the test files in this repo now shows roughly 90% concordance between the three segmentation methods.
The HMM methods are now implemented in pure Python with NumPy/SciPy, eliminating the heavy dependencies pomegranate and pytorch. The installation size and Docker image are consequently smaller, too. The somatic methods (hmm, hmm-tumor) now simultaneously estimate purity and ploidy by grid search over the marginal likelihood on autosomal arms. The emission model for variant b-allele frequency was also upgraded from a Gaussian approximation to a beta-binomial on raw allele counts, improving accuracy when jointly segmenting on coverage (BAM/CRAM) and a given VCF.
The Haar method was further optimized for performance, and two crucial bugs were fixed that previously resulted in over-segmentation. This very fast segmentation method is now recommended for WGS.
This release also includes substantial overhauls of sex-chromosome inference and RNA-based copy number estimation, and a large body of numerical-robustness, packaging, data, and testing improvements.
New features
purity (new command):
- New
cnvkit.py puritysubcommand estimates tumor purity and ploidy from a
.cnr/.cnspair, using the same grid-search likelihood model as the somatic
HMM methods. Purity and ploidy inputs are validated via argparse type
validators.
segment:
- HMM segmentation rewritten in pure NumPy/SciPy, including Baum-Welch/Viterbi machinery
and the emission distributions;pomegranateandtorchare no longer required. BAF
emission is now a beta-binomial on allele counts.
(#1003) - New fast Haar-based breakpoint detector unions depth and BAF breakpoints to
recover copy-neutral LOH. - BIC-based segment-merging filter for adjacent segments.
- Warn when the input has no
sample_id.
batch:
- Allow a sample to serve as its own reference, and reuse shared coverage across
samples to avoid redundant computation. (#48) - Accept
--sample-sexand propagate sex arguments through tocall. (#500,
#635) - Expose the
--bias-smootheroption. (#1028) - Use
autobinto choose target and antitarget bin sizes in hybrid mode. (#302) - Allow
--fastatogether with--referencefor CRAM support. (#869)
fix:
- Add an
-r/--referenceflag and clearer error messages when the reference
is missing or malformed. (#894) - Make the antitarget coverage optional, enabling
fixfor WGS samples without
an antitarget file. (#894) - Add an opt-in LOESS bias smoother as an alternative to the rolling median.
(#1028)
scatter:
- Surface LOH and somatic SNV evidence as colored overlays. (#290)
- Label only the genes requested with
-g, not co-binned neighbors. (#458) - Floor the genome-wide y-axis so deep deletions no longer distort the plot.
(#385) - Genome-agnostic chromosome handling; warn on empty chromosome selections.
diagram:
- Add a
--genefilter, directional thresholds, and graceful handling of
reversed intervals. (#248)
export vcf:
- Emit allele-specific copy number and BAF to represent LOH evidence. (#892)
call / export / import-theta:
- Accept non-integer ploidy as input. (#953)
import-rna:
- Add
--normalize-method size-factors(DESeq2-style median-of-ratios with
leave-one-out). - Add
--min-sample-fractionfor sparse/single-cell cohorts. (#448) - New
cnv_gene_info.pyscript builds gene-info tables for any genome; load
every gene from the bundled hg38 table. - Wire
--diploid-parx-genomethrough and make it effective.
coverage:
- Route bedGraph chromosome-name matching through the shared prefix detector.
- Explicitly exclude duplicate reads in the
bedcovcoverage path. (#689)
reference:
- Replace k-means/MCL clustering with k-medoids (PAM) on correlation distance;
add hierarchical clustering for batch-effect detection.
coverage / long chromosomes:
- Auto-select CSI indexing for genomes with long chromosomes. (#817)
Bug fixes
Segmentation and numerical robustness:
- Fix numerous NaN-propagation bugs across segmentation, weighting, and metrics.
(#436, #900, #908, #1036, #1043) - Fix
segmentcrash on NaNlog2bins via the in-memory path. (#881) - Fix CBS segmentation crash on bins with missing chromosome/start. (#868)
- Handle empty
.cnrinput and inputs where fewer than two bins survive
coverage filters, instead of silently producing no.cnr. (#891) - Defend the Savitzky-Golay path against non-finite
log2andlstsq
LinAlgError. (#508) - Fix the Haar segmenter's FDR calculation and make its weights NaN-safe.
Variants and VCF:
- Fix variant re-segmentation crash / mis-slice on unsorted VCF. (#893, #1004)
- Harden the VCF reader against missing
GT,./.no-calls, and unparseable
headers; do not count no-call.as a distinct allele. - Clamp purity-rescaled BAF to
[0, 1]. (#601)
Intervals and chromosome names:
- Fix start > end segments produced by squashing unsorted
.cns. (#677) - Harden
coverageandautobinagainst chromosome-name mismatches. - Fix cross-chromosome antitarget subtraction. (#471)
- Normalize singleton NaN gene/accession names to
-in merge/flatten/squash.
Other:
- Fix multiple bugs in
guess_baits.py. (#542) - Run serially when only one CPU is usable. (#1103)
- Surface R subprocess stderr in
call_quieterrors.
Compatibility
- Python 3.10 support removed; 3.11 is now the baseline. Python 3.14 is
tested in CI. - Codebase modernized to the 3.11 baseline: PEP 604 unions, PEP 634 match/case,
PEP 618zip(strict=True),removeprefix/removesuffix, anddict |=. bioframeadopted for genomic interval arithmetic, replacing bespoke
implementations. (#226, #227, #982)pysamis now a soft import, so CNVkit can run in place from source without it
installed. (#924)- Minimum
biopythonraised to 1.87 to address CVE-2025-68463. - Minimum dependency versions raised to align with Ubuntu 26.04 LTS (Resolute).
- New
skgenome.chromnamesandskgenome.genomebuildmodules add genome-aware
chromosome handling, including Roman-numeral chromosomes; sex-chromosome
detection is now genome-aware.
Sex-chromosome inference
- Resolve sex calls by a representation-invariant ratio-of-residuals statistic
combined with an AND-gate across chrX and chrY evidence, replacing the prior
approach. (#785, #954) - Add a VCF chrX SNP-heterozygosity confirmer (binomial test) to sex inference.
(#341) - Show male chrX gains rather than muting them; reconcile target/antitarget sex
by chrX confidence. (#846, #883) - Default to female when chromosomal sex is indeterminate; stop the alarmist
warning on assemblies without sex chromosomes and report "Unknown" instead.
(#360, #669)
Packaging and infrastructure
- HMM rewrite removes the
pomegranate/torchdependency chain (see above),
greatly reducing install and image size. - Full mypy type-checking adopted: 387 errors reduced to 0 across the codebase,
and mypy added to CI (targeted at Python 3.12 for NumPy 2.5 stubs). - Linting moved to ruff 0.15 with formatting; migrated security scanning from
safetytopip-audit. - Added Hypothesis property-based tests and
pytest-xdistparallel execution;
reorganized the test suite (split the monolithic command tests into focused
classes; marked slow tests). (#1038, #1042) - Docker: split a user-facing "Running CNVkit with Docker" doc from the developer
guide; tag thelatestimage on release tags rather than on master pushes;
parameterized the CNVkit version in the Dockerfile. - Removed obsolete in-repo Galaxy and WDL wrappers; Galaxy users are pointed to
the IUC tool suite. - Removed the defunct fused-lasso (cghFLasso) segmentation method.
- Added
FUNDING.yml,CONTRIBUTING.md, and a development section in the README. - CI: bumped GitHub Actions to Node 24 runtimes; trimmed the test matrix.
New contributor
- @haoyu-haoyu made their first contribution in #1046.
Full Changelog: v0.9.13...v0.9.14