Sniffles2: calling structural variants from long-read alignments
Structural variation caller using third generation sequencing
At a glance
- What is it?
- Sniffles2 is a structural variant caller for long-read sequencing data, from PacBio and Oxford Nanopore, that runs in a single command over a BAM alignment and writes a VCF. It has four modes covering germline, multi-sample population, mosaic and force-calling workflows, and it pins an unusually exact Python version.
- Who is it for?
- Adopt Sniffles2 if you are working with long-read data and want a caller that handles the full read span rather than a read-pair heuristic, and if you can provide the exact Python version and pinned dependencies it expects. Do not adopt it for short-read data, for a cohort where per-sample candidate calling followed by a joint genotype step is not acceptable, or for a pipeline that has to run unattended across differing Python versions.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the caller takes in and what it gives back
Sniffles2 is described as a fast structural variant caller for long-read sequencing, and it accurately detects SVs on germline, somatic and population-level for PacBio and Oxford Nanopore read data.
The basic invocation is one command over an alignment:
`sniffles -i mapped_input.bam -v output.vcf`
The input is a .bam or .cram file containing long read alignments, and the documentation is specific that these come from minimap2 or ngmlr. The output is a .vcf.gz that is bgzipped and tabix indexed, and you can also write both a .vcf and a .snf file at the same time for the multi-sample workflow.
So the tool does not align reads. It consumes an alignment, and it is worth being clear about that because the naming of the project in the repository description, a structural variation caller using third generation sequencing, can read as if it takes raw reads.
The reference genome is a separate concern. To output deletion sequences, the reference genome in .fasta form must be specified, for example with --reference reference.fasta. If you only want breakpoints and do not need the deleted sequence spelled out, the reference is not needed, and the documentation presents it as a requirement only for that one output.
Two other general settings apply to every mode. Sniffles2 is fully parallelised and uses 4 threads by default, which can be adapted with --threads, and the documentation is explicit that memory requirements increase with the number of threads used. And to output read names in the SNF and VCF files, the --output-rnames option is required.
Four modes, and the population workflow is two passes
The mode list in the README is short, and one of them is a workflow rather than a flag.
For mosaic calling, that is non-germline or somatic SVs, the --mosaic option is added to an otherwise normal run:
`sniffles --input mapped_input.bam --vcf output.vcf --mosaic`
For genotyping a known set of SVs, the force calling mode takes a VCF of known variants and re-genotypes them against a sample:
`sniffles --input sample.bam --genotype-vcf input_known_svs.vcf --vcf output_genotypes.vcf`
That is the mode to reach for when you have a candidate list from another caller or from a panel and want genotypes rather than fresh discovery, and it produces the re-genotyped SVs in the output VCF.
Multi-sample calling for trios and populations works in two steps, and this is the part with a real design consequence. First you call SV candidates per sample and create an associated .snf file for each:
`sniffles --input sample1.bam --snf sample1.snf`
Then you combine those .snf files into a single VCF:
`sniffles --input sample1.snf sample2.snf ... sampleN.snf --vcf multisample.vcf`
Alternatively, for that second step you can supply a .tsv file containing a list of .snf files, with custom sample ids in an optional second column, one sample per line:
`sniffles --input snf_files_list.tsv --vcf multisample.vcf`
The .snf file is therefore a real intermediate format and not just a log. The two-step design is the right one for a cohort: candidates are called once per sample against that sample's own coverage, and the joint pass then genotypes across samples, which is what makes a population mode different from running a single caller on a merged file. It also means the per-sample work has to be scheduled, since a hundred samples is a hundred first passes.
Installing it, and the Python version you have to match
Installation is with pip or conda. The pip form is:
`pip install sniffles`
and the conda form pins a version explicitly:
`conda install sniffles=2.8.1`
The README also covers the upgrade path for anyone who installed Sniffles1 through conda, with conda update sniffles=2.8.1.
The dependency list is where the sharp edges are. The requirements are Python ==3.10.15, pysam >=0.21.0, edlib >=1.3.9, psutil>=5.9.4, numpy>=2.2.0 and pyspoa>=0.2.1. The tested configuration is narrower still: python==3.10.12 and pysam==0.21.0.
An exact Python pin, down to a patch release, is unusual for a bioinformatics tool, and it is a consequence of a pinned environment rather than a technical necessity of the algorithm. The practical effect is on your infrastructure: a container image that satisfies it, a conda environment that resolves to it, and a rule about what happens when your cluster image gets bumped. The package metadata reflects the same shape, with a plain setuptools build and the version, licence and author recorded directly:
setup(
name='sniffles',
version='2.8.1',
packages=find_packages(),
url='https://github.com/fritzsedlazeck/Sniffles',
license='MIT',
author='Moritz Smolka, Hermann Romanek',
author_email='[email protected], [email protected]',
description='A fast structural variation caller for long-read sequencing data',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
)Note that the build system itself is minimal, requiring setuptools>=42 and wheel through the pyproject.toml, and there is no compiled extension in that metadata, so the heavy lifting is in the Python and its native dependencies rather than in a build step of the tool's own.
The companion tools live in separate repositories
Sniffles2 does not ship its plotting or its supplementary material inside this repository, and the README points out where they are.
There is a plotting tool developed for Sniffles2 at the farhangus/sniffle2_plot repository. There is also a repository with the VCF and scripts used for the manuscript, at smolkmo/Sniffles2-Supplement, and the supplementary tables are published there as a spreadsheet.
That arrangement is worth understanding for a practical reason. A variant caller is only half of an analysis, and the other half, the figures and the per-paper VCF artefacts, lives in a different place with a different maintenance history. If you are reproducing a published result, the scripts in the supplement repository are the part that makes the reproduction possible, and they are versioned separately from the caller.
The citation instructions follow the same pattern. The README asks you to cite the Sniffles v2 paper and the Sniffles v1 paper, both in Nature journals, and gives the links. Citing both is correct: v1 for the original method and v2 for the version you are actually running, since the second paper describes a different set of capabilities.
The top level of the repository is small and consistent with a tool rather than a platform: a .github directory, a .gitignore, a LICENSE, the README, an annotations/ directory, pyproject.toml, setup.cfg, setup.py and a src/ directory. The annotations directory is where the caller keeps its reference annotation resources.
Where Sniffles2 is the wrong choice
The first limitation is the platform. The tool is for long-read data, and the documentation says so in the first line. A short-read cohort has different coverage characteristics, different breakpoint resolution and different error profiles, and a long-read caller applied to it will produce something that looks like an SV call set and is not one. There is no configuration flag that makes it a short-read caller.
The second limitation is the environment. Python is pinned to 3.10.15, with 3.10.12 recorded as the tested version, and numpy is pinned exactly while pysam carries a minimum version requirement. A site that standardises on a newer Python, or that has a shared conda environment, will have to build a dedicated environment for this tool, and the upstream environment will eventually need rebuilding when the pins move. The 2.x line has been moving: v2.7.5 from 2026-04-02, v2.8.0 from 2026-05-07 and v2.8.1 from 2026-09-10, with the last push to the repository on 2026-10-18. The pace is steady but the pins are exact, so an upgrade is not a version bump, it is a new environment.
The third limitation is that the reference and thread settings have to be right, and the documentation gives you the flags but not the judgement. The reference genome is needed for deletion sequences, the thread count defaults to 4 and memory grows with it, and read names only appear with an explicit option. None of that is hard, but each is a decision that has to be made deliberately rather than inherited from a default.
The real alternative, and the one most structural variant workflows actually use, is to assemble a call set from more than one caller and reconcile them. A short-read caller plus a long-read caller plus an assembly-based caller produce overlapping but different call sets, and taking the union or intersecting them is the standard way to control sensitivity against false positives. The difference in approach is that Sniffles2 is one opinionated caller with a well-documented model of what a structural variant is on a long read, and a multi-caller pipeline is a set of opinions with a reconciliation step you have to build and validate yourself. For a research project that needs sensitivity against a truth set, the multi-caller route is the safer one, because it does not depend on one caller's model being right. For a routine pipeline on a well-characterised cohort, Sniffles2 alone is faster to run and easier to reason about, and the.snf plus --genotype-vcf route gives you a way to re-genotype a fixed candidate set without redoing discovery.
Editorial conclusion
Adopt Sniffles2 if you are working with long-read data and want a caller that handles the full read span rather than a read-pair heuristic, and if you can provide the exact Python version and pinned dependencies it expects. Do not adopt it for short-read data, for a cohort where per-sample candidate calling followed by a joint genotype step is not acceptable, or for a pipeline that has to run unattended across differing Python versions. Before you commit, confirm your aligner output is a sorted and indexed BAM or CRAM, check the reference genome requirement for deletion sequence output, and decide on the thread count, since the memory footprint grows with it.
Frequently asked questions
What is Sniffles2?
Sniffles2 is a fast structural variant caller for long-read sequencing, detecting SVs at germline, somatic and population level from PacBio and Oxford Nanopore read data. It consumes a long-read alignment in BAM or CRAM form and writes VCF output, and it is maintained by Moritz Smolka and Hermann Romanek.
How do I install Sniffles2?
With pip using pip install sniffles, or with conda using conda install sniffles=2.8.1. The requirements list pins Python to 3.10.15 and includes pysam 0.21.0 or newer, edlib, psutil, numpy and pyspoa, and the tested configuration is python 3.10.12 with pysam 0.21.0.
How does multi-sample calling work in Sniffles2?
It is a two-step process. First you call candidates per sample and write an .snf file with sniffles --input sample1.bam --snf sample1.snf, then you combine the .snf files into one VCF with sniffles --input sample1.snf sample2.snf --vcf multisample.vcf. A .tsv listing the .snf files with optional custom sample ids can be used for the second step.
Do I need a reference genome to run Sniffles2?
Only to output deletion sequences, in which case the reference in .fasta form must be specified with an option such as --reference reference.fasta. The input alignment itself is a .bam or .cram file from minimap2 or ngmlr, and the VCF output is bgzipped and tabix indexed.
Can Sniffles2 re-genotype a known set of structural variants?
Yes. The force calling mode takes a VCF of known variants with --genotype-vcf and writes the re-genotyped results to a VCF, so sniffles --input sample.bam --genotype-vcf input_known_svs.vcf --vcf output_genotypes.vcf determines the genotype of each variant in the input against the sample.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/fritzsedlazeck-sniffles)Was this useful?