survival-model-toolkit 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kaylee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.4
2
+ Name: survival-model-toolkit
3
+ Version: 0.1.0
4
+ Summary: Shared helpers and analysis steps for a competing-risk-aware Cox survival modelling pipeline: persisted splits, preprocessing fit on training data only, discrimination/calibration metrics, PH diagnostics, and model-comparison utilities.
5
+ Author: Kaylee
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://pypi.org/project/survival-model-toolkit/
8
+ Keywords: survival-analysis,cox-model,calibration,concordance-index,competing-risks,biostatistics
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
12
+ Classifier: Intended Audience :: Science/Research
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: numpy>=1.23
17
+ Requires-Dist: pandas>=1.5
18
+ Requires-Dist: scipy>=1.9
19
+ Requires-Dist: scikit-learn>=1.1
20
+ Requires-Dist: scikit-survival>=0.19
21
+ Requires-Dist: lifelines>=0.27
22
+ Requires-Dist: patsy>=0.5
23
+ Requires-Dist: matplotlib>=3.5
24
+ Requires-Dist: shap-recommender>=0.2.0
25
+ Requires-Dist: competing-risk-sensitivity>=0.1.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # survival-model-toolkit
31
+
32
+ Shared helpers and analysis steps for a competing-risk-aware Cox survival
33
+ modelling pipeline: a persisted train/test split (so multiple scripts never
34
+ silently diverge), preprocessing fitted on training data only, discrimination
35
+ and calibration metrics with bootstrap intervals, proportional-hazards
36
+ diagnostics, descriptive/reporting tables, and a set of higher-level analysis
37
+ steps for comparing models and validating design choices.
38
+
39
+ This package builds on two separately published, more narrowly scoped
40
+ packages rather than duplicating their logic:
41
+
42
+ - [`shap-recommender`](https://pypi.org/project/shap-recommender/) --
43
+ exclusion / non-linearity / interaction recommendations from SHAP
44
+ attributions.
45
+ - [`competing-risk-sensitivity`](https://pypi.org/project/competing-risk-sensitivity/) --
46
+ Aalen-Johansen cumulative incidence and Fine-Gray export for a competing
47
+ event such as death.
48
+
49
+ ## Install
50
+
51
+ ```bash
52
+ pip install survival-model-toolkit
53
+ ```
54
+
55
+ ## What's inside
56
+
57
+ **Splitting and preprocessing**
58
+
59
+ - `make_or_load_split` -- one train/test partition, persisted to disk, so
60
+ every script that loads it sees an identical partition.
61
+ - `temporal_split` -- a temporal (index-date cutoff) split, for a
62
+ sensitivity analysis closer to deployment than a random split.
63
+ - `build_preprocessor` -- one-hot or ordinal encoding, fitted on the
64
+ training subset only; continuous variables are left on their natural scale
65
+ by default so hazard ratios and SHAP attributions stay in interpretable
66
+ units.
67
+ - `NonlinearTransform` -- quadratic or restricted-cubic-spline expansion,
68
+ fit on train and replayed unchanged on test.
69
+ - `add_interactions` -- hierarchy-aware pairwise products: a pair whose
70
+ main effect was dropped is skipped and logged, not silently omitted.
71
+ - `onehot_group_map` / `aggregate_shap` -- map a one-hot-encoded feature's
72
+ dummy columns back to a single SHAP attribution.
73
+
74
+ **Discrimination and calibration**
75
+
76
+ - `cox_risk_score` / `batch_risk_scores` -- a scalar risk ordering for any
77
+ fitted model exposing `decision_function`, `predict`, or
78
+ `predict_partial_hazard`.
79
+ - `MetricEval` -- Harrell's C with a genuine bootstrap CI (every replicate
80
+ resamples the observations, rather than rescoring a fixed test set), Uno's
81
+ C, time-dependent AUC, Brier score / IBS, and a paired bootstrap for the
82
+ difference between two models' C-index.
83
+ - `CalibrationPerform` -- binned observed-vs-predicted calibration at a
84
+ fixed horizon with bootstrap CIs per bin, the conventional calibration
85
+ slope, an overlay plot across models, and an operational "is calibration
86
+ stable" check (95% CI of the slope contains 1).
87
+
88
+ **Diagnostics and descriptive tables**
89
+
90
+ - `ph_assumption_report` -- global and per-term Schoenfeld residual tests.
91
+ - `table1_with_smd` -- baseline characteristics with standardised mean
92
+ differences between groups.
93
+ - `incidence_by_group` -- crude incidence per 1,000 person-years with exact
94
+ Poisson intervals.
95
+ - `design_report` -- design-matrix dimensionality and events-per-parameter.
96
+ - `export_coefficients` -- hazard ratios with CIs for a fitted
97
+ scikit-survival Cox model (obtained via a matched lifelines refit, since
98
+ scikit-survival itself has no covariance matrix).
99
+ - `competing_risk_report` / `finegray_export` -- thin wrappers around
100
+ `competing-risk-sensitivity`.
101
+
102
+ **Pipeline steps**
103
+
104
+ - `discovery_confirmation_split` / `joint_lrt` -- screen candidate terms on
105
+ one half of the data, confirm them jointly on the other.
106
+ - `fit_and_score` / `comparator_models` -- fit-and-report a Cox model, plus
107
+ two useful comparators (restricted cubic splines; a penalised all-pairs
108
+ interaction model).
109
+ - `sequential_ablation` -- C-index after each pipeline component, under
110
+ every ordering.
111
+ - `subgroup_performance` -- discrimination within subgroups (e.g. for a
112
+ fairness/equity audit).
113
+ - `interaction_dose_response` / `plot_dose_response` -- refit after adding
114
+ the top-N interactions (ranked by effect size) for a grid of N, so the
115
+ number admitted is chosen by held-out discrimination.
116
+ - `margin_sensitivity_cindex` -- regenerate recommendations at several
117
+ subgroup margins and refit, reporting the margin's effect on
118
+ discrimination.
119
+
120
+ ## Example
121
+
122
+ ```python
123
+ from survival_model_toolkit import (
124
+ make_or_load_split, build_preprocessor, MetricEval, CalibrationPerform,
125
+ cox_risk_score,
126
+ )
127
+ from sksurv.linear_model import CoxPHSurvivalAnalysis
128
+
129
+ X_train, X_test, y_train, y_test = make_or_load_split(X, y, path="split.json")
130
+
131
+ pre = build_preprocessor(onehot_cols=["sex"], contin_cols=["age"]).fit(X_train)
132
+ X_train_t, X_test_t = pre.transform(X_train), pre.transform(X_test)
133
+
134
+ model = CoxPHSurvivalAnalysis(alpha=1e-6, ties="efron").fit(X_train_t, y_train)
135
+
136
+ evaluator = MetricEval()
137
+ c, (lo, hi) = evaluator.boot_metric(y_test, cox_risk_score(model, X_test_t))
138
+ print(f"C-index = {c:.3f} (95% CI {lo:.3f}-{hi:.3f})")
139
+
140
+ calib = CalibrationPerform(t0=365.0)
141
+ print(calib.report(model, X_test_t, y_test, label="cox"))
142
+ ```
143
+
144
+ ## License
145
+
146
+ MIT
@@ -0,0 +1,117 @@
1
+ # survival-model-toolkit
2
+
3
+ Shared helpers and analysis steps for a competing-risk-aware Cox survival
4
+ modelling pipeline: a persisted train/test split (so multiple scripts never
5
+ silently diverge), preprocessing fitted on training data only, discrimination
6
+ and calibration metrics with bootstrap intervals, proportional-hazards
7
+ diagnostics, descriptive/reporting tables, and a set of higher-level analysis
8
+ steps for comparing models and validating design choices.
9
+
10
+ This package builds on two separately published, more narrowly scoped
11
+ packages rather than duplicating their logic:
12
+
13
+ - [`shap-recommender`](https://pypi.org/project/shap-recommender/) --
14
+ exclusion / non-linearity / interaction recommendations from SHAP
15
+ attributions.
16
+ - [`competing-risk-sensitivity`](https://pypi.org/project/competing-risk-sensitivity/) --
17
+ Aalen-Johansen cumulative incidence and Fine-Gray export for a competing
18
+ event such as death.
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install survival-model-toolkit
24
+ ```
25
+
26
+ ## What's inside
27
+
28
+ **Splitting and preprocessing**
29
+
30
+ - `make_or_load_split` -- one train/test partition, persisted to disk, so
31
+ every script that loads it sees an identical partition.
32
+ - `temporal_split` -- a temporal (index-date cutoff) split, for a
33
+ sensitivity analysis closer to deployment than a random split.
34
+ - `build_preprocessor` -- one-hot or ordinal encoding, fitted on the
35
+ training subset only; continuous variables are left on their natural scale
36
+ by default so hazard ratios and SHAP attributions stay in interpretable
37
+ units.
38
+ - `NonlinearTransform` -- quadratic or restricted-cubic-spline expansion,
39
+ fit on train and replayed unchanged on test.
40
+ - `add_interactions` -- hierarchy-aware pairwise products: a pair whose
41
+ main effect was dropped is skipped and logged, not silently omitted.
42
+ - `onehot_group_map` / `aggregate_shap` -- map a one-hot-encoded feature's
43
+ dummy columns back to a single SHAP attribution.
44
+
45
+ **Discrimination and calibration**
46
+
47
+ - `cox_risk_score` / `batch_risk_scores` -- a scalar risk ordering for any
48
+ fitted model exposing `decision_function`, `predict`, or
49
+ `predict_partial_hazard`.
50
+ - `MetricEval` -- Harrell's C with a genuine bootstrap CI (every replicate
51
+ resamples the observations, rather than rescoring a fixed test set), Uno's
52
+ C, time-dependent AUC, Brier score / IBS, and a paired bootstrap for the
53
+ difference between two models' C-index.
54
+ - `CalibrationPerform` -- binned observed-vs-predicted calibration at a
55
+ fixed horizon with bootstrap CIs per bin, the conventional calibration
56
+ slope, an overlay plot across models, and an operational "is calibration
57
+ stable" check (95% CI of the slope contains 1).
58
+
59
+ **Diagnostics and descriptive tables**
60
+
61
+ - `ph_assumption_report` -- global and per-term Schoenfeld residual tests.
62
+ - `table1_with_smd` -- baseline characteristics with standardised mean
63
+ differences between groups.
64
+ - `incidence_by_group` -- crude incidence per 1,000 person-years with exact
65
+ Poisson intervals.
66
+ - `design_report` -- design-matrix dimensionality and events-per-parameter.
67
+ - `export_coefficients` -- hazard ratios with CIs for a fitted
68
+ scikit-survival Cox model (obtained via a matched lifelines refit, since
69
+ scikit-survival itself has no covariance matrix).
70
+ - `competing_risk_report` / `finegray_export` -- thin wrappers around
71
+ `competing-risk-sensitivity`.
72
+
73
+ **Pipeline steps**
74
+
75
+ - `discovery_confirmation_split` / `joint_lrt` -- screen candidate terms on
76
+ one half of the data, confirm them jointly on the other.
77
+ - `fit_and_score` / `comparator_models` -- fit-and-report a Cox model, plus
78
+ two useful comparators (restricted cubic splines; a penalised all-pairs
79
+ interaction model).
80
+ - `sequential_ablation` -- C-index after each pipeline component, under
81
+ every ordering.
82
+ - `subgroup_performance` -- discrimination within subgroups (e.g. for a
83
+ fairness/equity audit).
84
+ - `interaction_dose_response` / `plot_dose_response` -- refit after adding
85
+ the top-N interactions (ranked by effect size) for a grid of N, so the
86
+ number admitted is chosen by held-out discrimination.
87
+ - `margin_sensitivity_cindex` -- regenerate recommendations at several
88
+ subgroup margins and refit, reporting the margin's effect on
89
+ discrimination.
90
+
91
+ ## Example
92
+
93
+ ```python
94
+ from survival_model_toolkit import (
95
+ make_or_load_split, build_preprocessor, MetricEval, CalibrationPerform,
96
+ cox_risk_score,
97
+ )
98
+ from sksurv.linear_model import CoxPHSurvivalAnalysis
99
+
100
+ X_train, X_test, y_train, y_test = make_or_load_split(X, y, path="split.json")
101
+
102
+ pre = build_preprocessor(onehot_cols=["sex"], contin_cols=["age"]).fit(X_train)
103
+ X_train_t, X_test_t = pre.transform(X_train), pre.transform(X_test)
104
+
105
+ model = CoxPHSurvivalAnalysis(alpha=1e-6, ties="efron").fit(X_train_t, y_train)
106
+
107
+ evaluator = MetricEval()
108
+ c, (lo, hi) = evaluator.boot_metric(y_test, cox_risk_score(model, X_test_t))
109
+ print(f"C-index = {c:.3f} (95% CI {lo:.3f}-{hi:.3f})")
110
+
111
+ calib = CalibrationPerform(t0=365.0)
112
+ print(calib.report(model, X_test_t, y_test, label="cox"))
113
+ ```
114
+
115
+ ## License
116
+
117
+ MIT
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "survival-model-toolkit"
7
+ version = "0.1.0"
8
+ description = "Shared helpers and analysis steps for a competing-risk-aware Cox survival modelling pipeline: persisted splits, preprocessing fit on training data only, discrimination/calibration metrics, PH diagnostics, and model-comparison utilities."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ { name = "Kaylee" },
15
+ ]
16
+ keywords = ["survival-analysis", "cox-model", "calibration", "concordance-index", "competing-risks", "biostatistics"]
17
+ classifiers = [
18
+ "Programming Language :: Python :: 3",
19
+ "Operating System :: OS Independent",
20
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
21
+ "Intended Audience :: Science/Research",
22
+ ]
23
+ dependencies = [
24
+ "numpy>=1.23",
25
+ "pandas>=1.5",
26
+ "scipy>=1.9",
27
+ "scikit-learn>=1.1",
28
+ "scikit-survival>=0.19",
29
+ "lifelines>=0.27",
30
+ "patsy>=0.5",
31
+ "matplotlib>=3.5",
32
+ "shap-recommender>=0.2.0",
33
+ "competing-risk-sensitivity>=0.1.0",
34
+ ]
35
+
36
+ [project.optional-dependencies]
37
+ dev = ["pytest"]
38
+
39
+ [project.urls]
40
+ Homepage = "https://pypi.org/project/survival-model-toolkit/"
41
+
42
+ [tool.setuptools.packages.find]
43
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,89 @@
1
+ """survival_model_toolkit: shared helpers for a competing-risk-aware Cox
2
+ survival analysis pipeline -- a persisted train/test split, preprocessing
3
+ fitted on training data only, discrimination and calibration metrics,
4
+ proportional-hazards diagnostics, descriptive/reporting tables, and a set of
5
+ higher-level analysis steps (model comparators, sequential ablation,
6
+ subgroup discrimination, an interaction dose-response curve, and a subgroup-
7
+ margin sensitivity analysis).
8
+
9
+ Builds on the separately published `shap-recommender` (exclusion /
10
+ non-linearity / interaction recommendations from SHAP attributions) and
11
+ `competing-risk-sensitivity` (Aalen-Johansen CIF / Fine-Gray export)
12
+ packages rather than duplicating their logic.
13
+ """
14
+
15
+ from .core import (
16
+ BMI_LEGEND,
17
+ DATA_DIR,
18
+ DRUG_LOOKBACK_DAYS,
19
+ FOLLOWUP_YEARS,
20
+ N_BOOT,
21
+ RANDOM_STATE,
22
+ REC_DIR,
23
+ RESULT_DIR,
24
+ SPLIT_PATH,
25
+ T0_DAYS,
26
+ CalibrationPerform,
27
+ MetricEval,
28
+ NonlinearTransform,
29
+ add_interactions,
30
+ aggregate_shap,
31
+ anchored_pattern,
32
+ batch_risk_scores,
33
+ build_preprocessor,
34
+ categorize_BMI,
35
+ competing_risk_report,
36
+ cox_risk_score,
37
+ dedup_codes,
38
+ design_report,
39
+ ensure_dirs,
40
+ export_coefficients,
41
+ feature_num_counts,
42
+ finegray_export,
43
+ incidence_by_group,
44
+ make_or_load_split,
45
+ merge_group_time_interval,
46
+ onehot_group_map,
47
+ parse_mixed_datetime,
48
+ ph_assumption_report,
49
+ read_tsv,
50
+ seldata_path,
51
+ shap_path,
52
+ substract_interval,
53
+ table1_with_smd,
54
+ temporal_split,
55
+ unify_disease_name,
56
+ write_tsv,
57
+ )
58
+ from .pipeline import (
59
+ comparator_models,
60
+ discovery_confirmation_split,
61
+ fit_and_score,
62
+ interaction_dose_response,
63
+ joint_lrt,
64
+ margin_sensitivity_cindex,
65
+ plot_dose_response,
66
+ sequential_ablation,
67
+ subgroup_performance,
68
+ )
69
+
70
+ __version__ = "0.1.0"
71
+
72
+ __all__ = [
73
+ "BMI_LEGEND", "DATA_DIR", "DRUG_LOOKBACK_DAYS", "FOLLOWUP_YEARS", "N_BOOT",
74
+ "RANDOM_STATE", "REC_DIR", "RESULT_DIR", "SPLIT_PATH", "T0_DAYS",
75
+ "CalibrationPerform", "MetricEval", "NonlinearTransform",
76
+ "add_interactions", "aggregate_shap", "anchored_pattern",
77
+ "batch_risk_scores", "build_preprocessor", "categorize_BMI",
78
+ "competing_risk_report", "cox_risk_score", "dedup_codes", "design_report",
79
+ "ensure_dirs", "export_coefficients", "feature_num_counts",
80
+ "finegray_export", "incidence_by_group", "make_or_load_split",
81
+ "merge_group_time_interval", "onehot_group_map", "parse_mixed_datetime",
82
+ "ph_assumption_report", "read_tsv", "seldata_path", "shap_path",
83
+ "substract_interval", "table1_with_smd", "temporal_split",
84
+ "unify_disease_name", "write_tsv",
85
+ "comparator_models", "discovery_confirmation_split", "fit_and_score",
86
+ "interaction_dose_response", "joint_lrt", "margin_sensitivity_cindex",
87
+ "plot_dose_response", "sequential_ablation", "subgroup_performance",
88
+ "__version__",
89
+ ]