Skill Tracer
Skills › Scientific Agent Skills › pydeseq2 › api_reference.md

api_reference.md

157 lines · skills/pydeseq2/references/api_reference.md at 5f2bc03

Open on GitHub
1# PyDESeq2 0.5.4 API and verification notes
2
3Reviewed 2026-10-01 against the published release, official stable documentation,
4`v0.5.4` source and a local native runtime. This is a focused contract reference,
5not a complete replacement for upstream documentation.
6

PyDESeq2 0.5.4 API and verification notes

Reviewed 2026-10-01 against the published release, official stable documentation, v0.5.4 source and a local native runtime. This is a focused contract reference, not a complete replacement for upstream documentation.

Raw lines 1 to 6
7## Installation and tested scope
8
9The [current release](https://pypi.org/project/pydeseq2/0.5.4/) is 0.5.4 and requires
10Python >=3.11. Its dependency floor includes AnnData >=0.11, NumPy >=2,
11pandas >=2.2, SciPy >=1.12, scikit-learn >=1.4, formulaic >=1.0.2, and
12formulaic-contrasts >=0.2.0. Dependency floors are not a claim that every later
13combination was tested. AnnData 0.13.4 requires Python >=3.12.
15The native review used Python 3.13.3, PyDESeq2 0.5.4, AnnData 0.13.4,
16pandas 3.0.6, NumPy 2.5.1, SciPy 1.18.1, scikit-learn 1.9.1,
17formulaic 1.2.2, formulaic-contrasts 1.0.0, and Matplotlib 3.11.2.
18Tests cover synthetic numerical/input/contrast contracts and real H5AD round-trips.
19They do not establish R/Python numerical equivalence, real biological calibration,
20large-data memory performance, or all inference backends/platforms.

Installation and tested scope

The current release is 0.5.4 and requires Python >=3.11. Its dependency floor includes AnnData >=0.11, NumPy >=2, pandas >=2.2, SciPy >=1.12, scikit-learn >=1.4, formulaic >=1.0.2, and formulaic-contrasts >=0.2.0. Dependency floors are not a claim that every later combination was tested. AnnData 0.13.4 requires Python >=3.12.

The native review used Python 3.13.3, PyDESeq2 0.5.4, AnnData 0.13.4, pandas 3.0.6, NumPy 2.5.1, SciPy 1.18.1, scikit-learn 1.9.1, formulaic 1.2.2, formulaic-contrasts 1.0.0, and Matplotlib 3.11.2. Tests cover synthetic numerical/input/contrast contracts and real H5AD round-trips. They do not establish R/Python numerical equivalence, real biological calibration, large-data memory performance, or all inference backends/platforms.

Raw lines 7 to 21
22## `DeseqDataSet`
24```python
25from pydeseq2.dds import DeseqDataSet
26from pydeseq2.default_inference import DefaultInference
28dds = DeseqDataSet(
29 counts=counts_df, metadata=metadata, design='~condition',
30 fit_type='parametric', size_factors_fit_type='ratio',
31 refit_cooks=True, min_replicates=7,
32 inference=DefaultInference(n_cpus=1), low_memory=False,
34dds.deseq2() # required before constructing DeseqStats
35```
37- `counts`: samples × genes nonnegative integer DataFrame; `metadata` has matching
38 sample rows. Alternatively use `adata=` with counts in `.X` and annotations in
39 `.obs`; do not also supply counts/metadata. Sparse input is not a guarantee of a
40 sparse complete fit. Validate/densify a small matrix intentionally.
41- `design`: formula string or explicit design DataFrame. The older `design_factors`,
42 `continuous_factors`, and `ref_level` parameters are deprecated. Formulaic uses
43 numeric variables continuously; set categorical dtype/reference levels explicitly.
44- `fit_type`: `'parametric'` or `'mean'`; the former can fall back with a warning.
45- `size_factors_fit_type`: `'ratio'`, `'poscounts'`, or `'iterative'`.
46 `control_genes` selects gene indexers, with the release-specific caveats in the
47 [workflow guide](workflow_guide.md).
48- `refit_cooks`: eligible count replacement and refitting; not sample deletion.
49 `min_replicates` defaults to seven.
50- `n_cpus` can be set directly or on `DefaultInference`; reuse a bounded inference
51 object for fitting/testing. `quiet=True` reduces routine messages, not all warnings.
53Methods:
55| Method | Contract |
56| --- | --- |
57| `deseq2(fit_type=None)` | Fit normalization, dispersions, LFCs and Cook diagnostics/refits; updates in place. |
58| `fit_size_factors(fit_type=None, control_genes=None)` | Normalize only; check positive finite factors. |
59| `cond(**kwargs)` | Formula-based condition vector; unspecified factors use defaults/baselines. |
60| `contrast(column, baseline, group_to_compare)` | Formula-based simple pairwise contrast vector. |
61| `plot_dispersions(log=True, save_path=None, **kwargs)` | Plot gene-wise, fitted and final dispersions. |
62| `vst(use_design=False, fit_type=None)` | Fits/applies VST and stores `layers['vst_counts']`. |
63| `vst_fit(use_design=False)` / `vst_transform(counts=None)` | Separate fitted transformation and application; held-out use needs method-specific validation. |
64| `to_picklable_anndata()` | Plain AnnData snapshot; converts formulaic design matrix to DataFrame. |

DeseqDataSet

from pydeseq2.dds import DeseqDataSet
from pydeseq2.default_inference import DefaultInference

dds = DeseqDataSet(
    counts=counts_df, metadata=metadata, design='~condition',
    fit_type='parametric', size_factors_fit_type='ratio',
    refit_cooks=True, min_replicates=7,
    inference=DefaultInference(n_cpus=1), low_memory=False,
)
dds.deseq2()  # required before constructing DeseqStats
  • counts: samples × genes nonnegative integer DataFrame; metadata has matching sample rows. Alternatively use adata= with counts in .X and annotations in .obs; do not also supply counts/metadata. Sparse input is not a guarantee of a sparse complete fit. Validate/densify a small matrix intentionally.
  • design: formula string or explicit design DataFrame. The older design_factors, continuous_factors, and ref_level parameters are deprecated. Formulaic uses numeric variables continuously; set categorical dtype/reference levels explicitly.
  • fit_type: 'parametric' or 'mean'; the former can fall back with a warning.
  • size_factors_fit_type: 'ratio', 'poscounts', or 'iterative'. control_genes selects gene indexers, with the release-specific caveats in the workflow guide.
  • refit_cooks: eligible count replacement and refitting; not sample deletion. min_replicates defaults to seven.
  • n_cpus can be set directly or on DefaultInference; reuse a bounded inference object for fitting/testing. quiet=True reduces routine messages, not all warnings.

Methods:

MethodContract
deseq2(fit_type=None)Fit normalization, dispersions, LFCs and Cook diagnostics/refits; updates in place.
fit_size_factors(fit_type=None, control_genes=None)Normalize only; check positive finite factors.
cond(**kwargs)Formula-based condition vector; unspecified factors use defaults/baselines.
contrast(column, baseline, group_to_compare)Formula-based simple pairwise contrast vector.
plot_dispersions(log=True, save_path=None, **kwargs)Plot gene-wise, fitted and final dispersions.
vst(use_design=False, fit_type=None)Fits/applies VST and stores layers['vst_counts'].
vst_fit(use_design=False) / vst_transform(counts=None)Separate fitted transformation and application; held-out use needs method-specific validation.
to_picklable_anndata()Plain AnnData snapshot; converts formulaic design matrix to DataFrame.
Raw lines 22 to 65
66## AnnData layout after fitting
68| Field | Meaning |
69| --- | --- |
70| `X` | Input sample × gene counts. |
71| `obs['size_factors']` | One positive normalization factor per sample. |
72| `obsm['design_matrix']` | Sample × coefficient design matrix. |
73| `layers['normed_counts']` | Counts divided by sample factors; not TPM or VST. |
74| `layers['cooks']` | Sample × gene Cook diagnostic matrix, if retained. |
75| `var['genewise_dispersions']`, `['fitted_dispersions']`, `['MAP_dispersions']`, `['dispersions']` | Gene-wise/trend/MAP/final estimates. |
76| `varm['LFC']` | Gene × coefficient estimates in **natural log**, not log2. |
77| `var['_LFC_converged']` and other underscore fields | Useful release-specific diagnostic flags; not a stable cross-version schema. |
78| `uns` | Shared trend/prior parameters; contents depend on method/fallback. |
80`DeseqStats.results_df` is stored on the statistics object, not automatically in
81this AnnData. Save the result CSVs separately. An H5AD snapshot cannot recreate
82formulaic contrasts or resume every estimator method simply by reading it back.

AnnData layout after fitting

FieldMeaning
XInput sample × gene counts.
obs['size_factors']One positive normalization factor per sample.
obsm['design_matrix']Sample × coefficient design matrix.
layers['normed_counts']Counts divided by sample factors; not TPM or VST.
layers['cooks']Sample × gene Cook diagnostic matrix, if retained.
var['genewise_dispersions'], ['fitted_dispersions'], ['MAP_dispersions'], ['dispersions']Gene-wise/trend/MAP/final estimates.
varm['LFC']Gene × coefficient estimates in natural log, not log2.
var['_LFC_converged'] and other underscore fieldsUseful release-specific diagnostic flags; not a stable cross-version schema.
unsShared trend/prior parameters; contents depend on method/fallback.

DeseqStats.results_df is stored on the statistics object, not automatically in this AnnData. Save the result CSVs separately. An H5AD snapshot cannot recreate formulaic contrasts or resume every estimator method simply by reading it back.

Raw lines 66 to 83
84## `DeseqStats`
86```python
87from pydeseq2.ds import DeseqStats
89ds = DeseqStats(dds, contrast=['condition', 'treated', 'control'], alpha=0.05,
90 cooks_filter=True, independent_filter=True, n_cpus=1)
91ds.summary()
92```
94`contrast` is mandatory: a three-string list `[factor, numerator, denominator]`
95or a 1D NumPy vector with one entry per design column. Check finite entries,
96nonzero contrast and biological estimability. Numeric vectors should be NumPy
97arrays, not numeric Python lists interpreted as factor contrasts.
99`lfc_null=0.0` is in log2 units. `alt_hypothesis=None` gives the usual two-sided
100Wald test. `'greaterAbs'`, `'lessAbs'`, `'greater'`, and `'less'` specify different
101alternatives; choose deliberately. `summary(lfc_null=..., alt_hypothesis=...)`
102can replace the hypothesis and rerun testing, but do so on an unshrunken object.
103`prior_LFC_var` is an optional ridge prior and is distinct from apeGLM shrinkage.
105`summary()` updates `results_df` with `baseMean`, `log2FoldChange`, `lfcSE`,
106`stat`, `pvalue`, and `padj`. `baseMean` is the mean normalized count across all
107samples, not either condition's mean. Original LFC and SE are log2 values;
108`stat` is dimensionless. The usual zero-null two-sided statistic is signed.
109Cook/independent filtering can produce missing p-values/adjusted p-values.
111`lfc_shrink(coeff, adapt=True)` selects a **single column name** from the LFC
112matrix and uses an apeGLM-style heavy-tailed prior. It mutates `ds.LFC`, `ds.SE`,
113and the table's `log2FoldChange` and `lfcSE`, keeping existing `stat`, `pvalue`,
114and `padj`. The source writes the selected coefficient to the table even when
115it differs from the original contrast. Check that the exact contrast is the
116positive unit vector for that coefficient, or relevel/refit/use unshrunk results.
117NaN/infinite shrinkage estimates can leave individual original estimates in place;
118inspect warnings and `_LFC_shrink_converged` instead of assuming universal success.

DeseqStats

from pydeseq2.ds import DeseqStats

ds = DeseqStats(dds, contrast=['condition', 'treated', 'control'], alpha=0.05,
                cooks_filter=True, independent_filter=True, n_cpus=1)
ds.summary()

contrast is mandatory: a three-string list [factor, numerator, denominator] or a 1D NumPy vector with one entry per design column. Check finite entries, nonzero contrast and biological estimability. Numeric vectors should be NumPy arrays, not numeric Python lists interpreted as factor contrasts.

lfc_null=0.0 is in log2 units. alt_hypothesis=None gives the usual two-sided Wald test. 'greaterAbs', 'lessAbs', 'greater', and 'less' specify different alternatives; choose deliberately. summary(lfc_null=..., alt_hypothesis=...) can replace the hypothesis and rerun testing, but do so on an unshrunken object. prior_LFC_var is an optional ridge prior and is distinct from apeGLM shrinkage.

summary() updates results_df with baseMean, log2FoldChange, lfcSE, stat, pvalue, and padj. baseMean is the mean normalized count across all samples, not either condition's mean. Original LFC and SE are log2 values; stat is dimensionless. The usual zero-null two-sided statistic is signed. Cook/independent filtering can produce missing p-values/adjusted p-values.

lfc_shrink(coeff, adapt=True) selects a single column name from the LFC matrix and uses an apeGLM-style heavy-tailed prior. It mutates ds.LFC, ds.SE, and the table's log2FoldChange and lfcSE, keeping existing stat, pvalue, and padj. The source writes the selected coefficient to the table even when it differs from the original contrast. Check that the exact contrast is the positive unit vector for that coefficient, or relevel/refit/use unshrunk results. NaN/infinite shrinkage estimates can leave individual original estimates in place; inspect warnings and _LFC_shrink_converged instead of assuming universal success.

Raw lines 84 to 119
120## Preprocessing and upstream example data
122`pydeseq2.preprocessing` provides `deseq2_norm(counts)` returning
123`(normalized_counts, size_factors)`, plus `deseq2_norm_fit(counts)` and
124`deseq2_norm_transform(counts, logmeans, filtered_genes)`. It does not perform the
125skill's manual sample exclusions or gene prefilter. Its ratio-only utilities do
126not automatically select an alternative method when geometric means are unusable.
128```python
129from pydeseq2.utils import load_example_data
131example_counts = load_example_data(modality='raw_counts', dataset='synthetic', debug=False)
132example_metadata = load_example_data(modality='metadata', dataset='synthetic', debug=False)
133```
135Each call returns **one DataFrame**, not a tuple. With no packaged `datasets/`
136directory, 0.5.4 downloads public CSVs using unauthenticated GET from
137`https://raw.githubusercontent.com/owkin/PyDESeq2/main/datasets/synthetic/`
138(`test_counts.csv` or `test_metadata.csv`; source inserts an extra slash).
139There is no request body, API version, token or pagination. It transposes the
140count CSV. This moving `main` data source is unsuitable as a pinned benchmark;
141retain a versioned fixture/checksum for reproducibility. `debug=True` is unreliable
142for raw counts in this release: the source tries to sample 100 rows after first
143sampling ten. Use `debug=False` and subset both modalities explicitly if needed.
145No hosted analysis service or authenticated scientific endpoint is needed for a
146local fit. Network example loading is a tiny public-data check, not a validation
147of a scientific dataset or remote computation.

Preprocessing and upstream example data

pydeseq2.preprocessing provides deseq2_norm(counts) returning (normalized_counts, size_factors), plus deseq2_norm_fit(counts) and deseq2_norm_transform(counts, logmeans, filtered_genes). It does not perform the skill's manual sample exclusions or gene prefilter. Its ratio-only utilities do not automatically select an alternative method when geometric means are unusable.

from pydeseq2.utils import load_example_data

example_counts = load_example_data(modality='raw_counts', dataset='synthetic', debug=False)
example_metadata = load_example_data(modality='metadata', dataset='synthetic', debug=False)

Each call returns one DataFrame, not a tuple. With no packaged datasets/ directory, 0.5.4 downloads public CSVs using unauthenticated GET from https://raw.githubusercontent.com/owkin/PyDESeq2/main/datasets/synthetic/ (test_counts.csv or test_metadata.csv; source inserts an extra slash). There is no request body, API version, token or pagination. It transposes the count CSV. This moving main data source is unsuitable as a pinned benchmark; retain a versioned fixture/checksum for reproducibility. debug=True is unreliable for raw counts in this release: the source tries to sample 100 rows after first sampling ten. Use debug=False and subset both modalities explicitly if needed.

No hosted analysis service or authenticated scientific endpoint is needed for a local fit. Network example loading is a tiny public-data check, not a validation of a scientific dataset or remote computation.

Raw lines 120 to 148
149## Sources
151- [Official dataset API](https://pydeseq2.readthedocs.io/en/stable/api/docstrings/pydeseq2.dds.DeseqDataSet.html)
152- [Official statistics API](https://pydeseq2.readthedocs.io/en/stable/api/docstrings/pydeseq2.ds.DeseqStats.html)
153- [Release metadata and requirements](https://pydeseq2.readthedocs.io/en/stable/usage/requirements.html)
154- [Tagged dataset implementation](https://github.com/scverse/PyDESeq2/blob/v0.5.4/pydeseq2/dds.py)
155- [Tagged statistics implementation](https://github.com/scverse/PyDESeq2/blob/v0.5.4/pydeseq2/ds.py)
156- [Tagged utilities and example loader](https://github.com/scverse/PyDESeq2/blob/v0.5.4/pydeseq2/utils.py)
157- [Tagged preprocessing](https://github.com/scverse/PyDESeq2/blob/v0.5.4/pydeseq2/preprocessing.py)