Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/rtichoke/calibration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,25 @@ def create_calibration_curve(*args, **kwargs):
)


def _extract_heuristics_sets(args, kwargs):
if "heuristics_sets" in kwargs:
return kwargs["heuristics_sets"]
if len(args) > 4:
return args[4]
return None


def create_calibration_curve_times(*args, **kwargs):
"""Create an interactive time-dependent calibration plot with a square main panel."""
heuristics_sets = _extract_heuristics_sets(args, kwargs)
if heuristics_sets is not None and len(heuristics_sets) != 1:
raise ValueError(
"create_calibration_curve_times() currently supports exactly one "
"heuristics set. Multiple heuristic sets would be combined in the "
"same plotted calibration curve. Call the function separately for "
"each heuristic set."
)

return enforce_square_calibration_panel(
_original_create_calibration_curve_times(*args, **kwargs)
)
Expand Down
63 changes: 63 additions & 0 deletions tests/test_calibration_times_heuristics_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
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,
)


@pytest.mark.parametrize(
"entry_point",
[
create_calibration_curve_times_top_level,
create_calibration_curve_times,
create_calibration_curve_times_direct,
],
)
def test_create_calibration_curve_times_rejects_multiple_heuristic_sets(entry_point):
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])

heuristics_sets = [
{
"censoring_heuristic": "adjusted",
"competing_heuristic": "adjusted_as_negative",
},
{
"censoring_heuristic": "excluded",
"competing_heuristic": "excluded",
},
]

with pytest.raises(ValueError, match="exactly one heuristics set"):
entry_point(
probs,
reals,
times,
fixed_time_horizons=[2.0],
heuristics_sets=heuristics_sets,
)


def test_create_calibration_curve_times_allows_one_heuristic_set():
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])

fig = create_calibration_curve_times(
probs,
reals,
times,
fixed_time_horizons=[2.0],
heuristics_sets=[
{
"censoring_heuristic": "adjusted",
"competing_heuristic": "adjusted_as_negative",
}
],
)

assert fig is not None
5 changes: 3 additions & 2 deletions user_guide/02-curve-api-compatibility.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ These statements describe the effect of the heuristics on the estimates. Functio

## Time-dependent calibration heuristics

`create_calibration_curve_times()` differs from its ROC, precision-recall, Gains, Lift, and decision-curve siblings in two important ways:
`create_calibration_curve_times()` differs from its ROC, precision-recall, Gains, Lift, and decision-curve siblings in three important ways:

1. `heuristics_sets` is currently required rather than defaulted.
2. Calibration explicitly rejects unsupported heuristic combinations (specifically `competing_heuristic="adjusted_as_censored"`) with an `Unsupported calibration heuristics` error instead of silently skipping requested horizons.
2. Calibration currently supports exactly one heuristic set per call. Use separate calls when comparing heuristic choices so distinct calibration estimates are never combined into one plotted curve.
3. Calibration explicitly rejects unsupported heuristic combinations (specifically `competing_heuristic="adjusted_as_censored"`) with an `Unsupported calibration heuristics` error instead of silently skipping requested horizons.

Pass the calibration heuristic explicitly. For adjusted or exclusion-based paths:

Expand Down
Loading