Skip to content
Fu-YileiPublic

About

Using DNA methylation to resolve cell-specific variant assignments in bulk only long-read sequencing data

Resources

Stars

9 stars

Watchers

2 watching

Forks

Repository files navigation

SniffCell

PyPI version Python License: MIT Issues

SniffCell links somatic structural variants (SVs) and tandem-repeat (TR) expansions/contractions to the cell type they occurred in, using long-read DNA methylation. It calls cell-type-specific differentially methylated regions (ctDMRs) from a reference methylation atlas, discovers SVs and TRs directly from long-read BAMs, extracts read-level methylation, and assigns each variant's supporting reads to the cell population whose methylation profile they match.

Which Package Should I Use?

Use sniffcell when you are discovering variants from a BAM (no existing callset yet):

  • ctDMR discovery from an atlas (find)
  • cell-type deconvolution and BAM splitting (deconv)
  • cell-type-aware SV, tandem-repeat, and SNV discovery (discover)
  • methylation-based annotation of the discovered variants (anno, svanno)
  • visualization, IGV screenshots, differential methylation tests, and HTML reports

Use sniffcell-lite when you already have a variant callset with each variant's supporting reads identified (e.g. from Sniffles/kanpig or another caller) and just want fast ctDMR-based cell-type annotation, without running the full deconvolution/discovery pipeline:

  • sniffcell-lite find
  • sniffcell-lite anno

sniffcell-lite is published as a separate PyPI package and does not replace the full sniffcell package:

pip install sniffcell-lite
sniffcell-lite --help

The lite package is maintained in the separate Fu-Yilei/SniffCell-lite repository.

Install SniffCell

pip install sniffcell

For the full external-tool environment:

micromamba env create -f environment.yml
micromamba activate sniffcell
pip install sniffcell

Methylation Atlases

Download the processed methylation atlas inputs and precomputed cell-type-specific differentially methylated regions (ctDMRs) from Zenodo. For the find example below, place all_celltypes_blocks.npy, all_celltypes_blocks.index.gz, index_to_major_celltypes.json, and all_celltypes.txt in the atlas/ directory. Precomputed ctDMR tables are available for brain/cerebellum, PBMC, lung, liver, pancreas, kidney, breast, and colon, and can be supplied directly to deconv or anno with -b instead of running find.

To discuss tissue-specific atlases, additional tissues or cell types, or custom atlas support, please open a GitHub issue or Email us.

Example Workflows

SniffCell: discover and annotate SVs/TRs from a BAM

  1. Call ctDMRs from an atlas:
sniffcell find \
  -n atlas/all_celltypes_blocks.npy \
  -i atlas/all_celltypes_blocks.index.gz \
  -cf atlas/index_to_major_celltypes.json \
  -m atlas/all_celltypes.txt \
  -ck pbmc \
  -o pbmc_ctdmr.tsv
  1. Split the BAM into cell-type groups using those ctDMRs:
sniffcell deconv \
  -i sample.bam \
  -r ref.fa \
  -b pbmc_ctdmr.tsv \
  -o deconv_out \
  --split_bam_groups "Lymphoid=T-cell,NK-cell,B-cell;Myeloid=Monocyte" \
  -t 8
  1. Discover SVs and tandem repeats from the two cell-type-split BAMs:
sniffcell discover tools run \
  --deconv-dir deconv_out \
  --reference ref.fa \
  --tr-bed tr_catalog.bed \
  --sex female \
  --run-id run1 \
  --threads 8

This runs Sniffles/Kanpig/Truvari (SVs), TRGT or Medaka (tandem repeats), and optionally Clair3 (SNVs) on the two split BAMs, then harmonizes everything into deconv_out/deconv_requested_group_splits/discover/run1/harmonized_variants.tsv. Tool binaries are resolved from PATH by default, or pass explicit --sniffles-bin/--trgt-bin/etc. flags; run sniffcell discover tools check to preflight-check dependencies first.

  1. Annotate the discovered SVs/TRs with cell-type methylation evidence:
sniffcell anno \
  -i sample.bam \
  -v deconv_out/deconv_requested_group_splits/discover/run1/harmonized_variants.tsv \
  -r ref.fa \
  -b pbmc_ctdmr.tsv \
  -o anno_out \
  -t 8
  1. Build an HTML review report:
sniffcell report --anno_output anno_out

Open anno_out/report/index.html to review high-confidence calls and figures.

SniffCell Lite: annotate an existing callset

If you already have a variant and know its supporting read names, skip deconvolution and discovery entirely:

sniffcell-lite find -ck "Colon, Ascending" -o colon_ascending.ctdmr.tsv

sniffcell-lite anno \
  -i sample.bam \
  -r ref.fa \
  --variant-name variant_001 \
  --variant-location chr1:100000-101000 \
  --supporting-reads readA,readB,readC \
  --catalog colon_ascending.ctdmr.tsv \
  -o anno_out

sniffcell-lite anno also supports a --batch variants.tsv mode for annotating many variants at once. See the SniffCell Lite README for details.

Main Commands

Command Purpose
sniffcell find Call ctDMRs from a methylation atlas
sniffcell anno Extract BAM methylation and assign SVs/TRs to cell types
sniffcell svanno Re-score SVs from a saved read-classification table
sniffcell deconv Classify all reads and optionally split BAMs by group
sniffcell discover Run cell-type-aware SV / TR / SNV discovery
sniffcell viz Render per-SV methylation figures
sniffcell igvviz Generate IGV batch screenshots
sniffcell report Filter calls and build an HTML review report
sniffcell dmsv Test methylation differences around SVs

Inputs

Input Format Used by
Long-read alignment BAM with MM / ML modification tags anno, deconv, discover, dmsv, viz
Variants VCF / VCF.GZ, harmonized TSV from discover, or a variant + supporting-read names (sniffcell-lite) anno, dmsv, viz, report
Reference genome FASTA plus index anno, deconv, discover, dmsv, viz
ctDMR table TSV from sniffcell find anno, deconv, viz
Methylation atlas NumPy matrix, CpG index, and metadata find

Outputs

A find -> deconv -> discover -> anno -> report run produces:

pbmc_ctdmr.tsv
deconv_out/
  deconv_summary.tsv
  deconv_reads_classification.tsv
  deconv_requested_group_splits/
    <group>.bam
    discover/run1/
      harmonized_variants.tsv
      run_summary.json
anno_out/
  reads_classification.tsv
  blocks_classification.tsv
  sv_assignment.tsv
  sv_assignment_readable.tsv
  sv_assignment_readable_long.tsv
  anno_run_manifest.json
  report/
    index.html
    high_confidence_sv.tsv
    figures/

A sniffcell-lite find -> anno run produces:

colon_ascending.ctdmr.tsv
colon_ascending.ctdmr.tsv.igv.bed
anno_out/
  variant_assignment.tsv
  variant_assignment_readable.tsv
  reads_classification.tsv
  anno_compact_manifest.json

Discovery VCF exports

sniffcell discover tools run automatically exports matching caller records beside harmonized_variants.tsv, when the corresponding source VCFs exist:

harmonized_variants.sv.vcf.gz
harmonized_variants.tr.<group>.vcf.gz
harmonized_variants.snv.<group>.vcf.gz

Each VCF is coordinate-sorted, BGZF-compressed, and tabix-indexed. SV records come from the joint Sniffles/Truvari/Kanpig postprocessing VCF; TR records come from each group's TRGT VCF; SNV records come from each group's Clair3 pileup VCF used for comparison. Original caller alleles, genotypes, quality, and filters are retained. These are subsets, not copies of the full callsets.

Additional INFO fields describe the SniffCell evidence:

INFO field Meaning
SC_ID, SC_ROW Harmonized variant ID and one-based data-row number
SC_CLASS, SC_SUBTYPE Variant class and change subtype
SC_CATEGORY group_a_only, group_b_only, shared, or unknown
SC_GROUP_A, SC_GROUP_B Actual comparison-group labels
SC_TARGET_GROUP Group carrying the candidate change; absent for shared/unknown calls
SC_SUPPORT_A, SC_SUPPORT_B Support counts from the harmonized TSV
SC_CHANGE_BP SniffCell change size; for TRs, a between-group difference

String values are percent-encoded so composite cell-type labels remain intact. These annotations identify split-BAM group-specific candidates, not methylation-confirmed assignments from anno. Zero support does not establish reference genotype or coverage. For TRs, annotations describe a locus-level change, not necessarily a particular TRGT ALT allele; SC_CHANGE_BP is not reference-relative SVLEN. Multiple harmonized changes at one locus yield separate annotated copies, distinguished by SC_ROW.

Missing source records are not reconstructed. Export paths, counts, and unmatched data-row numbers are recorded in harmonized_variants_manifest.json, with warnings for missing matches. Medaka-only TR runs currently have no TRGT VCF export. An opposite-group SNV record may be absent even when the target group has a matching call. These VCFs preserve caller genotypes rather than inferring somatic genotypes; they are not somatic truth sets.

Documentation

For command-line options, run sniffcell --help or sniffcell <command> --help (for example, sniffcell anno --help).

Citation

If you use SniffCell in your research, please cite:

Cell-type-resolved somatic variant discovery from bulk long-read sequencing Yilei Fu et al. medRxiv preprint (2026). DOI: 10.64898/2026.09.01.26361966.

License

MIT License. See LICENSE for details.

About

Using DNA methylation to resolve cell-specific variant assignments in bulk only long-read sequencing data

Resources

Stars

9 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages