from __future__ import annotations import json from dataclasses import asdict from pathlib import Path from sepsis_mcp.gossis_experiment import GossisRunConfig from sepsis_mcp.mimic4_experiment import Mimic4RunConfig from sepsis_mcp.modeling import ProbabilityEstimator, QuantileRegressionEstimator, RegressionEstimator def _pipeline_terminal_params(estimator) -> dict[str, object]: model = getattr(estimator, "model", estimator) if hasattr(model, "named_steps"): terminal = list(model.named_steps.values())[-1] return terminal.get_params() return model.get_params() def render_implementation_details() -> str: gossis_defaults = asdict(GossisRunConfig(data_root=Path("."), output_dir=Path("outputs/gossis-hospital"))) mimic_defaults = asdict(Mimic4RunConfig(csv_path=Path("mimic.csv"), output_dir=Path("outputs/mimic4-validation"))) classifier_defaults = { "logistic_regression": _pipeline_terminal_params(ProbabilityEstimator(model_type="logistic_regression")), "mlp": _pipeline_terminal_params(ProbabilityEstimator(model_type="mlp")), "xgboost": _pipeline_terminal_params(ProbabilityEstimator(model_type="xgboost")), } regression_defaults = { "ridge_regression": _pipeline_terminal_params(RegressionEstimator(model_type="ridge_regression")), "sklearn_gbdt": _pipeline_terminal_params(RegressionEstimator(model_type="sklearn_gbdt")), "cqr_xgboost": _pipeline_terminal_params(QuantileRegressionEstimator(model_type="xgboost", quantile=0.95)), } return "\n".join( [ "# Implementation Details", "", "## GOSSIS Classification Defaults", "", "```json", json.dumps(gossis_defaults, indent=2, default=str), "```", "", "## MIMIC-IV Validation Defaults", "", "```json", json.dumps(mimic_defaults, indent=2, default=str), "```", "", "## Base Model Hyperparameters", "", "### Classification", "", "```json", json.dumps(classifier_defaults, indent=2, default=str), "```", "", "### Regression / CQR", "", "```json", json.dumps(regression_defaults, indent=2, default=str), "```", "", "## Split and Seed Protocol", "", "- GOSSIS uses hospital-disjoint splits with optional selection hospitals when `selection_fraction > 0`.", "- MIMIC-IV uses leave-one-care-unit-out assignments with `rotations` train/selection/calibration rotations per held-out unit.", "- Random seeds are passed through the run config and sweep grids; appendix sweeps report per-seed outputs and repeated summaries.", "", "## Conformity Scores", "", "- Classification uses binary nonconformity scores: `p_hat(y!=y_true)` via `binary_nonconformity_scores`.", "- Standard CP uses a single global conformal threshold.", "- Missingness-aware CP uses subgroup-specific thresholds when subgroup calibration support exceeds `min_group_size`, otherwise it falls back to the global threshold.", "- CPMDA exact uses exact mask-signature matching on selected missingness features and falls back to the global threshold when `min_match` is not met.", "- CQR uses symmetric or normalized residual scores with optional trimming via `trim_fraction`.", "", "## Preprocessing and Missingness Handling", "", "- Tabular classification models use one-hot encoding plus constant-value imputation for missing values where required by the estimator pipeline.", "- Structured missingness grouping is selected from candidate variables whose missing fractions lie between `min_variable_missing_fraction` and `max_variable_missing_fraction`.", "- The default appendix fallback threshold rule is explicit: undersupported groups revert to the marginal calibration threshold rather than forcing unstable subgroup quantiles.", ] ) def write_implementation_details(*, output_path: Path, manifest_path: Path) -> dict[str, Path]: output_path.parent.mkdir(parents=True, exist_ok=True) output_path.write_text(render_implementation_details(), encoding="utf-8") manifest_path.write_text( json.dumps({"implementation_details": str(output_path)}, indent=2, sort_keys=True), encoding="utf-8", ) return {"implementation_details": output_path, "manifest": manifest_path}