diff --git a/src/rtichoke/__init__.py b/src/rtichoke/__init__.py index bc84b742..f489bb15 100644 --- a/src/rtichoke/__init__.py +++ b/src/rtichoke/__init__.py @@ -30,7 +30,7 @@ ) from rtichoke.discrimination.gains import plot_gains_curve as plot_gains_curve -from rtichoke.calibration.calibration import ( +from rtichoke.calibration import ( create_calibration_curve as create_calibration_curve, create_calibration_curve_times as create_calibration_curve_times, ) diff --git a/src/rtichoke/calibration/calibration.py b/src/rtichoke/calibration/calibration.py index 2efbf57d..c809ed6d 100644 --- a/src/rtichoke/calibration/calibration.py +++ b/src/rtichoke/calibration/calibration.py @@ -99,7 +99,29 @@ def create_calibration_curve_times( "#585123", ], ) -> Figure: - """Creates a time-dependent Calibration Curve with a slider for different time horizons.""" + """Create a time-dependent calibration curve across fixed horizons. + + Raises: + ValueError: If a heuristic set requests adjusted censoring or treats + competing events as censored, which calibration does not support. + """ + + unsupported = [ + heuristics + for heuristics in heuristics_sets + if heuristics.get("censoring_heuristic") == "adjusted" + or heuristics.get("competing_heuristic") == "adjusted_as_censored" + ] + if unsupported: + raise ValueError( + "Unsupported calibration heuristics: " + "create_calibration_curve_times() does not support " + "censoring_heuristic='adjusted' or " + "competing_heuristic='adjusted_as_censored'. " + "Use a supported heuristic combination such as " + "censoring_heuristic='excluded' with " + "competing_heuristic='adjusted_as_negative'." + ) calibration_curve_list_times = _create_calibration_curve_list_times( probs, diff --git a/tests/test_calibration_times.py b/tests/test_calibration_times.py index 8e73c63a..6fbc86ed 100644 --- a/tests/test_calibration_times.py +++ b/tests/test_calibration_times.py @@ -1,5 +1,10 @@ import numpy as np +import pytest +from rtichoke import create_calibration_curve_times as create_calibration_curve_times_top_level from rtichoke.calibration import create_calibration_curve_times +from rtichoke.calibration.calibration import ( + create_calibration_curve_times as create_calibration_curve_times_direct, +) def test_create_calibration_curve_times(): @@ -53,3 +58,37 @@ def test_create_calibration_curve_times_unequal_size_populations(): ) assert {trace.name for trace in fig.data if trace.name} >= {"Train", "Test"} + + +@pytest.mark.parametrize( + "entry_point", + [create_calibration_curve_times_top_level, create_calibration_curve_times_direct], +) +@pytest.mark.parametrize( + "heuristics", + [ + { + "censoring_heuristic": "adjusted", + "competing_heuristic": "adjusted_as_negative", + }, + { + "censoring_heuristic": "excluded", + "competing_heuristic": "adjusted_as_censored", + }, + ], +) +def test_create_calibration_curve_times_rejects_unsupported_heuristics( + entry_point, heuristics +): + probs = {"model_1": np.array([0.1, 0.2, 0.3, 0.4])} + reals = np.array([0, 1, 0, 1]) + times = np.array([1.0, 2.0, 3.0, 4.0]) + + with pytest.raises(ValueError, match="Unsupported calibration heuristics"): + entry_point( + probs, + reals, + times, + fixed_time_horizons=[2.0], + heuristics_sets=[heuristics], + )