vdjtools 2.0.0a2__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/.gitignore +3 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/PKG-INFO +92 -13
- vdjtools-2.2.0/README.md +154 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/include/vdjtools/model.hpp +11 -1
- vdjtools-2.2.0/notebooks/model_explorer.py +142 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/pyproject.toml +6 -3
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/__init__.py +1 -1
- vdjtools-2.2.0/python/vdjtools/biomarker/__init__.py +8 -0
- vdjtools-2.2.0/python/vdjtools/biomarker/fisher.py +202 -0
- vdjtools-2.2.0/python/vdjtools/biomarker/metaclonotype.py +114 -0
- vdjtools-2.2.0/python/vdjtools/cli/__init__.py +249 -0
- vdjtools-2.2.0/python/vdjtools/cli/__main__.py +4 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/features/kmer.py +5 -5
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/features/physchem.py +12 -11
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/io/__init__.py +18 -4
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/io/batch.py +43 -2
- vdjtools-2.2.0/python/vdjtools/io/convert.py +395 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/io/read.py +13 -13
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/io/schema.py +18 -15
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/__init__.py +3 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/d2_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/d2_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/d_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/d_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/dd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/dd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/dj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/dj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/genes_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/manifest.json +88 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/n_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/vd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGH/vd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/manifest.json +44 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/vj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGK/vj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/manifest.json +44 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/vj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/IGL/vj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/manifest.json +44 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/vj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRA/vj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/d2_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/d2_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/d_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/d_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/dd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/dd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/dj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/dj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/genes_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/manifest.json +88 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/n_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/vd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRB/vd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/d2_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/d2_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/d_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/d_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/dd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/dd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/dj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/dj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/genes_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/manifest.json +88 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/n_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/vd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRD/vd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/manifest.json +44 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/vj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/learned/TRG/vj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/d_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/d_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/dj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/dj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/genes_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/manifest.json +68 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/n_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/vd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGH/vd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/manifest.json +44 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/vj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGK/vj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/manifest.json +44 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/vj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/IGL/vj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/manifest.json +44 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/vj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRA/vj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/d_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/d_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/dj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/dj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/genes_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/manifest.json +68 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/n_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/vd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRB/vd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/d_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/d_gene.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/dj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/dj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/genes_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/manifest.json +68 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/n_d.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/vd_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRD/vd_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/genes_j.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/genes_v.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/j_5_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/j_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/manifest.json +44 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/v_3_del.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/v_choice.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/vj_dinucl.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/_bundled/olga/TRG/vj_ins.parquet +0 -0
- vdjtools-2.2.0/python/vdjtools/model/bundled.py +56 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/generate.py +5 -5
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/infer.py +31 -13
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/native.py +43 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/reference.py +95 -4
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/stitch.py +1 -1
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/overlap/cluster.py +2 -2
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/overlap/fuzzy.py +10 -10
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/overlap/metrics.py +4 -4
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/overlap/similarity.py +13 -13
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/overlap/tcrnet.py +7 -7
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/overlap/track.py +2 -2
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/preprocess/correct.py +7 -7
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/preprocess/decontaminate.py +3 -3
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/preprocess/filter.py +7 -7
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/preprocess/pool.py +13 -13
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/sc/__init__.py +3 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/sc/pair.py +9 -9
- vdjtools-2.2.0/python/vdjtools/sc/pgen.py +90 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/sc/read.py +15 -15
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/stats/spectratype.py +4 -4
- vdjtools-2.2.0/skills/vdjtools/SKILL.md +99 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/src/_bindings.cpp +12 -2
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/src/core.cpp +1 -1
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/src/pgen.cpp +71 -6
- vdjtools-2.0.0a2/README.md +0 -73
- vdjtools-2.0.0a2/python/vdjtools/biomarker/__init__.py +0 -1
- vdjtools-2.0.0a2/python/vdjtools/cli/__init__.py +0 -1
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/CMakeLists.txt +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/LICENSE +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/environment.yml +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/include/vdjtools/core.hpp +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/include/vdjtools/inext.hpp +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/features/__init__.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/io/cohort.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/analyze.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/data.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/dd.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/events.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/io.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/model.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/pgen.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/model/schema.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/overlap/__init__.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/preprocess/__init__.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/preprocess/batch.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/preprocess/downsample.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/preprocess/join.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/py.typed +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/resources/.gitkeep +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/resources/aa_property_table.txt +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/sc/anndata.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/sc/cluster_eval.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/stats/__init__.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/stats/diversity.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/stats/inext.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/stats/rarefaction.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/python/vdjtools/stats/usage.py +0 -0
- {vdjtools-2.0.0a2 → vdjtools-2.2.0}/src/inext.cpp +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: vdjtools
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: TCR/BCR repertoire analysis — Pgen/generation/inference, diversity, overlap, biomarkers (Python + C++)
|
|
5
5
|
Keywords: immunology,tcr,bcr,airr,repertoire,pgen,olga,igor,bioinformatics
|
|
6
6
|
Author-Email: Mikhail Shugay <mikhail.shugay@gmail.com>
|
|
@@ -18,6 +18,7 @@ Requires-Python: >=3.10
|
|
|
18
18
|
Requires-Dist: polars>=1.0
|
|
19
19
|
Requires-Dist: numpy
|
|
20
20
|
Requires-Dist: scipy
|
|
21
|
+
Requires-Dist: typer>=0.12
|
|
21
22
|
Provides-Extra: model
|
|
22
23
|
Requires-Dist: arda-mapper>=2.5; extra == "model"
|
|
23
24
|
Provides-Extra: overlap
|
|
@@ -31,8 +32,6 @@ Requires-Dist: scikit-learn; extra == "sc"
|
|
|
31
32
|
Requires-Dist: pyyaml; extra == "sc"
|
|
32
33
|
Requires-Dist: anndata; extra == "sc"
|
|
33
34
|
Requires-Dist: huggingface_hub; extra == "sc"
|
|
34
|
-
Provides-Extra: cli
|
|
35
|
-
Requires-Dist: typer>=0.12; extra == "cli"
|
|
36
35
|
Provides-Extra: examples
|
|
37
36
|
Requires-Dist: marimo; extra == "examples"
|
|
38
37
|
Requires-Dist: huggingface_hub; extra == "examples"
|
|
@@ -56,7 +55,6 @@ Requires-Dist: pybind11>=2.12; extra == "dev"
|
|
|
56
55
|
Provides-Extra: all
|
|
57
56
|
Requires-Dist: arda-mapper>=2.5; extra == "all"
|
|
58
57
|
Requires-Dist: vdjmatch>=0.0.1; extra == "all"
|
|
59
|
-
Requires-Dist: typer>=0.12; extra == "all"
|
|
60
58
|
Description-Content-Type: text/markdown
|
|
61
59
|
|
|
62
60
|
<p align="center">
|
|
@@ -88,9 +86,12 @@ Built on the antigenomics ecosystem:
|
|
|
88
86
|
[vdjmatch](https://github.com/antigenomics/vdjmatch) (overlap + TCRnet),
|
|
89
87
|
[arda](https://github.com/antigenomics/arda) (AIRR annotation + markup repair).
|
|
90
88
|
|
|
91
|
-
> **Status: v2.
|
|
92
|
-
>
|
|
93
|
-
>
|
|
89
|
+
> **Status: `v2.2.0`** — the native V(D)J model engine plus the full analytics suite (diversity,
|
|
90
|
+
> overlap/TCRnet, preprocessing, biomarkers, single-cell), CDR features, and legacy-format ingestion
|
|
91
|
+
> (MiXcr, MiGec, immunoSEQ, IMGT/HighV-QUEST, Vidjil, RTCR). Clonotype columns follow the AIRR
|
|
92
|
+
> **junction** convention (`junction_nt` / `junction_aa`). The legacy v1.x tool lives on the
|
|
93
|
+
> [`legacy-1.x`](https://github.com/antigenomics/vdjtools/tree/legacy-1.x) branch and its releases
|
|
94
|
+
> remain available under the repository tags (`v0.0.1` … `1.2.1`).
|
|
94
95
|
|
|
95
96
|
## Install
|
|
96
97
|
|
|
@@ -117,17 +118,95 @@ pip install -e ".[dev,test]" # builds the _core C++ extension
|
|
|
117
118
|
|
|
118
119
|
Or run the bootstrap script: `bash setup.sh --dev-parents --tests`.
|
|
119
120
|
|
|
120
|
-
##
|
|
121
|
+
## Quickstart — recombination model engine
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
Precomputed models for all **7 human loci** ship in the wheel — no OLGA or download needed:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from vdjtools.model import load_bundled, native
|
|
127
|
+
from vdjtools.model.generate import generate
|
|
128
|
+
|
|
129
|
+
model = load_bundled("TRB", source="olga") # or source="learned" (fit to real repertoires)
|
|
130
|
+
|
|
131
|
+
native.pgen_nt(model, "TGTGCCAGCAGC...") # nucleotide generation probability (native C++)
|
|
132
|
+
native.pgen_aa(model, "CASSLAPGATNEKLFF") # amino-acid Pgen (codon-marginalised)
|
|
133
|
+
native.pgen_aa(model, "CASSLAPGATNEKLFF", mismatches=1) # + the whole Hamming-1 ball
|
|
134
|
+
native.pgen_aa_batch(model, seqs, mismatches=1, threads=0) # Pgen over many CDR3s, thread-parallel (~11×)
|
|
135
|
+
generate(model, 1000) # sample a repertoire -> polars DataFrame
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Matches OLGA's Pgen to machine precision across all 7 loci, and adds tandem-D (D-D) support that
|
|
139
|
+
OLGA/IGoR lack. Learn a model from your own out-of-frame reads with `model.infer.infer_native`.
|
|
140
|
+
|
|
141
|
+
Explore any model's recombination **Bayes net** interactively (entropy, mutual information, marginals):
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
pip install "vdjtools[examples]"
|
|
145
|
+
marimo edit notebooks/model_explorer.py
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Command line
|
|
149
|
+
|
|
150
|
+
`pip install vdjtools` installs the `vdjtools` command — the model engine (OLGA/IGoR-style) and the
|
|
151
|
+
repertoire analytics (over sample files or a metadata table, like the legacy tool):
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# recombination model engine — built-in models for all 7 loci (no download)
|
|
155
|
+
vdjtools models # list the bundled models
|
|
156
|
+
vdjtools generate -m TRB -n 1000 -o gen.tsv # sample sequences (cf. olga-generate_sequences)
|
|
157
|
+
vdjtools pgen seqs.tsv -m TRB -o pgen.tsv # Pgen per CDR3 (cf. olga-compute_pgen)
|
|
158
|
+
vdjtools pgen seqs.tsv -m TRB --mismatches 1 # + the Hamming-1 ball; --v-col/--j-col to condition
|
|
159
|
+
|
|
160
|
+
# repertoire analytics — sample files, or a cohort via -m/--metadata + --base-dir
|
|
161
|
+
vdjtools diversity sampleA.tsv sampleB.tsv -o diversity.tsv
|
|
162
|
+
vdjtools overlap *.tsv -o overlap.tsv
|
|
163
|
+
vdjtools segment-usage *.tsv --segment v -o usage.tsv
|
|
164
|
+
vdjtools spectratype *.tsv -o spectra.tsv
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Native vdjtools and AIRR Rearrangement inputs are auto-detected; every command writes TSV to `-o`
|
|
168
|
+
(or stdout, so it pipes). Run `vdjtools <command> --help` for options.
|
|
169
|
+
|
|
170
|
+
## Performance
|
|
171
|
+
|
|
172
|
+
The Pgen / generation / EM / diversity hot paths are a native C++ (pybind11) core; everything else is
|
|
173
|
+
polars. Amino-acid Pgen matches OLGA to machine precision (1e-15) across all 7 loci while being
|
|
174
|
+
several times faster, and the built-in models keep the resident set small. Single thread, Apple M3
|
|
175
|
+
(arm64), bundled human TRB model:
|
|
176
|
+
|
|
177
|
+
| operation | throughput | vs OLGA |
|
|
178
|
+
|---|---|---|
|
|
179
|
+
| nucleotide Pgen (single-D VDJ) | **~0.5 ms/seq** | **9×** |
|
|
180
|
+
| amino-acid Pgen | **~0.6–0.9 ms/seq** | **8.6×** |
|
|
181
|
+
| Pgen + Hamming-1 ball (1 substitution) | **~15 ms/seq** | **8.7×** |
|
|
182
|
+
| sequence generation | **~32 000 seq/s** | — |
|
|
183
|
+
|
|
184
|
+
Nucleotide Pgen (via the same transfer-matrix DP as the aa path — an in-frame CDR3 is an aa query with
|
|
185
|
+
one codon fixed per position) is exact vs OLGA across all loci. Batched Pgen / 1-mismatch over many
|
|
186
|
+
CDR3s parallelises over sequences (`native.pgen_aa_batch`, **~11× on 16 cores**, bitwise-identical to
|
|
187
|
+
the serial result); the EM E-step parallelises over reads (~6.7× on 8 threads); diversity/rarefaction
|
|
188
|
+
run on a native iNEXT kernel (bootstrap + parallel batch). Memory
|
|
189
|
+
stays light — **~63 MB** resident for `import vdjtools` plus one loaded model, **~123 MB** with all
|
|
190
|
+
seven bundled models resident. Reproduce with `appendix/bench_pgen.py` and the `test_*_benchmark.py`
|
|
191
|
+
suites (`RUN_BENCHMARK=1`).
|
|
192
|
+
|
|
193
|
+
## Capabilities (see [ROADMAP.md](ROADMAP.md) and the [API reference](https://docs.isalgo.dev/vdjtools/))
|
|
194
|
+
|
|
195
|
+
- **IO** — canonical clonotype frame on AIRR **junction** columns (`junction_nt` / `junction_aa`);
|
|
196
|
+
readers for native vdjtools, AIRR Rearrangement TSV, and Parquet, plus format-detecting converters
|
|
197
|
+
for MiXcr (v1/2 + v3/4), MiGec, Adaptive immunoSEQ (v1/v2), IMGT/HighV-QUEST, Vidjil, and RTCR
|
|
198
|
+
([`vdjtools.io.convert`](python/vdjtools/io/convert.py)); metadata-driven batch + hive-partitioned cohorts.
|
|
199
|
+
- **Model** — native V(D)J recombination model: generation probability (Pgen — nt, aa,
|
|
200
|
+
1-mismatch, V/J-agnostic, **thread-parallel batch**), sequence generation, and EM inference, all in a
|
|
201
|
+
native (pybind11) core. Supersedes OLGA and IGoR: arda-driven scenario enumeration, polars marginal
|
|
202
|
+
tables, read-parallelised EM, and **tandem-D (D-D)** support. Concordant with OLGA across all 7 loci;
|
|
203
|
+
precomputed OLGA + real-data-learned models bundled ([`load_bundled`](python/vdjtools/model/bundled.py)).
|
|
125
204
|
- **Stats** — diversity (Chao1/Shannon/Simpson/…), spectratype, V/J/VJ usage.
|
|
126
205
|
- **Features** — CDR physicochemical profiles, k-mer / V+k-mer summaries.
|
|
127
|
-
- **Overlap** — sample overlap and TCRnet (via vdjmatch/seqtree).
|
|
206
|
+
- **Overlap** — sample overlap and TCRnet (via vdjmatch/seqtree), similarity-aware overlap, clustering.
|
|
128
207
|
- **Preprocess** — downsampling, error-correction, VJ-usage batch-effect correction, pooling/joining.
|
|
129
208
|
- **Biomarker** — incidence-based association (Fisher) vs HLA / condition / chain-pairing; metaclonotypes.
|
|
130
|
-
- **Single-cell** — AIRR Cell / 10x interoperability.
|
|
209
|
+
- **Single-cell** — AIRR Cell / 10x interoperability, chain pairing + QC, and paired α/β Pgen.
|
|
131
210
|
|
|
132
211
|
## License
|
|
133
212
|
|
vdjtools-2.2.0/README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/vdjtools_dark.svg">
|
|
4
|
+
<source media="(prefers-color-scheme: light)" srcset="assets/vdjtools_light.svg">
|
|
5
|
+
<!-- Absolute PNG fallback: PyPI strips <picture>/<source> and cannot render a relative or
|
|
6
|
+
raw-served SVG, so the logo must be an absolute-URL raster here. GitHub uses the SVG sources. -->
|
|
7
|
+
<img alt="vdjtools" src="https://raw.githubusercontent.com/antigenomics/vdjtools/master/assets/vdjtools_dark.png" width="320">
|
|
8
|
+
</picture>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<h1 align="center">vdjtools — immune-repertoire analysis</h1>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="https://pypi.org/project/vdjtools/"><img alt="PyPI" src="https://img.shields.io/pypi/v/vdjtools"></a>
|
|
15
|
+
<a href="https://github.com/antigenomics/vdjtools/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/antigenomics/vdjtools/actions/workflows/ci.yml/badge.svg"></a>
|
|
16
|
+
<a href="https://docs.isalgo.dev/vdjtools/"><img alt="docs" src="https://github.com/antigenomics/vdjtools/actions/workflows/docs.yml/badge.svg"></a>
|
|
17
|
+
<img alt="python" src="https://img.shields.io/badge/python-3.10%2B-blue">
|
|
18
|
+
<img alt="license" src="https://img.shields.io/badge/license-GPLv3-green">
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
TCR/BCR immune-repertoire analysis — a clean-room **Python + C++** rewrite of the legacy
|
|
22
|
+
Groovy/Java [vdjtools](https://doi.org/10.1371/journal.pcbi.1004503), standardised on the
|
|
23
|
+
**AIRR schema** and **polars** DataFrames with minimal object-orientation.
|
|
24
|
+
|
|
25
|
+
Built on the antigenomics ecosystem:
|
|
26
|
+
[seqtree](https://github.com/antigenomics/seqtree) (fuzzy search / e-value engine),
|
|
27
|
+
[vdjmatch](https://github.com/antigenomics/vdjmatch) (overlap + TCRnet),
|
|
28
|
+
[arda](https://github.com/antigenomics/arda) (AIRR annotation + markup repair).
|
|
29
|
+
|
|
30
|
+
> **Status: `v2.2.0`** — the native V(D)J model engine plus the full analytics suite (diversity,
|
|
31
|
+
> overlap/TCRnet, preprocessing, biomarkers, single-cell), CDR features, and legacy-format ingestion
|
|
32
|
+
> (MiXcr, MiGec, immunoSEQ, IMGT/HighV-QUEST, Vidjil, RTCR). Clonotype columns follow the AIRR
|
|
33
|
+
> **junction** convention (`junction_nt` / `junction_aa`). The legacy v1.x tool lives on the
|
|
34
|
+
> [`legacy-1.x`](https://github.com/antigenomics/vdjtools/tree/legacy-1.x) branch and its releases
|
|
35
|
+
> remain available under the repository tags (`v0.0.1` … `1.2.1`).
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install vdjtools
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Prebuilt wheels ship for CPython 3.10–3.13 on Linux, macOS (Apple Silicon), and Windows; the
|
|
44
|
+
native `_core` C++ extension is bundled (the source distribution compiles it on install). The
|
|
45
|
+
pure-analytics paths (diversity / spectratype / usage / overlap) work out of the box; the model
|
|
46
|
+
and annotation paths additionally pull in [arda](https://github.com/antigenomics/arda) (MMseqs2):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install "vdjtools[model]"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Development
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
conda env create -f environment.yml # python + mmseqs2 (arda backend) + C++ toolchain
|
|
56
|
+
conda activate vdjtools
|
|
57
|
+
pip install -e ".[dev,test]" # builds the _core C++ extension
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Or run the bootstrap script: `bash setup.sh --dev-parents --tests`.
|
|
61
|
+
|
|
62
|
+
## Quickstart — recombination model engine
|
|
63
|
+
|
|
64
|
+
Precomputed models for all **7 human loci** ship in the wheel — no OLGA or download needed:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from vdjtools.model import load_bundled, native
|
|
68
|
+
from vdjtools.model.generate import generate
|
|
69
|
+
|
|
70
|
+
model = load_bundled("TRB", source="olga") # or source="learned" (fit to real repertoires)
|
|
71
|
+
|
|
72
|
+
native.pgen_nt(model, "TGTGCCAGCAGC...") # nucleotide generation probability (native C++)
|
|
73
|
+
native.pgen_aa(model, "CASSLAPGATNEKLFF") # amino-acid Pgen (codon-marginalised)
|
|
74
|
+
native.pgen_aa(model, "CASSLAPGATNEKLFF", mismatches=1) # + the whole Hamming-1 ball
|
|
75
|
+
native.pgen_aa_batch(model, seqs, mismatches=1, threads=0) # Pgen over many CDR3s, thread-parallel (~11×)
|
|
76
|
+
generate(model, 1000) # sample a repertoire -> polars DataFrame
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Matches OLGA's Pgen to machine precision across all 7 loci, and adds tandem-D (D-D) support that
|
|
80
|
+
OLGA/IGoR lack. Learn a model from your own out-of-frame reads with `model.infer.infer_native`.
|
|
81
|
+
|
|
82
|
+
Explore any model's recombination **Bayes net** interactively (entropy, mutual information, marginals):
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install "vdjtools[examples]"
|
|
86
|
+
marimo edit notebooks/model_explorer.py
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Command line
|
|
90
|
+
|
|
91
|
+
`pip install vdjtools` installs the `vdjtools` command — the model engine (OLGA/IGoR-style) and the
|
|
92
|
+
repertoire analytics (over sample files or a metadata table, like the legacy tool):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# recombination model engine — built-in models for all 7 loci (no download)
|
|
96
|
+
vdjtools models # list the bundled models
|
|
97
|
+
vdjtools generate -m TRB -n 1000 -o gen.tsv # sample sequences (cf. olga-generate_sequences)
|
|
98
|
+
vdjtools pgen seqs.tsv -m TRB -o pgen.tsv # Pgen per CDR3 (cf. olga-compute_pgen)
|
|
99
|
+
vdjtools pgen seqs.tsv -m TRB --mismatches 1 # + the Hamming-1 ball; --v-col/--j-col to condition
|
|
100
|
+
|
|
101
|
+
# repertoire analytics — sample files, or a cohort via -m/--metadata + --base-dir
|
|
102
|
+
vdjtools diversity sampleA.tsv sampleB.tsv -o diversity.tsv
|
|
103
|
+
vdjtools overlap *.tsv -o overlap.tsv
|
|
104
|
+
vdjtools segment-usage *.tsv --segment v -o usage.tsv
|
|
105
|
+
vdjtools spectratype *.tsv -o spectra.tsv
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Native vdjtools and AIRR Rearrangement inputs are auto-detected; every command writes TSV to `-o`
|
|
109
|
+
(or stdout, so it pipes). Run `vdjtools <command> --help` for options.
|
|
110
|
+
|
|
111
|
+
## Performance
|
|
112
|
+
|
|
113
|
+
The Pgen / generation / EM / diversity hot paths are a native C++ (pybind11) core; everything else is
|
|
114
|
+
polars. Amino-acid Pgen matches OLGA to machine precision (1e-15) across all 7 loci while being
|
|
115
|
+
several times faster, and the built-in models keep the resident set small. Single thread, Apple M3
|
|
116
|
+
(arm64), bundled human TRB model:
|
|
117
|
+
|
|
118
|
+
| operation | throughput | vs OLGA |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| nucleotide Pgen (single-D VDJ) | **~0.5 ms/seq** | **9×** |
|
|
121
|
+
| amino-acid Pgen | **~0.6–0.9 ms/seq** | **8.6×** |
|
|
122
|
+
| Pgen + Hamming-1 ball (1 substitution) | **~15 ms/seq** | **8.7×** |
|
|
123
|
+
| sequence generation | **~32 000 seq/s** | — |
|
|
124
|
+
|
|
125
|
+
Nucleotide Pgen (via the same transfer-matrix DP as the aa path — an in-frame CDR3 is an aa query with
|
|
126
|
+
one codon fixed per position) is exact vs OLGA across all loci. Batched Pgen / 1-mismatch over many
|
|
127
|
+
CDR3s parallelises over sequences (`native.pgen_aa_batch`, **~11× on 16 cores**, bitwise-identical to
|
|
128
|
+
the serial result); the EM E-step parallelises over reads (~6.7× on 8 threads); diversity/rarefaction
|
|
129
|
+
run on a native iNEXT kernel (bootstrap + parallel batch). Memory
|
|
130
|
+
stays light — **~63 MB** resident for `import vdjtools` plus one loaded model, **~123 MB** with all
|
|
131
|
+
seven bundled models resident. Reproduce with `appendix/bench_pgen.py` and the `test_*_benchmark.py`
|
|
132
|
+
suites (`RUN_BENCHMARK=1`).
|
|
133
|
+
|
|
134
|
+
## Capabilities (see [ROADMAP.md](ROADMAP.md) and the [API reference](https://docs.isalgo.dev/vdjtools/))
|
|
135
|
+
|
|
136
|
+
- **IO** — canonical clonotype frame on AIRR **junction** columns (`junction_nt` / `junction_aa`);
|
|
137
|
+
readers for native vdjtools, AIRR Rearrangement TSV, and Parquet, plus format-detecting converters
|
|
138
|
+
for MiXcr (v1/2 + v3/4), MiGec, Adaptive immunoSEQ (v1/v2), IMGT/HighV-QUEST, Vidjil, and RTCR
|
|
139
|
+
([`vdjtools.io.convert`](python/vdjtools/io/convert.py)); metadata-driven batch + hive-partitioned cohorts.
|
|
140
|
+
- **Model** — native V(D)J recombination model: generation probability (Pgen — nt, aa,
|
|
141
|
+
1-mismatch, V/J-agnostic, **thread-parallel batch**), sequence generation, and EM inference, all in a
|
|
142
|
+
native (pybind11) core. Supersedes OLGA and IGoR: arda-driven scenario enumeration, polars marginal
|
|
143
|
+
tables, read-parallelised EM, and **tandem-D (D-D)** support. Concordant with OLGA across all 7 loci;
|
|
144
|
+
precomputed OLGA + real-data-learned models bundled ([`load_bundled`](python/vdjtools/model/bundled.py)).
|
|
145
|
+
- **Stats** — diversity (Chao1/Shannon/Simpson/…), spectratype, V/J/VJ usage.
|
|
146
|
+
- **Features** — CDR physicochemical profiles, k-mer / V+k-mer summaries.
|
|
147
|
+
- **Overlap** — sample overlap and TCRnet (via vdjmatch/seqtree), similarity-aware overlap, clustering.
|
|
148
|
+
- **Preprocess** — downsampling, error-correction, VJ-usage batch-effect correction, pooling/joining.
|
|
149
|
+
- **Biomarker** — incidence-based association (Fisher) vs HLA / condition / chain-pairing; metaclonotypes.
|
|
150
|
+
- **Single-cell** — AIRR Cell / 10x interoperability, chain pairing + QC, and paired α/β Pgen.
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
GPL-3.0-or-later.
|
|
@@ -64,6 +64,13 @@ double pgen_aa(const PackedModel& m, const std::string& aa, int v_idx, int j_idx
|
|
|
64
64
|
// via the inclusion-exclusion identity over per-position wildcards. v_idx/j_idx as above.
|
|
65
65
|
double pgen_aa_hamming1(const PackedModel& m, const std::string& aa, int v_idx, int j_idx);
|
|
66
66
|
|
|
67
|
+
// Batch aa Pgen over many sequences, parallelized across sequences (mismatches: 0 = exact,
|
|
68
|
+
// 1 = Hamming-1 ball). Bitwise-identical to the per-sequence calls. Per-sequence v/j indices;
|
|
69
|
+
// empty v_idxs/j_idxs → all -1 (gene-agnostic). nthreads=0 → auto (hw-2).
|
|
70
|
+
std::vector<double> pgen_aa_batch(const PackedModel& m, const std::vector<std::string>& seqs,
|
|
71
|
+
const std::vector<int>& v_idxs, const std::vector<int>& j_idxs,
|
|
72
|
+
int mismatches, int nthreads);
|
|
73
|
+
|
|
67
74
|
// EM soft counts — one accumulator per event realization, laid out like the PackedModel prob
|
|
68
75
|
// arrays so the Python M-step can renormalize them directly.
|
|
69
76
|
struct Counts {
|
|
@@ -85,12 +92,15 @@ Counts make_counts(const PackedModel& m);
|
|
|
85
92
|
// in a fixed order); 0 = auto (hardware_concurrency - 2). Small batches run single-threaded so their
|
|
86
93
|
// result stays bitwise-identical. The soft counts are exact regardless of thread count (up to the
|
|
87
94
|
// float summation order, which the fixed reduction keeps deterministic per ``nthreads``).
|
|
95
|
+
// ``dd_allowed`` optionally gates the tandem (n_D=2) E-step per read (1 = may be tandem, 0 = single-D
|
|
96
|
+
// only); empty = every read may be tandem. Used to anchor D-D learning to arda's tandem calls.
|
|
88
97
|
double estep_batch(const PackedModel& m,
|
|
89
98
|
const std::vector<std::vector<int8_t>>& seqs,
|
|
90
99
|
const std::vector<std::vector<int>>& vmasks,
|
|
91
100
|
const std::vector<std::vector<int>>& jmasks,
|
|
92
101
|
const std::vector<std::vector<int>>& dmasks,
|
|
93
102
|
Counts& counts,
|
|
94
|
-
int nthreads = 0
|
|
103
|
+
int nthreads = 0,
|
|
104
|
+
const std::vector<int>& dd_allowed = {});
|
|
95
105
|
|
|
96
106
|
} // namespace vdjtools
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# vdjtools — interactive recombination-model explorer.
|
|
2
|
+
# Reactive marimo app: pick a locus and model source, see its Bayes net (nodes = marginal entropy H,
|
|
3
|
+
# edges = mutual information I), the per-event entropy / MI tables, a marginal distribution, and an
|
|
4
|
+
# OLGA-vs-learned comparison. Run with: marimo edit notebooks/model_explorer.py
|
|
5
|
+
import marimo
|
|
6
|
+
|
|
7
|
+
__generated_with = "0.23.14"
|
|
8
|
+
app = marimo.App(width="medium")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@app.cell
|
|
12
|
+
def _():
|
|
13
|
+
import marimo as mo
|
|
14
|
+
return (mo,)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@app.cell
|
|
18
|
+
def _(mo):
|
|
19
|
+
import subprocess
|
|
20
|
+
|
|
21
|
+
import matplotlib.pyplot as plt
|
|
22
|
+
import polars as pl
|
|
23
|
+
|
|
24
|
+
from vdjtools.model import analyze, list_bundled, load_bundled
|
|
25
|
+
return analyze, list_bundled, load_bundled, mo, pl, plt, subprocess
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@app.cell
|
|
29
|
+
def _(mo):
|
|
30
|
+
mo.md(
|
|
31
|
+
"""
|
|
32
|
+
# V(D)J recombination model explorer
|
|
33
|
+
|
|
34
|
+
Explore any bundled recombination model as a **Bayes net** — nodes are recombination events
|
|
35
|
+
(sized/annotated by their marginal Shannon entropy *H*), edges are the conditioning
|
|
36
|
+
dependencies (annotated by mutual information *I*). Compare the **OLGA** bootstrap models to
|
|
37
|
+
the **EM-learned** models fit to real out-of-frame repertoires.
|
|
38
|
+
"""
|
|
39
|
+
)
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@app.cell
|
|
44
|
+
def _(list_bundled, mo):
|
|
45
|
+
avail = list_bundled()
|
|
46
|
+
source = mo.ui.dropdown(list(avail), value="olga", label="Model source")
|
|
47
|
+
return avail, source
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@app.cell
|
|
51
|
+
def _(avail, mo, source):
|
|
52
|
+
loci = avail.get(source.value, [])
|
|
53
|
+
locus = mo.ui.dropdown(loci, value=(loci[0] if loci else None), label="Locus")
|
|
54
|
+
mo.hstack([source, locus], justify="start", gap=2)
|
|
55
|
+
return (locus,)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@app.cell
|
|
59
|
+
def _(load_bundled, locus, mo, source):
|
|
60
|
+
mo.stop(locus.value is None, mo.md("*No bundled models found — build them first.*"))
|
|
61
|
+
model = load_bundled(locus.value, source.value)
|
|
62
|
+
mo.md(f"**{locus.value}** · *{source.value}* · chain **{model.chain_type}** · "
|
|
63
|
+
f"{model.genomic['genes_v'].height} V / {model.genomic['genes_j'].height} J genes")
|
|
64
|
+
return (model,)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@app.cell
|
|
68
|
+
def _(analyze, mo, model, subprocess):
|
|
69
|
+
# Render the Bayes net to inline SVG via the graphviz `dot` CLI (no python-graphviz dep).
|
|
70
|
+
dot = analyze.bayes_net_dot(model)
|
|
71
|
+
try:
|
|
72
|
+
svg = subprocess.run(["dot", "-Tsvg"], input=dot, capture_output=True, text=True, check=True).stdout
|
|
73
|
+
svg = svg[svg.index("<svg"):] # drop the <?xml?> / <!DOCTYPE> preamble for clean inline embedding
|
|
74
|
+
bn = mo.Html(svg)
|
|
75
|
+
except (FileNotFoundError, subprocess.CalledProcessError):
|
|
76
|
+
bn = mo.md("`dot` (graphviz) not found — showing the DOT source instead:").callout("warn")
|
|
77
|
+
bn = mo.vstack([bn, mo.plain_text(dot)])
|
|
78
|
+
mo.vstack([mo.md("### Bayes net *(node = event · H bits; edge = conditioning · I bits)*"), bn])
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@app.cell
|
|
83
|
+
def _(analyze, mo, model):
|
|
84
|
+
ent = analyze.entropy_table(model)
|
|
85
|
+
mi = analyze.mutual_information(model)
|
|
86
|
+
mo.hstack([
|
|
87
|
+
mo.vstack([mo.md("### Marginal entropy *H* (bits)"), ent]),
|
|
88
|
+
mo.vstack([mo.md("### Mutual information *I* (bits)"), mi]),
|
|
89
|
+
], widths=[1, 1], gap=2)
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@app.cell
|
|
94
|
+
def _(mo, model):
|
|
95
|
+
# Pick a marginal to plot (insertion length or a gene-usage table).
|
|
96
|
+
plottable = [e for e in ("vd_ins", "dj_ins", "vj_ins", "dd_ins", "d_del", "n_d", "v_choice", "j_choice")
|
|
97
|
+
if e in model.tables]
|
|
98
|
+
event = mo.ui.dropdown(plottable, value=plottable[0] if plottable else None, label="Marginal to plot")
|
|
99
|
+
event
|
|
100
|
+
return (event,)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@app.cell
|
|
104
|
+
def _(event, mo, model, plt):
|
|
105
|
+
mo.stop(event.value is None)
|
|
106
|
+
df = model.tables[event.value]
|
|
107
|
+
fig, ax = plt.subplots(figsize=(7, 3))
|
|
108
|
+
cols = df.columns
|
|
109
|
+
if "length" in cols:
|
|
110
|
+
ax.bar(df["length"], df["p"]); ax.set_xlabel("insertion length (nt)")
|
|
111
|
+
elif "n_d" in cols:
|
|
112
|
+
ax.bar(df["n_d"].cast(str), df["p"]); ax.set_xlabel("number of D segments")
|
|
113
|
+
elif "ndel5" in cols: # 2D deletion: marginal over 3'
|
|
114
|
+
agg = df.group_by("ndel5").agg(__import__("polars").col("p").sum()).sort("ndel5")
|
|
115
|
+
ax.bar(agg["ndel5"], agg["p"]); ax.set_xlabel("D 5' deletion (nt; neg = P-nt)")
|
|
116
|
+
else: # gene usage: top 15 by probability
|
|
117
|
+
top = df.sort("p", descending=True).head(15)
|
|
118
|
+
gcol = [c for c in cols if c.endswith("_allele")][-1]
|
|
119
|
+
ax.barh(top[gcol].to_list()[::-1], top["p"].to_list()[::-1]); ax.set_xlabel("P")
|
|
120
|
+
ax.set_ylabel("probability"); ax.set_title(f"{event.value}"); fig.tight_layout()
|
|
121
|
+
ax
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@app.cell
|
|
126
|
+
def _(analyze, avail, load_bundled, locus, mo):
|
|
127
|
+
# OLGA vs learned entropy side-by-side, when both are available for this locus.
|
|
128
|
+
both = {s: load_bundled(locus.value, s) for s in ("olga", "learned")
|
|
129
|
+
if locus.value in avail.get(s, [])}
|
|
130
|
+
if len(both) == 2:
|
|
131
|
+
import polars as _pl
|
|
132
|
+
cmp = analyze.compare_entropy(both).with_columns(
|
|
133
|
+
(_pl.col("learned") - _pl.col("olga")).round(3).alias("Δ (learned−olga)"))
|
|
134
|
+
out = mo.vstack([mo.md("### OLGA vs learned — marginal entropy *H* (bits)"), cmp])
|
|
135
|
+
else:
|
|
136
|
+
out = mo.md("*Load a locus present in both `olga` and `learned` to see the comparison.*").callout()
|
|
137
|
+
out
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
app.run()
|
|
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vdjtools" # if the PyPI name is taken, fall back to a distinct dist name (cf. arda -> arda-mapper)
|
|
7
|
-
version = "2.0
|
|
7
|
+
version = "2.2.0"
|
|
8
8
|
description = "TCR/BCR repertoire analysis — Pgen/generation/inference, diversity, overlap, biomarkers (Python + C++)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -26,21 +26,24 @@ dependencies = [
|
|
|
26
26
|
"polars>=1.0",
|
|
27
27
|
"numpy",
|
|
28
28
|
"scipy",
|
|
29
|
+
"typer>=0.12", # the `vdjtools` CLI (Phase 8) is a core entry point
|
|
29
30
|
]
|
|
30
31
|
|
|
32
|
+
[project.scripts]
|
|
33
|
+
vdjtools = "vdjtools.cli:app"
|
|
34
|
+
|
|
31
35
|
[project.optional-dependencies]
|
|
32
36
|
model = ["arda-mapper>=2.5"] # Phase 1: scenario enumeration + markup repair (brings mmseqs2)
|
|
33
37
|
overlap = ["vdjmatch>=0.0.1", "seqtree>=0.3", "scikit-learn"] # Phase 4: overlap + TCRnet (brings the seqtree engine); sklearn for MDS clustering; seqtree for similarity-weighted (TINA) overlap
|
|
34
38
|
preprocess = ["seqtree>=0.3"] # Phase 5: freq-based error correction (near-neighbour search)
|
|
35
39
|
sc = ["scikit-learn", "pyyaml", "anndata", "huggingface_hub"] # Phase 7: single-cell — sklearn for cluster_eval contingency, pyyaml for AIRR Cell export, anndata for the scverse bridge (to_anndata), HF for the dCODE benchmark fetch (tests only)
|
|
36
|
-
cli = ["typer>=0.12"] # Phase 8
|
|
37
40
|
examples = ["marimo", "huggingface_hub", "matplotlib", "scikit-learn"] # example notebooks (scipy is a base dep)
|
|
38
41
|
oracle = ["olga"] # Pgen cross-check oracle (tests only)
|
|
39
42
|
test = ["pytest>=7.4", "pytest-cov"]
|
|
40
43
|
bench = ["huggingface_hub"] # test-only: real-data fetch; never a runtime dep
|
|
41
44
|
docs = ["sphinx>=7", "pydata-sphinx-theme>=0.15", "nbsphinx"]
|
|
42
45
|
dev = ["ruff", "pytest>=7.4", "pybind11>=2.12"]
|
|
43
|
-
all = ["arda-mapper>=2.5", "vdjmatch>=0.0.1"
|
|
46
|
+
all = ["arda-mapper>=2.5", "vdjmatch>=0.0.1"]
|
|
44
47
|
|
|
45
48
|
[project.urls]
|
|
46
49
|
Homepage = "https://github.com/antigenomics/vdjtools"
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""vdjtools.biomarker — Incidence-based association (Fisher) and metaclonotype grouping."""
|
|
2
|
+
from .fisher import fisher_association
|
|
3
|
+
from .metaclonotype import metaclonotypes
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"fisher_association", # Fisher-exact clonotype-incidence vs phenotype association
|
|
7
|
+
"metaclonotypes", # edit-scope metaclonotype grouping (1mm matching)
|
|
8
|
+
]
|