Fast Rust command-line tools for selected Picard-compatible genomics workflows.
Project description
turbo-picard
Drop-in Picard replacement. Rust speed. Up to 84.46x faster.
If you already run Picard workflows and are evaluating alternatives, the default
operating decision is:
turbo-picard first, then any QC-only replatform (riker) if your stack is already changing command semantics.
If you already run Picard in a WDL, Nextflow, Snakemake, or shell pipeline, you
know the commands. You know the KEY=VALUE arguments. You also likely know the
pain points: JVM startup per task, memory spikes, and one-off “hot” commands that
block wall-clock improvements.
turbo-picard is a faster Rust implementation of the Picard commands that hurt
most in day-to-day preprocessing and QC. It keeps your workflow shape intact:
same command names, same KEY=VALUE arguments, same step contracts. On the
accelerated surface, outputs are checked against Picard 3.4.0. Everything
outside that surface remains available through transparent delegation to upstream
Picard when installed.
For teams asking for the strongest practical alternative to Picard, this is the lowest-friction path: no command rewrites, no argument mapping, and no immediate pipeline rewrite.
Why turbo-picard is the strongest first option
turbo-picardis the only drop-in path that keeps the sameKEY=VALUEcommand model for the full Picard 3.4.0 surface.- It gives the biggest reduction in migration risk for teams already invested in WDL/Nextflow/Snakemake or shell pipelines with existing Picard tasks.
- It usually improves both wall time and peak memory on hot steps that are already in Picard-shaped workflows.
- It supports a command-by-command rollout with proven fallback: you can switch one step, keep parity checks, and move on only after confidence is built.
- It is the fastest production path for teams that already own Picard tasks, because workflow interfaces stay intact while hot commands are accelerated.
- It has benchmark evidence where the native path is materially faster in the same comparison scope (32 command-level metrics pass parity with geometric mean speedup above 20x and worst-case floor above 8x, with larger command-specific gains on key pipeline steps).
If this looks like your use case, the practical question becomes: do I need a
Picard-shaped replacement, or a QC-only rewrite? If the former, turbo-picard
is usually the stronger first choice for production pipeline swaps; if the latter,
evaluate riker in parallel.
If you are explicitly comparing alternatives, this is the default filter:
- choose
turbo-picardwhen execution speed matters and you already use Picard tasks in WDL/Nextflow/Snakemake/shell pipelines and want the lowest-risk rollout path. - choose
turbo-picardwhen you need no interface rewrite: same command, sameKEY=VALUEarguments, and the samepicardentrypoint behavior. - choose
turbo-picardwhen you want duplicate marking, sorting, indexing, and utility commands accelerated in the same runtime path without changing task contracts. - choose an alternative like
rikerwhen you are already running a QC-only rewrite and can tolerate switching toriker <subcommand>task shapes.
If your evaluation includes riker, this project is the first practical
choice for existing production stacks:
- same command surface (
picard COMMAND+KEY=VALUE); - command-by-command rollout with parity checks between checks and switched shards;
- fallback to upstream Picard when a command is not yet implemented natively.
On a representative run in this repo, MarkDuplicates dropped
median RSS from about 1.2 GB in Picard to about 8.7 MB in
turbo-picard. That matters when the same step fans out across many samples or
shards.
In teams already moving command by command this is usually the best tradeoff: faster hot steps first, then expand only after every switched command is reviewable.
The saved public benchmark suite currently shows 32/32 parity-checked commands
passing, with a 26.74x geometric mean speedup and an 84.46x top speedup
versus Picard 3.4.0. Details and the full per-command table are below.
Enjoy trying it on one shard before you change a whole workflow.
Quick start
Install
python3 -m pip install turbo-picard
Installing from PyPI currently gives you both commands:
turbo-picard— use this while you are testing.picard— an optional compatibility shim for scripts that already callpicard.
Use a dedicated virtual environment if you need upstream Picard and the shim side
by side. PyPI currently has a macOS Apple Silicon wheel and a source distribution.
If pip builds from source, you will need Rust and native build dependencies.
For Linux clusters, Bioconda will be the cleaner install path once the recipe is
accepted.
From a repository checkout:
cargo install --locked --path crates/turbo-picard-cli --bin turbo-picard --bin picard
Test that it runs
turbo-picard --version
turbo-picard MarkDuplicates --help
turbo-picard AccelerationStatus
Run one command
Pick a slow step you can compare easily, then run it on a representative file:
turbo-picard MarkDuplicates I=input.bam O=marked.bam M=metrics.txt
The shim accepts the same Picard-style call:
picard MarkDuplicates I=input.bam O=marked.bam M=metrics.txt
CRAM works on the hot preprocessing path when you pass a reference FASTA with
REFERENCE_SEQUENCE (or set TURBO_PICARD_REFERENCE):
export TURBO_PICARD_REFERENCE=/path/to/reference.fa
turbo-picard SortSam I=reads.cram O=sorted.cram SORT_ORDER=coordinate R=$TURBO_PICARD_REFERENCE
Use the explicit turbo-picard command while testing. Add the optional picard
shim only when you deliberately want existing pipeline code to resolve to
turbo-picard.
What stays the same
- Picard command names and
KEY=VALUEarguments. - A practical migration path: swap one step, compare outputs, move on.
- The full Picard 3.4.0 command surface — accelerated commands run natively; everything else delegates to upstream Picard when available.
Good first commands
These are usually the best places to start:
MarkDuplicateswhen duplicate marking is dragging a preprocessing run.SortSamwhen you are repeatedly reordering BAM or CRAM between stages.SamToFastqwhen Picard export is still in an alignment or remap path, including per-read-group FASTQ output.FastqToSamwhen lane-sharded FASTQ ingest still uses Picard before alignment.FixMateInformationwhen mate repair is still in a preprocessing chain.BuildBamIndexand small VCF utilities when pipeline glue work keeps adding up.- Metrics commands when iteration speed matters more than Picard's exact plot rendering.
The right first trial is one slow, easy-to-compare command on one representative shard — not your smallest toy file.
Starter workflows and copy-paste examples live in
packaging/workflows/. If you are not sure where to
begin, start with
choose-your-first-command.md
or the tiny
one-command-trial.md flow.
Migration patterns that usually keep Picard in place: per-read-group SamToFastq,
sequential-shard FastqToSam, and mate-repair boundaries around FixMateInformation.
Trial workflows include
trial.wdl,
trial.nf,
trial-samtofastq.nf,
trial-samtofastq.wdl,
trial-fastqtosam.nf,
trial-fastqtosam.wdl,
trial-fixmateinformation.wdl, and
trial-fixmateinformation.nf.
Using it in a pipeline
WDL / Cromwell:
command <<<
turbo-picard MarkDuplicates \
I=~{input_bam} \
O=~{sample_id}.marked.bam \
M=~{sample_id}.metrics.txt \
ASSUME_SORTED=true
>>>
Nextflow:
def picard = params.use_turbo_picard ? 'turbo-picard' : 'picard'
"""
${picard} SortSam I=${bam} O=${meta.id}.sorted.bam SORT_ORDER=coordinate
"""
Snakemake:
shell:
"turbo-picard BuildBamIndex I={input.bam} O={output.bai}"
More workflow notes: packaging/nf-core/README.md,
packaging/workflows/wdl-cromwell.md,
packaging/workflows/nextflow-nf-core.md,
packaging/workflows/snakemake.md.
When It Helps
The best first use is one expensive Picard step that you can compare easily:
sorting, duplicate marking, FASTQ conversion, indexing, VCF housekeeping, or a
metrics command that keeps slowing down iteration. Run Picard and turbo-picard
beside each other on a representative file, compare the outputs that matter for
that command, then switch only that checked step.
When To Stay With Picard
Use upstream Picard directly when you want every step to run on the JVM without delegation, when workflows depend on exact Picard-rendered chart PDFs, or for any accelerated step you have not compared on data that looks like your own. Delegation keeps every Picard 3.4.0 command available; it is not a reason to skip validation on the accelerated path.
Documentation
The full docs are on Read the Docs:
https://turbo-picard.readthedocs.io/en/latest/
Good starting points:
- Is this for you?
- Choose your first command
- Evaluation playbook
- Quickstart
- Command coverage
- Picard vs turbo-picard
- turbo-picard vs riker
- FAQ
- What parity means — the parity guide for what comparisons prove and what they do not.
- Trying it in a pipeline
- Benchmarks
- Citation
The docs source is in docs/.
Fallback to Picard
Unsupported commands fail by default. To let them run through upstream Picard:
export TURBO_PICARD_FALLBACK_COMMAND='java -jar /opt/picard/picard.jar'
Use an absolute path so the fallback cannot accidentally resolve back to the
picard shim. See the
fallback documentation.
Container image
docker build -t turbo-picard:local .
docker run --rm turbo-picard:local MarkDuplicates --help
Check your own data
Before switching a pipeline step, run Picard and turbo-picard on a
representative file and keep the comparison with the analysis:
python3 tools/audit_real_data.py \
--input-bam /data/representative.bam \
--input-source-url https://example.org/accession.bam \
--input-source-commit <40-char-sha-or-accession> \
--output-dir benchmarks/real-data/my-workflow/evidence \
--dataset-id my-workflow \
--picard-command "picard" \
--turbo-picard-command ./target/release/picard \
--skip-build
Record pinned input SHA-256 hashes, source URLs, and commits with your evidence. See Trying it in a pipeline for the full validation protocol.
Benchmarks
Three-way QC comparisons against riker:
python3 tools/bench_qc_vs_riker.py --smoke --skip-build --allow-missing-riker
The smoke helper now defaults to median-of-5 repeats so tiny fixture startup noise does not swamp the overlap timings.
Evidence lives in benchmarks/riker-comparison/.
The benchmark suite compares each command with Picard and checks stable output
before reporting speed. Saved on 2026-06-04 from
python3 tools/bench_suite.py --repeats 1 --skip-build.
Raw log: docs/site/assets/bench-suite-output.txt.
Summary:
32/32benchmarked commands passed parity checks.84.46xtop speedup:UpdateVcfSequenceDictionary.8.55xfloor speedup:RevertSam.26.82xmedian speedup.26.74xgeometric mean speedup.
Benchmark note: AccelerationStatus is listed under benchmark exceptions
because it is a status/preflight command with no Picard data-processing runtime
to benchmark. Every native or partly native data-processing command in
docs/command-matrix.yml has a saved public speedup claim. Chart-producing
metrics commands compare metrics text. Their lightweight PDF sidecars are there
so Picard-style outputs still exist, not because the plots are claimed to be
pixel-identical to Picard.
| Command | Speedup | Parity |
|---|---|---|
| UpdateVcfSequenceDictionary | 84.46x | PASS |
| NormalizeFasta | 68.69x | PASS |
| GatherVcfs | 63.77x | PASS |
| MergeVcfs | 56.99x | PASS |
| CreateSequenceDictionary | 50.86x | PASS |
| CollectGcBiasMetrics | 50.25x | PASS |
| SortSam | 47.40x | PASS |
| CollectInsertSizeMetrics | 46.41x | PASS |
| BuildBamIndex | 45.49x | PASS |
| CollectAlignmentSummaryMetrics | 37.50x | PASS |
| IntervalListTools | 33.01x | PASS |
| SamToFastq | 30.44x | PASS |
| ViewSam | 28.64x | PASS |
| BedToIntervalList | 27.91x | PASS |
| SortVcf | 27.87x | PASS |
| CleanSam | 26.82x | PASS |
| AddOrReplaceReadGroups | 26.17x | PASS |
| FastqToSam | 24.80x | PASS |
| CollectQualityYieldMetrics | 24.06x | PASS |
| MarkDuplicates | 23.19x | PASS |
| CollectWgsMetrics | 22.42x | PASS |
| MeanQualityByCycle | 21.66x | PASS |
| CollectMultipleMetrics | 20.48x | PASS |
| ValidateSamFile | 19.38x | PASS |
| LiftoverVcf | 15.13x | PASS |
| FixMateInformation | 14.54x | PASS |
| MergeSamFiles | 14.31x | PASS |
| ReplaceSamHeader | 14.07x | PASS |
| CollectBaseDistributionByCycle | 12.46x | PASS |
| QualityScoreDistribution | 11.40x | PASS |
| SetNmMdAndUqTags | 10.19x | PASS |
| RevertSam | 8.55x | PASS |
CRAM preprocessing parity checks:
./tools/verify_basic_cram_parity.sh
./tools/verify_markdup_cram_parity.sh
./tools/verify_gatk_preprocessing_combo_parity.sh
./tools/verify_gatk_mito_bam_parity.sh
./tools/verify_gatk_mito_cram_parity.sh
./tools/verify_gatk_preprocessing_combo_cram_parity.sh
Evidence verifiers:
python3 tools/verify_benchmark_log_evidence.py
python3 tools/verify_benchmark_suite_coverage.py
python3 tools/verify_benchmark_thresholds.py
python3 tools/verify_readme_benchmark_evidence.py
python3 tools/verify_site_benchmark_evidence.py
Real data
Synthetic benchmarks are not enough. The repository keeps pinned public
comparisons with source URLs, commits, SHA-256 input hashes, versions, outputs,
and digest comparisons in benchmarks/real-data/.
Current checked datasets:
gatk-na12878-mito: a public GATK NA12878 mitochondrial BAM.gatk-na12878-mito-cram: the same shard as CRAM with assembly38 mt-only reference.picard-snvq: Picard's public SNVQ metrics test BAM.
To add another pinned dataset:
python3 tools/update_real_data_manifest.py \
--entry benchmarks/real-data/<dataset-id>/evidence/manifest-entry.json
Then run:
python3 tools/verify_real_data_evidence.py
python3 tools/verify_real_data_evidence.py --release-ready
Citation
Cite the archived turbo-picard release with CITATION.cff.
Cite benchmark and validation inputs separately, using their source URLs,
commits or accessions, and SHA-256 hashes. The
citation docs
spell out what to record.
Use the Zenodo DOI for the archived release you actually used. GitHub and Zenodo update that metadata after a release is cut.
A short JOSS-style software paper draft is in paper/. Check it with:
python3 tools/verify_joss_paper.py
The submission checklist is in docs/joss-submission.md.
Bioconda status
Release v0.1.2 has been submitted to Bioconda as two recipes:
turbo-picard— installsturbo-picard.turbo-picard-picard-shim— installs the optionalpicardcommand name.
Release checks:
python3 tools/bioconda_release_preflight.py
python3 tools/prepare_bioconda_release.py \
--archive ~/Downloads/turbo-picard-0.1.2.tar.gz
python3 tools/verify_bioconda_recipes.py --release-ready
Contributing
Bug reports, parity evidence, documentation fixes, and small command-coverage
improvements are welcome. Start with CONTRIBUTING.md.
Before adding or widening a native command, check
docs/command-matrix.yml. Changes should include
tests, a command-coverage update, and documentation that says plainly what is
supported.
Development workflow:
development docs.
Support: SUPPORT.md. Security: SECURITY.md.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file turbo_picard-0.1.2.tar.gz.
File metadata
- Download URL: turbo_picard-0.1.2.tar.gz
- Upload date:
- Size: 192.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
29ea1abf69dae574f9fc6575793fb41b1eafe5f3002721edda9c0e643f5663f8
|
|
| MD5 |
03a87e64d14f991a3f30835e9c269b6a
|
|
| BLAKE2b-256 |
38cd3486dfe4de3300714ac454bf5297b649cd00a75b0ba0efa856302ceabeb9
|
Provenance
The following attestation bundles were made for turbo_picard-0.1.2.tar.gz:
Publisher:
publish-pypi.yml on dnncha/turbo-picard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
turbo_picard-0.1.2.tar.gz -
Subject digest:
29ea1abf69dae574f9fc6575793fb41b1eafe5f3002721edda9c0e643f5663f8 - Sigstore transparency entry: 1789351766
- Sigstore integration time:
-
Permalink:
dnncha/turbo-picard@161e386f6bdc5daf267e96f4040a3f1124c827ac -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/dnncha
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@161e386f6bdc5daf267e96f4040a3f1124c827ac -
Trigger Event:
release
-
Statement type:
File details
Details for the file turbo_picard-0.1.2-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: turbo_picard-0.1.2-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 7.8 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06a196dddb3a5e62a2a3b9dda64284afc8afcbfdd68a9ea837a604a8cd96940a
|
|
| MD5 |
a755196d10a7b0f954eaa45c69acbec1
|
|
| BLAKE2b-256 |
523aa88ec24ea06bb787c2e21d88b191ab958c2717deac6803c39ef94d1b4d3c
|
Provenance
The following attestation bundles were made for turbo_picard-0.1.2-py3-none-macosx_11_0_arm64.whl:
Publisher:
publish-pypi.yml on dnncha/turbo-picard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
turbo_picard-0.1.2-py3-none-macosx_11_0_arm64.whl -
Subject digest:
06a196dddb3a5e62a2a3b9dda64284afc8afcbfdd68a9ea837a604a8cd96940a - Sigstore transparency entry: 1789351777
- Sigstore integration time:
-
Permalink:
dnncha/turbo-picard@161e386f6bdc5daf267e96f4040a3f1124c827ac -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/dnncha
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@161e386f6bdc5daf267e96f4040a3f1124c827ac -
Trigger Event:
release
-
Statement type: