Probabilistic identification of antigen-specific T cells from single-cell pMHC multimer experiments.
DextraDemixer models pMHC multimer UMI counts as a mixture of specific and nonspecific binding components. It returns a posterior binding probability and assignment for each cell, helping separate antigen-specific signal from background binding and assay noise.
The method is described in DextraDemixer enables accurate identification of antigen-specific T cells from pMHC multimer experiments.
Note
DextraDemixer is research software under active development. Interfaces may change while the package matures.
- Infers cell-level posterior probabilities of antigen specificity from pMHC UMI counts.
- Supports optional negative-control multimers.
- Incorporates clonotype information through clone-level probability aggregation.
- Provides fixed-threshold and Bayesian false discovery rate (FDR) assignments.
- Works directly with
MuData,AnnData, andPandas DataFramesobjects and uses JAX and NumPyro for inference.
pip install dextrademixerFor a conda environment.
git clone https://github.com/SchubertLab/DextraDemixer.git
cd DextraDemixer
conda env create -f environment.yaml
conda activate dextrademixer
pip install -e . # or pip install dextrademixerThe final command installs the local package in editable mode. Runtime dependency constraints are aligned between pyproject.toml and environment.yaml. To reproduce the numbers from the manuscript, use environment_reproducible.yaml instead: it pins the exact versions, and results can shift slightly with other JAX/NumPyro releases.
The example below fits one pMHC feature and classifies cells using a posterior-probability threshold of 0.5.
import muon as mu
from dextrademixer import DextraDemixer
mdata = mu.read("data/example_data.h5mu")
model = DextraDemixer().fit(mdata, pmhc_key="pmhc1", pmhc_modality_key="gex")
p_binder, is_binder = model.predict(threshold=0.5)
mdata.mod["gex"].obs["dextrademixer_probability"] = p_binder
mdata.mod["gex"].obs["dextrademixer_assignment"] = is_binderTo include a negative-control multimer, pass neg_ctrl_key. To aggregate probabilities within clonotypes, pass the clonotype column as ir_clone_key and set clonotype_median_p=True when predicting:
model = DextraDemixer().fit(
mdata,
pmhc_key="pmhc1",
pmhc_modality_key="gex",
neg_ctrl_key="neg_control",
ir_clone_key="clone_id",
)
p_pred, assignment = model.predict(threshold=0.5, clonotype_median_p=True)Use either threshold for a fixed decision boundary or target_fdr for FDR-controlled assignments; do not specify both.
DextraDemixerMulti fits one independent DextraDemixer per pMHC and returns cells x pMHC tables instead of vectors. Each fit stays reachable as model.demixers[pmhc_key].
from dextrademixer import DextraDemixerMulti
mdata = mu.read("data/example_multi_pmhc.h5mu")
model = DextraDemixerMulti().fit(
mdata,
pmhc_keys=["pmhc1", "pmhc2", "pmhc3"],
pmhc_modality_key="gex",
neg_ctrl_key="neg_control",
)
p_pred, assignment = model.predict(threshold=0.5, clonotype_median_p=True, max_prob=True)Because the pMHCs are fitted independently, a cell can pass the threshold for several. max_prob=True keeps only the pMHC with the highest probability per cell, combined with clonotype_median_p=True the same choice is made per clonotype.
DextraDemixer needs the pMHC UMI counts and, optionally, a cell-level clonotype identifier. It reads them from any of:
- A
MuDataobject: counts in the.Xof the feature modality (pmhc_modality_key,gexby default), clonotypes in the.obsof the AIRR modality (ir_modality_key,airrby default). - An
AnnDataobject: counts in.X, clonotypes in.obs;pmhc_modality_keyandir_modality_keyare then unused. - A cells x features
DataFrame: counts and annotation in the same table, so every key is a column name.
pmhc_key (or pmhc_keys) and the optional neg_ctrl_key name the count columns, ir_clone_key the clonotype column, whose ids may be integers or strings. The bundled example dataset ships in all three formats: data/example_data.h5mu, .h5ad and .csv. data/example_multi_pmhc.h5mu is a simulated three-pMHC panel.
See Tutorial.ipynb for a complete, reproducible workflow using the bundled example dataset, including configuration, model fitting, evaluation, and visualization, and Tutorial DextraDemixerMulti.ipynb for the same with multiple pMHCs:
jupyter lab Tutorial.ipynbThe analyses and figure-generation code used in the manuscript are maintained in the DextraDemixer reproducibility repository.
Bug reports, feature requests, and pull requests are welcome through the GitHub issue tracker. When reporting a problem, please include a minimal reproducible example and details of your operating system and Conda environment.
If DextraDemixer supports your research, please cite:
@article{An2026DextraDemixer,
author = {An, Yang and Drost, Felix and Bonafonte-Pard{\`a}s, Irene and Grotz, Myriam and Schober, Kilian and Schubert, Benjamin},
title = {DextraDemixer enables accurate identification of antigen-specific T cells from pMHC multimer experiments},
journal = {bioRxiv},
year = {2026},
publisher = {Cold Spring Harbor Laboratory},
doi = {10.64898/2026.06.23.733339},
url = {https://doi.org/10.64898/2026.06.23.733339},
elocation-id = {2026.06.23.733339}
}DextraDemixer is distributed under the BSD 3-Clause License.