I released pbcheck 0.1.0, a Python package and command-line tool that audits a single-cell RNA-seq differential-expression design for pseudoreplication.
You give it one .h5ad file, the donor and condition columns, and the two condition levels. It checks the design first: donor nesting within condition, donors per group, and whether a batch column separates the conditions. If a donor appears under both conditions it stops there, rather than running a test that treats two halves of one person as two people.
If the design allows it, pbcheck runs a naive per-cell test and a donor-pseudobulk test on the same frozen gene universe, then repeats both with donor labels shuffled between conditions. It reports each arm’s permutation floor, how far the real-label result sits above that floor, and genomic inflation (lambda) as a separate summary. Output is JSON, Markdown and a standalone HTML page.
A separate pre-registered measurement study is still in progress; the report pbcheck writes is descriptive and carries its caveats in the text, and it makes no claim about that study.
The pseudobulk arm’s stated limit, in the tool’s own words:
Amendment 3 declares an operating envelope for the pseudobulk arm on synthetic oracles. For each donor-variance point it states the donor count per group at which the power target is reached, and each row says what the committed grid supports there: a point measured on the grid, or a count derived or extrapolated from it.
[the four envelope rows, one per sigma_donor value, are left out here; the report prints them]
The arm’s calibration was evaluated at one hard regime (sigma_donor 0.5, 8 against 8 donors) and nowhere else. pbcheck does not estimate sigma_donor for real data, so whether this stratum lies inside that envelope is not determined here.
Two demonstrations are committed under demo/. On Kang et al. 2018 (IFN-beta stimulation, every donor measured under both conditions) pbcheck stops at the design audit, and that stop is the demonstration. The two-arm run is on the package’s own synthetic reference dataset: the public Stephenson et al. 2021 artifact I tried first carries no raw counts anywhere, and pbcheck refuses a non-count matrix rather than rounding it.
Tell me where the report wording confused you.
pip install pbcheck