scib-validity
Construct validity diagnostics for single-cell embedding evaluation metrics. CKA null saturation bounds and source classifier confidence (SCC).
Install
pip install scib-validity
Quick start
from scib_validity import scc, cka_null, cka_certifiable
# Is CKA informative at your dimensionality?
print(cka_null(k=15, d=512)) # 0.973 -- null floor
print(cka_certifiable(0.95, 15, 512)) # False -- below random
# SCC: does the source classifier transfer?
score = scc(X_source, X_target, labels_source, labels_target)
print(f"SCC = {score:.3f}")
The problem
CKA on cell-type centroids exhibits null saturation: its analytic expectation under a Gaussian null,
$$\mathbb{E}[\text{CKA}] \approx 1 - 1.06 \cdot \frac{k-1}{d+k}$$
exceeds every trained-model CKA score at foundation-model dimensionality (d >= 512). At d = 50, 86% of conditions clear the null; at d >= 512, none do.
Five relational consistency score variants avoid null saturation yet predict cross-technology transfer only marginally (rho <= 0.25).
The alternative
Source classifier confidence (SCC) trains a cell-type classifier on source embeddings and reports the mean maximum predicted probability on target cells. It directly measures whether learned decision boundaries transfer.
| Classifier | Key | Spearman rho with transfer F1 |
|---|---|---|
| Logistic regression | "logreg" |
0.67 |
| k-nearest neighbors | "knn" |
0.56 |
| Random forest | "rf" |
0.57 |
| Support vector machine | "svm" |
0.55 |
All four pass Benjamini-Hochberg correction across 23 human tissues and 92 embedding conditions in CELLxGENE Census.
API
scc(X_source, X_target, labels_source, labels_target=None, shared_types=None, classifier="logreg", seed=0)
Returns the mean maximum predicted probability of a source-trained classifier applied to target cells.
scc_multi(X_source, X_target, labels_source, ...)
Returns a dict mapping classifier name to SCC score across all four families.
cka_null(k, d)
Returns the analytic expected CKA between independent Gaussian centroid matrices.
cka_certifiable(observed_cka, k, d, margin=0.0)
Returns True if the observed CKA exceeds the null floor.
Cross-classifier stress test
from scib_validity import scc_multi
scores = scc_multi(X_source, X_target, labels_source, labels_target)
# {'logreg': 0.87, 'knn': 0.82, 'rf': 0.84, 'svm': 0.85}
Running SCC with multiple classifier families rules out shared-machinery confounding. If all classifiers agree, the signal is an embedding-space property.
Empirical CKA null
Verify the closed-form bound against Monte Carlo simulation:
from scib_validity.metrics.cka_null import cka_null_empirical
empirical = cka_null_empirical(k=15, d=512, n_trials=5000)
print(f"Empirical mean: {empirical['mean']:.4f}")
print(f"Analytic bound: {cka_null(15, 512):.4f}")
Citation
@software{tower2026scib_validity,
author = {Tower, Elliot},
title = {Construct Validity Failure in Single-Cell Embedding Evaluation},
year = {2026},
url = {https://github.com/elliottower/scib-construct-validity},
license = {MIT}
}
License
MIT
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 scib_validity-0.3.0.tar.gz.
File metadata
- Download URL: scib_validity-0.3.0.tar.gz
- Upload date:
- Size: 2.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f7130c493855de1b1cecc3c111ee05795308d134e71bafc88421129efa59e95
|
|
| MD5 |
757e2cb9477df93eeb374b2161535dd4
|
|
| BLAKE2b-256 |
e504c3fffeb2ba4979e79afcc93121e72ac5f60fa06790ebf18db2196673721d
|
Provenance
The following attestation bundles were made for scib_validity-0.3.0.tar.gz:
Publisher:
publish.yml on elliottower/scib-construct-validity
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scib_validity-0.3.0.tar.gz -
Subject digest:
6f7130c493855de1b1cecc3c111ee05795308d134e71bafc88421129efa59e95 - Sigstore transparency entry: 2500312801
- Sigstore integration time:
-
Permalink:
elliottower/scib-construct-validity@d8a2cd40b81093f381ba80e7dd30f89dbf70c339 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/elliottower
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d8a2cd40b81093f381ba80e7dd30f89dbf70c339 -
Trigger Event:
release
-
Statement type:
File details
Details for the file scib_validity-0.3.0-py3-none-any.whl.
File metadata
- Download URL: scib_validity-0.3.0-py3-none-any.whl
- Upload date:
- Size: 7.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
383107999752bdc93afc57cfeedc476cb9bb17ff57fe25cdfc36c8c69379e26e
|
|
| MD5 |
b81d83994c744f2d39a15a3007e7576c
|
|
| BLAKE2b-256 |
5589f26e0d6c032dadad44d53e5198e560ae95c8a4fd8b619f2bc505934f2fe4
|
Provenance
The following attestation bundles were made for scib_validity-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on elliottower/scib-construct-validity
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scib_validity-0.3.0-py3-none-any.whl -
Subject digest:
383107999752bdc93afc57cfeedc476cb9bb17ff57fe25cdfc36c8c69379e26e - Sigstore transparency entry: 2500312814
- Sigstore integration time:
-
Permalink:
elliottower/scib-construct-validity@d8a2cd40b81093f381ba80e7dd30f89dbf70c339 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/elliottower
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@d8a2cd40b81093f381ba80e7dd30f89dbf70c339 -
Trigger Event:
release
-
Statement type: