Leave-one-cohort-out survival-signature benchmarking with built-in leakage audits (fully nested re-selection, permutation calibration, size-matched random-panel nulls), extracted from a nine-cohort breast-cancer gene-signature study.
Project description
survaudit
Leave-one-cohort-out (LOCO) survival-signature benchmarking with built-in leakage audits — fully nested re-selection, permutation calibration of a forward search, and size-matched random-panel nulls — extracted from a nine-cohort breast-cancer gene-signature study (five-gene panel vs. PAM50, MammaPrint, Oncotype DX, the genomic grade index, and the Buffa hypoxia metagene).
The numerics (ridge-penalised Cox via Newton-Raphson, Breslow ties, numba-JIT;
Harrell's concordance) are implemented from scratch and validated against
scikit-survival; see survaudit.core.validate_against_sksurv.
Install
pip install survaudit
# figures need matplotlib, some sensitivity analyses need lifelines/statsmodels:
pip install "survaudit[all]"
Quickstart: harmonise your own cohort, then fit and evaluate
survaudit expects one expression matrix (genes x samples) and one clinical
table (one row per sample) per cohort. harmonise_cohort converts these into
the on-disk schema (<cohort>_expr.parquet, <cohort>_surv.parquet) that
every other function reads, doing per-gene z-scoring within the cohort
(never pooled across cohorts — this is what makes leave-one-cohort-out
evaluation meaningful) and normalising follow-up time/event coding along the
way.
import pandas as pd
from survaudit import harmonise_cohort, load_cohort, load_all, fit_ridge_cox, cindex
expr = pd.read_csv("my_expression.tsv", sep="\t", index_col="hugo_symbol") # genes x samples
clin = pd.read_csv("my_clinical.tsv", sep="\t") # one row per sample
cfg = dict(
sample_col="sample_id", time_col="os_months", event_col="os_event",
endpoint="OS", platform="RNA-seq", scale="linear", # "zscored" | "log2" | "linear"
cov=dict(age="age", grade=None, size=None, node=None, stage=None,
er=None, pr=None, subtype=None), # None where you don't have it
)
qc_row = harmonise_cohort("MyCohort", cfg, expr, clin, out_dir="./harmonised")
print(qc_row) # n, events, event_rate, median_fu_months, n_genes, join diagnostics
# Load it back (or several cohorts at once) and fit the same validated model:
store = load_all(["MyCohort"], data_dir="./harmonised")
X, t, ev, genes = store["MyCohort"]
panel = ["FLT3", "CLIC6", "SUSD3", "ZIC2", "P4HA2"] # or your own gene list
beta = fit_ridge_cox(X[panel].values, t, ev, alpha=100.0)
risk = X[panel].values @ beta
print("concordance:", cindex(risk, t, ev))
If you have raw files on disk rather than loaded DataFrames, use
harmonise_cohort_from_files(name, cfg, data_dir, out_dir) with cfg["expr"]
/cfg["clin"] set to paths relative to data_dir (this is what
harmonise_all does internally, looping a COHORTS registry — see
survaudit.harmonise.COHORTS for a fully worked example of that registry, the
nine cohorts this package was built from).
The audits, as a library or a CLI
Every analysis stage from the original study — fully nested re-selection,
permutation calibration, size-matched nulls, the LOCO benchmark grid across
four learners, decision-curve/likelihood-ratio incremental-value tests,
figure and table generation — ships as one importable, side-effect-free module
under survaudit.pipeline, runnable exactly as it was written (reads its
inputs and writes its outputs relative to the current directory):
survaudit --list # show every available stage
survaudit harmonise # OUT=./harmonised python -m survaudit.pipeline...
survaudit run_nested_selection # writes nested_selection_*.csv/.json here
survaudit run_permutation_search 1000 0
survaudit make_tables # regenerate paper/tabN_*.tex from results/
equivalently python -m survaudit.pipeline.run_nested_selection. Each
module's docstring documents what it reads and writes; several were written
for a specific nine-cohort study and assume gene sets / cohort names from that
study by default (survaudit.core.NOVEL5, OS6, SEC3) — override those
where the stage exposes them as arguments, or adapt the module for your own
gene sets (they are ordinary, short, readable Python scripts).
What's validated, what's a starting point
survaudit.core (the Cox fitting, concordance, and the fully-nested
re-selection / candidate-pool / forward-search primitives) and
survaudit.harmonise (cohort ingestion) are the reusable engine and are
covered by validate_against_sksurv plus a byte-identical round-trip check
against the original study's nine harmonised cohorts. survaudit.pipeline.*
are faithful extractions of that study's specific analysis scripts — useful as
a worked, runnable reference for how to wire the engine into a leakage audit
on your own data, but written for that study's cohort names, gene sets, and
directory layout, not yet generalised into a parametrised API.
License
MIT (see LICENSE).
Project details
Release history Release notifications | RSS feed
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 survaudit-0.1.0.tar.gz.
File metadata
- Download URL: survaudit-0.1.0.tar.gz
- Upload date:
- Size: 160.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e838527bee19c32b20203c00180e0e11bafde9267e54ef53ae9daff3b6835ab3
|
|
| MD5 |
6f853343b8d90d68b47fd752394a11b7
|
|
| BLAKE2b-256 |
6af4253fa69485f75a25d490378ff3c84e8757542d38edd9a974e2e3f90d501b
|
File details
Details for the file survaudit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: survaudit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 194.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.13.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa36347ace1be2eeda3dcd6f218c2a0fc0042d1472e364ab15e2068d9e11fbf1
|
|
| MD5 |
6d45ede0accb6ca2f9e62e969ea18d8f
|
|
| BLAKE2b-256 |
b2a409bbc0a6a60f7e6bd1490176cb196ad3f59175f9b91b4e45296a55588669
|