From f04e0345c56dd2eefe5c902f4290ca1beba858c8 Mon Sep 17 00:00:00 2001 From: gmartinon-ed Date: Thu, 22 Oct 2026 14:20:28 +0200 Subject: [PATCH] chore: enable ruff D102 and D105 and make engine methods private Co-Authored-By: Claude Sonnet 5.5 --- glide/confidence_intervals/bootstrap.py | 1 + glide/confidence_intervals/clt.py | 1 + glide/engines/base.py | 6 ++--- glide/engines/classical.py | 6 ++--- glide/engines/clustered_classical.py | 8 +++--- glide/engines/clustered_ppi.py | 10 +++---- glide/engines/multi_ppi.py | 6 ++--- glide/engines/ppi.py | 6 ++--- glide/engines/stratified_classical.py | 8 +++--- glide/engines/stratified_ppi.py | 6 ++--- glide/estimators/classical.py | 4 +-- glide/estimators/clustered_classical.py | 4 +-- glide/estimators/clustered_ppi.py | 6 ++--- glide/estimators/multi_ppi.py | 8 +++--- glide/estimators/ppi.py | 8 +++--- glide/estimators/stratified_classical.py | 4 +-- glide/estimators/stratified_ppi.py | 6 ++--- glide/mean_inference_results/base.py | 5 ++++ glide/mean_inference_results/classical.py | 1 + .../prediction_powered.py | 1 + glide/mean_monitoring_results/base.py | 9 +++++++ glide/mean_monitoring_results/classical.py | 2 ++ .../prediction_powered.py | 2 ++ glide/monitors/base.py | 10 +++---- pyproject.toml | 2 +- tests/unit/engines/test_classical.py | 18 ++++++------- .../unit/engines/test_clustered_classical.py | 20 +++++++------- tests/unit/engines/test_clustered_ppi.py | 18 ++++++------- tests/unit/engines/test_multi_ppi.py | 18 ++++++------- tests/unit/engines/test_ppi.py | 18 ++++++------- .../unit/engines/test_stratified_classical.py | 18 ++++++------- tests/unit/engines/test_stratified_ppi.py | 26 +++++++++---------- tests/unit/estimators/test_classical.py | 4 +-- .../estimators/test_clustered_classical.py | 4 +-- tests/unit/estimators/test_multi_ppi.py | 10 +++---- tests/unit/estimators/test_ppi.py | 10 +++---- .../estimators/test_stratified_classical.py | 4 +-- tests/unit/estimators/test_stratified_ppi.py | 6 ++--- tests/unit/monitors/test_base.py | 6 ++--- 39 files changed, 166 insertions(+), 144 deletions(-) diff --git a/glide/confidence_intervals/bootstrap.py b/glide/confidence_intervals/bootstrap.py index 24cfc4fc..6de15b8c 100644 --- a/glide/confidence_intervals/bootstrap.py +++ b/glide/confidence_intervals/bootstrap.py @@ -50,6 +50,7 @@ def __init__(self, bootstrap_estimates: NDArray, confidence_level: float = 0.95) @property def confidence_level(self) -> float: + """Confidence level of the interval; setting it recomputes the bounds.""" return self._confidence_level @confidence_level.setter diff --git a/glide/confidence_intervals/clt.py b/glide/confidence_intervals/clt.py index 407d89e7..cd8a3fa7 100644 --- a/glide/confidence_intervals/clt.py +++ b/glide/confidence_intervals/clt.py @@ -48,6 +48,7 @@ def __init__(self, mean: float, std: float, confidence_level: float = 0.95) -> N @property def confidence_level(self) -> float: + """Confidence level of the interval; setting it recomputes the bounds.""" return self._confidence_level @confidence_level.setter diff --git a/glide/engines/base.py b/glide/engines/base.py index 344af50a..a76bc857 100644 --- a/glide/engines/base.py +++ b/glide/engines/base.py @@ -7,8 +7,8 @@ class MeanEstimationEngine(Protocol[DatasetT, TuningParameterT]): - def preprocess(self, **fields: NDArray) -> DatasetT: ... + def _preprocess(self, **fields: NDArray) -> DatasetT: ... - def fit_tuning_parameter(self, dataset: DatasetT, *, power_tuning: bool) -> TuningParameterT: ... + def _fit_tuning_parameter(self, dataset: DatasetT, *, power_tuning: bool) -> TuningParameterT: ... - def compute_mean_and_std(self, dataset: DatasetT, tuning_parameter: TuningParameterT) -> Tuple[float, float]: ... + def _compute_mean_and_std(self, dataset: DatasetT, tuning_parameter: TuningParameterT) -> Tuple[float, float]: ... diff --git a/glide/engines/classical.py b/glide/engines/classical.py index a224bfaa..1323a73f 100644 --- a/glide/engines/classical.py +++ b/glide/engines/classical.py @@ -7,16 +7,16 @@ class ClassicalMeanEngine: - def preprocess(self, y: NDArray) -> NDArray: + def _preprocess(self, y: NDArray) -> NDArray: not_nan_mask = ~np.isnan(y) y_valid = y[not_nan_mask] _validate_min_samples(y_valid, "y") return y_valid - def fit_tuning_parameter(self, dataset: NDArray, *, power_tuning: bool) -> None: + def _fit_tuning_parameter(self, dataset: NDArray, *, power_tuning: bool) -> None: return None - def compute_mean_and_std(self, dataset: NDArray, tuning_parameter: None) -> Tuple[float, float]: + def _compute_mean_and_std(self, dataset: NDArray, tuning_parameter: None) -> Tuple[float, float]: n_samples = len(dataset) mean = np.mean(dataset) std = np.std(dataset, ddof=1) / np.sqrt(n_samples) diff --git a/glide/engines/clustered_classical.py b/glide/engines/clustered_classical.py index ba6aeafd..a7df325f 100644 --- a/glide/engines/clustered_classical.py +++ b/glide/engines/clustered_classical.py @@ -12,7 +12,7 @@ class ClusteredClassicalMeanEngine: def __init__(self) -> None: self._classical_engine = ClassicalMeanEngine() - def preprocess(self, y: NDArray, clusters: NDArray) -> NDArray: + def _preprocess(self, y: NDArray, clusters: NDArray) -> NDArray: _validate_equal_lengths(y, clusters, names=["y", "clusters"]) _validate_has_no_nan(clusters, "clusters") not_nan_mask = ~np.isnan(y) @@ -28,9 +28,9 @@ def preprocess(self, y: NDArray, clusters: NDArray) -> NDArray: cluster_means = _compute_cluster_means(y_valid, cluster_indices) return cluster_means - def fit_tuning_parameter(self, dataset: NDArray, *, power_tuning: bool) -> None: + def _fit_tuning_parameter(self, dataset: NDArray, *, power_tuning: bool) -> None: return None - def compute_mean_and_std(self, dataset: NDArray, tuning_parameter: None) -> Tuple[float, float]: - mean, std = self._classical_engine.compute_mean_and_std(dataset, tuning_parameter) + def _compute_mean_and_std(self, dataset: NDArray, tuning_parameter: None) -> Tuple[float, float]: + mean, std = self._classical_engine._compute_mean_and_std(dataset, tuning_parameter) return mean, std diff --git a/glide/engines/clustered_ppi.py b/glide/engines/clustered_ppi.py index 1c549d88..b761c456 100644 --- a/glide/engines/clustered_ppi.py +++ b/glide/engines/clustered_ppi.py @@ -11,14 +11,14 @@ class ClusteredPPIMeanEngine: def __init__(self) -> None: self._ppi_engine = PPIMeanEngine() - def preprocess(self, y_true: NDArray, y_proxy: NDArray, clusters: NDArray) -> ClusteredPPIDataset: + def _preprocess(self, y_true: NDArray, y_proxy: NDArray, clusters: NDArray) -> ClusteredPPIDataset: clustered_dataset = _preprocess(y_true, y_proxy, clusters) return clustered_dataset - def fit_tuning_parameter(self, dataset: ClusteredPPIDataset, *, power_tuning: bool) -> float: - tuning_parameter = self._ppi_engine.fit_tuning_parameter(dataset, power_tuning=power_tuning) + def _fit_tuning_parameter(self, dataset: ClusteredPPIDataset, *, power_tuning: bool) -> float: + tuning_parameter = self._ppi_engine._fit_tuning_parameter(dataset, power_tuning=power_tuning) return tuning_parameter - def compute_mean_and_std(self, dataset: ClusteredPPIDataset, tuning_parameter: float) -> Tuple[float, float]: - mean, std = self._ppi_engine.compute_mean_and_std(dataset, tuning_parameter) + def _compute_mean_and_std(self, dataset: ClusteredPPIDataset, tuning_parameter: float) -> Tuple[float, float]: + mean, std = self._ppi_engine._compute_mean_and_std(dataset, tuning_parameter) return mean, std diff --git a/glide/engines/multi_ppi.py b/glide/engines/multi_ppi.py index ee9302f2..3919047e 100644 --- a/glide/engines/multi_ppi.py +++ b/glide/engines/multi_ppi.py @@ -10,7 +10,7 @@ class MultiPPIMeanEngine: - def preprocess(self, y_true: NDArray, y_proxies: NDArray) -> MultiPPIDataset: + def _preprocess(self, y_true: NDArray, y_proxies: NDArray) -> MultiPPIDataset: _validate_is_2d(y_proxies, "y_proxies") _validate_equal_lengths(y_true, y_proxies, names=["y_true", "y_proxies"]) _validate_has_no_nan(y_proxies, "y_proxies") @@ -20,14 +20,14 @@ def preprocess(self, y_true: NDArray, y_proxies: NDArray) -> MultiPPIDataset: _validate_sample_sizes(labeled_mask) return y_true_labeled, y_proxies_labeled, y_proxies_unlabeled - def fit_tuning_parameter(self, dataset: MultiPPIDataset, *, power_tuning: bool) -> NDArray: + def _fit_tuning_parameter(self, dataset: MultiPPIDataset, *, power_tuning: bool) -> NDArray: y_true, y_proxies_labeled, y_proxies_unlabeled = dataset tuning_parameter = _compute_tuning_parameter( y_true, y_proxies_labeled, y_proxies_unlabeled, power_tuning=power_tuning ) return tuning_parameter - def compute_mean_and_std(self, dataset: MultiPPIDataset, tuning_parameter: NDArray) -> Tuple[float, float]: + def _compute_mean_and_std(self, dataset: MultiPPIDataset, tuning_parameter: NDArray) -> Tuple[float, float]: y_true, y_proxies_labeled, y_proxies_unlabeled = dataset mean = _compute_mean_estimate(y_true, y_proxies_labeled, y_proxies_unlabeled, tuning_parameter) std = _compute_std_estimate(y_true, y_proxies_labeled, y_proxies_unlabeled, tuning_parameter) diff --git a/glide/engines/ppi.py b/glide/engines/ppi.py index 5b339241..b274314c 100644 --- a/glide/engines/ppi.py +++ b/glide/engines/ppi.py @@ -10,21 +10,21 @@ class PPIMeanEngine: - def preprocess(self, y_true: NDArray, y_proxy: NDArray) -> PPIDataset: + def _preprocess(self, y_true: NDArray, y_proxy: NDArray) -> PPIDataset: _validate_equal_lengths(y_true, y_proxy, names=["y_true", "y_proxy"]) _validate_has_no_nan(y_proxy, "y_proxy") y_true_labeled, y_proxy_labeled, y_proxy_unlabeled, labeled_mask = _split_labeled_unlabeled(y_true, y_proxy) _validate_sample_sizes(labeled_mask) return y_true_labeled, y_proxy_labeled, y_proxy_unlabeled - def fit_tuning_parameter(self, dataset: PPIDataset, *, power_tuning: bool) -> float: + def _fit_tuning_parameter(self, dataset: PPIDataset, *, power_tuning: bool) -> float: y_true, y_proxy_labeled, y_proxy_unlabeled = dataset tuning_parameter = _compute_tuning_parameter( y_true, y_proxy_labeled, y_proxy_unlabeled, power_tuning=power_tuning ) return tuning_parameter - def compute_mean_and_std(self, dataset: PPIDataset, tuning_parameter: float) -> Tuple[float, float]: + def _compute_mean_and_std(self, dataset: PPIDataset, tuning_parameter: float) -> Tuple[float, float]: y_true, y_proxy_labeled, y_proxy_unlabeled = dataset mean = _compute_mean_estimate(y_true, y_proxy_labeled, y_proxy_unlabeled, tuning_parameter) std = _compute_std_estimate(y_true, y_proxy_labeled, y_proxy_unlabeled, tuning_parameter) diff --git a/glide/engines/stratified_classical.py b/glide/engines/stratified_classical.py index 4d6d402d..9e644cf6 100644 --- a/glide/engines/stratified_classical.py +++ b/glide/engines/stratified_classical.py @@ -13,7 +13,7 @@ class StratifiedClassicalMeanEngine: def __init__(self) -> None: self._classical_engine = ClassicalMeanEngine() - def preprocess( + def _preprocess( self, y: NDArray, groups: NDArray, stratum_weights: Optional[NDArray] = None ) -> StratifiedClassicalDataset: _validate_has_no_nan(groups, "groups") @@ -30,14 +30,14 @@ def preprocess( stratified_dataset[stratum_id] = (y_stratum, stratum_weights[stratum_code]) return stratified_dataset - def fit_tuning_parameter(self, dataset: StratifiedClassicalDataset, *, power_tuning: bool) -> None: + def _fit_tuning_parameter(self, dataset: StratifiedClassicalDataset, *, power_tuning: bool) -> None: return None - def compute_mean_and_std(self, dataset: StratifiedClassicalDataset, tuning_parameter: None) -> Tuple[float, float]: + def _compute_mean_and_std(self, dataset: StratifiedClassicalDataset, tuning_parameter: None) -> Tuple[float, float]: weighted_mean = 0.0 weighted_var = 0.0 for y_stratum, stratum_weight in dataset.values(): - mean_k, std_k = self._classical_engine.compute_mean_and_std(y_stratum, tuning_parameter) + mean_k, std_k = self._classical_engine._compute_mean_and_std(y_stratum, tuning_parameter) weighted_mean += stratum_weight * mean_k weighted_var += stratum_weight**2 * std_k**2 std = np.sqrt(weighted_var) diff --git a/glide/engines/stratified_ppi.py b/glide/engines/stratified_ppi.py index 0e612883..1596386f 100644 --- a/glide/engines/stratified_ppi.py +++ b/glide/engines/stratified_ppi.py @@ -11,11 +11,11 @@ class StratifiedPPIMeanEngine: - def preprocess(self, y_true: NDArray, y_proxy: NDArray, groups: NDArray) -> StratifiedPPIDataset: + def _preprocess(self, y_true: NDArray, y_proxy: NDArray, groups: NDArray) -> StratifiedPPIDataset: stratified_dataset = _preprocess(y_true, y_proxy, groups) return stratified_dataset - def fit_tuning_parameter(self, dataset: StratifiedPPIDataset, *, power_tuning: bool) -> StratifiedTuningParameter: + def _fit_tuning_parameter(self, dataset: StratifiedPPIDataset, *, power_tuning: bool) -> StratifiedTuningParameter: tuning_parameter = {} for stratum_id, (y_true, y_proxy_labeled, y_proxy_unlabeled) in dataset.items(): try: @@ -26,7 +26,7 @@ def fit_tuning_parameter(self, dataset: StratifiedPPIDataset, *, power_tuning: b raise ValueError(f"{error} (stratum '{stratum_id}').") from error return tuning_parameter - def compute_mean_and_std( + def _compute_mean_and_std( self, dataset: StratifiedPPIDataset, tuning_parameter: StratifiedTuningParameter ) -> Tuple[float, float]: stratum_sizes = { diff --git a/glide/estimators/classical.py b/glide/estimators/classical.py index 5ffa6a77..e8c8dfd6 100644 --- a/glide/estimators/classical.py +++ b/glide/estimators/classical.py @@ -61,9 +61,9 @@ def estimate( - If ``y`` contains fewer than 2 non-NaN values. - If ``confidence_level`` is not in ``(0, 1)``. """ - dataset = self._engine.preprocess(y) + dataset = self._engine._preprocess(y) n_labeled = len(dataset) - mean, std = self._engine.compute_mean_and_std(dataset, None) + mean, std = self._engine._compute_mean_and_std(dataset, None) ci = CLTConfidenceInterval( mean=mean, std=std, diff --git a/glide/estimators/clustered_classical.py b/glide/estimators/clustered_classical.py index 9ab07399..1ac8995c 100644 --- a/glide/estimators/clustered_classical.py +++ b/glide/estimators/clustered_classical.py @@ -79,8 +79,8 @@ def estimate( - If ``clusters`` contains NaN values (numeric dtype) or None values (non-numeric dtype). - If fewer than 2 clusters have at least one non-NaN observation. """ - cluster_means = self._engine.preprocess(y, clusters) - mean, std = self._engine.compute_mean_and_std(cluster_means, None) + cluster_means = self._engine._preprocess(y, clusters) + mean, std = self._engine._compute_mean_and_std(cluster_means, None) n_labeled = np.sum(~np.isnan(y)) ci = CLTConfidenceInterval( diff --git a/glide/estimators/clustered_ppi.py b/glide/estimators/clustered_ppi.py index 84dc72ed..7e7ce044 100644 --- a/glide/estimators/clustered_ppi.py +++ b/glide/estimators/clustered_ppi.py @@ -119,11 +119,11 @@ def estimate( - If ``power_tuning=True`` and proxy cluster means have zero variance across both labeled and unlabeled clusters. """ - clustered_dataset = self._engine.preprocess(y_true, y_proxy, clusters) + clustered_dataset = self._engine._preprocess(y_true, y_proxy, clusters) labeled_true_means, _, _ = clustered_dataset _validate_non_constant(labeled_true_means, "'y_true' labeled cluster means are constant.") - tuning_parameter = self._engine.fit_tuning_parameter(clustered_dataset, power_tuning=power_tuning) - mean, std = self._engine.compute_mean_and_std(clustered_dataset, tuning_parameter) + tuning_parameter = self._engine._fit_tuning_parameter(clustered_dataset, power_tuning=power_tuning) + mean, std = self._engine._compute_mean_and_std(clustered_dataset, tuning_parameter) confidence_interval = CLTConfidenceInterval( mean=mean, std=std, diff --git a/glide/estimators/multi_ppi.py b/glide/estimators/multi_ppi.py index ac3d155a..427ed51c 100644 --- a/glide/estimators/multi_ppi.py +++ b/glide/estimators/multi_ppi.py @@ -103,19 +103,19 @@ def estimate( perfectly correlated), with ``power_tuning=True``. - If ``confidence_level`` is not in ``(0, 1)``. """ - multi_ppi_dataset = self._engine.preprocess(y_true, y_proxies) + multi_ppi_dataset = self._engine._preprocess(y_true, y_proxies) y_true_labeled, _, y_proxies_unlabeled = multi_ppi_dataset _validate_non_constant(y_true_labeled, "'y_true' labeled values are constant.") - tuning_parameter = self._engine.fit_tuning_parameter(multi_ppi_dataset, power_tuning=power_tuning) - mean, std = self._engine.compute_mean_and_std(multi_ppi_dataset, tuning_parameter) + tuning_parameter = self._engine._fit_tuning_parameter(multi_ppi_dataset, power_tuning=power_tuning) + mean, std = self._engine._compute_mean_and_std(multi_ppi_dataset, tuning_parameter) confidence_interval = CLTConfidenceInterval( mean=mean, std=std, confidence_level=confidence_level, ) - _, classical_std = self._classical_engine.compute_mean_and_std(y_true_labeled, None) + _, classical_std = self._classical_engine._compute_mean_and_std(y_true_labeled, None) n_labeled, n_unlabeled = len(y_true_labeled), len(y_proxies_unlabeled) effective_sample_size = floor(n_labeled * classical_std**2 / std**2) diff --git a/glide/estimators/ppi.py b/glide/estimators/ppi.py index a85b5c3c..726a731a 100644 --- a/glide/estimators/ppi.py +++ b/glide/estimators/ppi.py @@ -106,19 +106,19 @@ def estimate( - If there are fewer than 2 labeled or fewer than 2 unlabeled samples. - If ``confidence_level`` is not in ``(0, 1)``. """ - ppi_dataset = self._engine.preprocess(y_true, y_proxy) + ppi_dataset = self._engine._preprocess(y_true, y_proxy) y_true_labeled, _, y_proxy_unlabeled = ppi_dataset _validate_non_constant(y_true_labeled, "'y_true' labeled values are constant.") - tuning_parameter = self._engine.fit_tuning_parameter(ppi_dataset, power_tuning=power_tuning) - mean, std = self._engine.compute_mean_and_std(ppi_dataset, tuning_parameter) + tuning_parameter = self._engine._fit_tuning_parameter(ppi_dataset, power_tuning=power_tuning) + mean, std = self._engine._compute_mean_and_std(ppi_dataset, tuning_parameter) confidence_interval = CLTConfidenceInterval( mean=mean, std=std, confidence_level=confidence_level, ) - _, classical_std = self._classical_engine.compute_mean_and_std(y_true_labeled, None) + _, classical_std = self._classical_engine._compute_mean_and_std(y_true_labeled, None) n_labeled, n_unlabeled = len(y_true_labeled), len(y_proxy_unlabeled) effective_sample_size = floor(n_labeled * classical_std**2 / std**2) diff --git a/glide/estimators/stratified_classical.py b/glide/estimators/stratified_classical.py index 13fc5796..3de71541 100644 --- a/glide/estimators/stratified_classical.py +++ b/glide/estimators/stratified_classical.py @@ -91,8 +91,8 @@ def estimate( - If ``y`` and ``groups`` have different lengths. - If any stratum contains fewer than 2 non-NaN values. """ - stratified_dataset = self._engine.preprocess(y, groups, stratum_weights) - weighted_mean, std = self._engine.compute_mean_and_std(stratified_dataset, None) + stratified_dataset = self._engine._preprocess(y, groups, stratum_weights) + weighted_mean, std = self._engine._compute_mean_and_std(stratified_dataset, None) n_labeled = np.sum(~np.isnan(y)) ci = CLTConfidenceInterval( mean=weighted_mean, diff --git a/glide/estimators/stratified_ppi.py b/glide/estimators/stratified_ppi.py index 85cd87c5..e2d9f5d5 100644 --- a/glide/estimators/stratified_ppi.py +++ b/glide/estimators/stratified_ppi.py @@ -122,11 +122,11 @@ def estimate( - If any stratum has fewer than 2 labeled or fewer than 2 unlabeled samples. - If a stratum's proxy values are constant, with ``power_tuning=True``. """ - stratified_dataset = self._engine.preprocess(y_true, y_proxy, groups) + stratified_dataset = self._engine._preprocess(y_true, y_proxy, groups) _validate_non_constant(y_true[~np.isnan(y_true)], "'y_true' labeled values are constant.") - tuning_parameter = self._engine.fit_tuning_parameter(stratified_dataset, power_tuning=power_tuning) - weighted_mean, std = self._engine.compute_mean_and_std(stratified_dataset, tuning_parameter) + tuning_parameter = self._engine._fit_tuning_parameter(stratified_dataset, power_tuning=power_tuning) + weighted_mean, std = self._engine._compute_mean_and_std(stratified_dataset, tuning_parameter) n_samples = len(y_true) n_labeled = int(np.sum(~np.isnan(y_true))) diff --git a/glide/mean_inference_results/base.py b/glide/mean_inference_results/base.py index fcd40e02..71e7809d 100644 --- a/glide/mean_inference_results/base.py +++ b/glide/mean_inference_results/base.py @@ -14,15 +14,18 @@ class MeanInferenceResult: @property def width(self) -> float: + """Width of the confidence interval.""" result = self.confidence_interval.width return result @property def mean(self) -> float: + """Point estimate of the mean.""" return self.confidence_interval.mean @property def std(self) -> float: + """Standard error of the point estimate.""" return self.confidence_interval.std def _common_lines(self) -> List[str]: @@ -37,6 +40,7 @@ def _common_lines(self) -> List[str]: ] def __str__(self) -> str: + """Return the multi-line textual representation of the result.""" return "\n".join(self._common_lines()) def summary(self) -> str: @@ -44,4 +48,5 @@ def summary(self) -> str: return self.__str__() def __repr__(self) -> str: + """Return the same representation as ``str``.""" return self.__str__() diff --git a/glide/mean_inference_results/classical.py b/glide/mean_inference_results/classical.py index a3be8fb4..6a91affc 100644 --- a/glide/mean_inference_results/classical.py +++ b/glide/mean_inference_results/classical.py @@ -10,6 +10,7 @@ class ClassicalMeanInferenceResult(MeanInferenceResult): n: int = 0 def __str__(self) -> str: + """Return the multi-line textual representation of the result.""" lines = self._common_lines() + [ f"n: {self.n}", ] diff --git a/glide/mean_inference_results/prediction_powered.py b/glide/mean_inference_results/prediction_powered.py index fc7d3f17..0295e0b4 100644 --- a/glide/mean_inference_results/prediction_powered.py +++ b/glide/mean_inference_results/prediction_powered.py @@ -12,6 +12,7 @@ class PredictionPoweredMeanInferenceResult(MeanInferenceResult): effective_sample_size: int = 0 def __str__(self) -> str: + """Return the multi-line textual representation of the result.""" lines = self._common_lines() + [ f"n_true: {self.n_true}", f"n_proxy: {self.n_proxy}", diff --git a/glide/mean_monitoring_results/base.py b/glide/mean_monitoring_results/base.py index 6e46cb9e..7e4ab994 100644 --- a/glide/mean_monitoring_results/base.py +++ b/glide/mean_monitoring_results/base.py @@ -41,6 +41,7 @@ class MeanMonitoringResult: confidence_sequence: ConfidenceSequence def __post_init__(self) -> None: + """Validate that the per-batch arrays and the confidence sequence have matching lengths.""" _validate_non_empty(self.batch_mean_estimates, "batch_mean_estimates") _validate_equal_lengths( self.batch_mean_estimates, @@ -51,32 +52,38 @@ def __post_init__(self) -> None: @property def running_means(self) -> NDArray: + """Running mean of the per-batch estimates, for each batch.""" result = self.confidence_sequence.running_mean_estimates return result @property def confidence_bounds(self) -> NDArray: + """Anytime-valid bound on the running mean, for each batch.""" result = self.confidence_sequence.confidence_bounds return result @property def alarms(self) -> NDArray: + """Whether the confidence bound has crossed the alarm threshold, for each batch.""" alternative = "smaller" if self.higher_is_better else "larger" result = self.confidence_sequence.test_null_hypothesis(self.alarm_threshold, alternative) return result @property def n_batches(self) -> int: + """Number of batches monitored.""" result = len(self.batch_mean_estimates) return result @property def drift_detected(self) -> bool: + """Whether an alarm was raised on any batch.""" result = bool(self.alarms.any()) return result @property def first_alarm_index(self) -> Optional[int]: + """Index of the first batch raising an alarm, or None if no drift was detected.""" if not self.drift_detected: return None result = int(self.alarms.argmax()) @@ -97,6 +104,7 @@ def _common_lines(self) -> List[str]: return lines def __str__(self) -> str: + """Return the multi-line textual representation of the result.""" return "\n".join(self._common_lines()) def summary(self) -> str: @@ -104,4 +112,5 @@ def summary(self) -> str: return self.__str__() def __repr__(self) -> str: + """Return the same representation as ``str``.""" return self.__str__() diff --git a/glide/mean_monitoring_results/classical.py b/glide/mean_monitoring_results/classical.py index 6392a7dc..d82ea2ea 100644 --- a/glide/mean_monitoring_results/classical.py +++ b/glide/mean_monitoring_results/classical.py @@ -18,10 +18,12 @@ class ClassicalMeanMonitoringResult(MeanMonitoringResult): batch_n: NDArray def __post_init__(self) -> None: + """Validate that the per-batch sample counts match the batch estimates.""" super().__post_init__() _validate_equal_lengths(self.batch_mean_estimates, self.batch_n, names=["batch_mean_estimates", "batch_n"]) def __str__(self) -> str: + """Return the multi-line textual representation of the result.""" lines = self._common_lines() + [ f"batch_n: {self.batch_n.tolist()}", ] diff --git a/glide/mean_monitoring_results/prediction_powered.py b/glide/mean_monitoring_results/prediction_powered.py index a6052d04..6c04d6af 100644 --- a/glide/mean_monitoring_results/prediction_powered.py +++ b/glide/mean_monitoring_results/prediction_powered.py @@ -20,6 +20,7 @@ class PredictionPoweredMeanMonitoringResult(MeanMonitoringResult): batch_n_proxy: NDArray def __post_init__(self) -> None: + """Validate that the per-batch sample counts match the batch estimates.""" super().__post_init__() _validate_equal_lengths( self.batch_mean_estimates, @@ -29,6 +30,7 @@ def __post_init__(self) -> None: ) def __str__(self) -> str: + """Return the multi-line textual representation of the result.""" lines = self._common_lines() + [ f"batch_n_true: {self.batch_n_true.tolist()}", f"batch_n_proxy: {self.batch_n_proxy.tolist()}", diff --git a/glide/monitors/base.py b/glide/monitors/base.py index a4dd927d..5bd02d05 100644 --- a/glide/monitors/base.py +++ b/glide/monitors/base.py @@ -13,7 +13,7 @@ class AsymptoticRM(Generic[DatasetT, TuningParameterT]): def _preprocess_subset(self, fields: Dict[str, NDArray], mask: NDArray) -> DatasetT: field_subsets = {name: field[mask] for name, field in fields.items()} - dataset = self._engine.preprocess(**field_subsets) + dataset = self._engine._preprocess(**field_subsets) return dataset def _detect( @@ -44,13 +44,13 @@ def _detect( raise ValueError(f"{error} (batch '{batch_identifiers[position]}').") from error if position == 0 or not power_tuning: - tuning_parameter = self._engine.fit_tuning_parameter(batch_risk_dataset, power_tuning=False) + tuning_parameter = self._engine._fit_tuning_parameter(batch_risk_dataset, power_tuning=False) else: prefix_risk_dataset = self._preprocess_subset(risk_fields, batch_codes < position) - tuning_parameter = self._engine.fit_tuning_parameter(prefix_risk_dataset, power_tuning=True) + tuning_parameter = self._engine._fit_tuning_parameter(prefix_risk_dataset, power_tuning=True) - batch_risk_mean_estimates[position], batch_risk_std_estimates[position] = self._engine.compute_mean_and_std( - batch_risk_dataset, tuning_parameter + batch_risk_mean_estimates[position], batch_risk_std_estimates[position] = ( + self._engine._compute_mean_and_std(batch_risk_dataset, tuning_parameter) ) miscoverage = 1.0 - confidence_level diff --git a/pyproject.toml b/pyproject.toml index 1b4271c9..f9d5df51 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,7 +74,7 @@ default-groups = ["dev"] [tool.ruff] line-length = 120 fix = true -lint.select = ["E", "F", "FBT001", "FBT002", "I", "RUF001", "RUF002", "RUF003"] +lint.select = ["E", "F", "FBT001", "FBT002", "I", "RUF001", "RUF002", "RUF003", "D102", "D105"] [tool.ty.analysis] respect-type-ignore-comments = true diff --git a/tests/unit/engines/test_classical.py b/tests/unit/engines/test_classical.py index 69198774..b1dec6b4 100644 --- a/tests/unit/engines/test_classical.py +++ b/tests/unit/engines/test_classical.py @@ -18,37 +18,37 @@ def engine(): @pytest.fixture def dataset(engine, y): - return engine.preprocess(y) + return engine._preprocess(y) -# --- preprocess --- +# --- _preprocess --- def test_preprocess_valid_output(engine, y): - dataset = engine.preprocess(y) + dataset = engine._preprocess(y) np.testing.assert_array_equal(dataset, np.array([2.0, 4.0])) def test_preprocess_delegates_to_validation(engine, y): with patch("glide.engines.classical._validate_min_samples") as mock_validate_min_samples: - engine.preprocess(y) + engine._preprocess(y) mock_validate_min_samples.assert_called_once() np.testing.assert_array_equal(mock_validate_min_samples.call_args[0][0], np.array([2.0, 4.0])) assert mock_validate_min_samples.call_args[0][1] == "y" -# --- fit_tuning_parameter --- +# --- _fit_tuning_parameter --- def test_fit_tuning_parameter_returns_none(engine, dataset): - assert engine.fit_tuning_parameter(dataset, power_tuning=True) is None - assert engine.fit_tuning_parameter(dataset, power_tuning=False) is None + assert engine._fit_tuning_parameter(dataset, power_tuning=True) is None + assert engine._fit_tuning_parameter(dataset, power_tuning=False) is None -# --- compute_mean_and_std --- +# --- _compute_mean_and_std --- def test_compute_mean_and_std(engine, dataset): - mean, std = engine.compute_mean_and_std(dataset, tuning_parameter=None) + mean, std = engine._compute_mean_and_std(dataset, tuning_parameter=None) assert mean == pytest.approx(3.0) assert std == pytest.approx(1.0) diff --git a/tests/unit/engines/test_clustered_classical.py b/tests/unit/engines/test_clustered_classical.py index 35969858..332a605e 100644 --- a/tests/unit/engines/test_clustered_classical.py +++ b/tests/unit/engines/test_clustered_classical.py @@ -25,7 +25,7 @@ def engine(): @pytest.fixture def dataset(engine, y, clusters): - return engine.preprocess(y, clusters) + return engine._preprocess(y, clusters) # --- __init__ --- @@ -35,7 +35,7 @@ def test_init_sets_classical_engine(engine): assert isinstance(engine._classical_engine, ClassicalMeanEngine) -# --- preprocess --- +# --- _preprocess --- def test_preprocess_delegates_to_validation(engine, y, clusters): @@ -44,7 +44,7 @@ def test_preprocess_delegates_to_validation(engine, y, clusters): patch.object(clustered_classical_engine_module, "_validate_has_no_nan") as mock_validate_has_no_nan, patch.object(clustered_classical_engine_module, "_validate_bounds") as mock_validate_bounds, ): - engine.preprocess(y, clusters) + engine._preprocess(y, clusters) mock_validate_equal_lengths.assert_called_once() np.testing.assert_array_equal(mock_validate_equal_lengths.call_args[0][0], y) @@ -64,26 +64,26 @@ def test_preprocess_delegates_to_validation(engine, y, clusters): def test_preprocess_valid_output(engine, y, clusters): - cluster_means = engine.preprocess(y, clusters) + cluster_means = engine._preprocess(y, clusters) expected = np.array([5.0, 7.0]) np.testing.assert_allclose(cluster_means, expected) -# --- fit_tuning_parameter --- +# --- _fit_tuning_parameter --- def test_fit_tuning_parameter_returns_none(engine, dataset): - assert engine.fit_tuning_parameter(dataset, power_tuning=True) is None - assert engine.fit_tuning_parameter(dataset, power_tuning=False) is None + assert engine._fit_tuning_parameter(dataset, power_tuning=True) is None + assert engine._fit_tuning_parameter(dataset, power_tuning=False) is None -# --- compute_mean_and_std --- +# --- _compute_mean_and_std --- def test_compute_mean_and_std_delegates_to_classical_engine(engine, dataset): - with patch.object(engine._classical_engine, "compute_mean_and_std") as mock_compute_mean_and_std: + with patch.object(engine._classical_engine, "_compute_mean_and_std") as mock_compute_mean_and_std: mock_compute_mean_and_std.return_value = (1.5, 0.25) - mean, std = engine.compute_mean_and_std(dataset, tuning_parameter=None) + mean, std = engine._compute_mean_and_std(dataset, tuning_parameter=None) mock_compute_mean_and_std.assert_called_once() np.testing.assert_array_equal(mock_compute_mean_and_std.call_args[0][0], dataset) diff --git a/tests/unit/engines/test_clustered_ppi.py b/tests/unit/engines/test_clustered_ppi.py index 8980318e..ed5867e8 100644 --- a/tests/unit/engines/test_clustered_ppi.py +++ b/tests/unit/engines/test_clustered_ppi.py @@ -30,7 +30,7 @@ def engine(): @pytest.fixture def dataset(engine, y_true, y_proxy, clusters): - return engine.preprocess(y_true, y_proxy, clusters) + return engine._preprocess(y_true, y_proxy, clusters) # --- __init__ --- @@ -40,14 +40,14 @@ def test_init_sets_ppi_engine(engine): assert isinstance(engine._ppi_engine, PPIMeanEngine) -# --- preprocess --- +# --- _preprocess --- def test_preprocess_delegates_to_clustered_core(engine, y_true, y_proxy, clusters): sentinel_dataset = object() with patch.object(clustered_ppi_engine_module, "_preprocess") as mock_preprocess: mock_preprocess.return_value = sentinel_dataset - dataset = engine.preprocess(y_true, y_proxy, clusters) + dataset = engine._preprocess(y_true, y_proxy, clusters) mock_preprocess.assert_called_once() np.testing.assert_array_equal(mock_preprocess.call_args[0][0], y_true) @@ -56,13 +56,13 @@ def test_preprocess_delegates_to_clustered_core(engine, y_true, y_proxy, cluster assert dataset is sentinel_dataset -# --- fit_tuning_parameter --- +# --- _fit_tuning_parameter --- def test_fit_tuning_parameter_delegates_to_ppi_engine(engine, dataset): - with patch.object(engine._ppi_engine, "fit_tuning_parameter") as mock_fit_tuning_parameter: + with patch.object(engine._ppi_engine, "_fit_tuning_parameter") as mock_fit_tuning_parameter: mock_fit_tuning_parameter.return_value = 0.5 - tuning_parameter = engine.fit_tuning_parameter(dataset, power_tuning=False) + tuning_parameter = engine._fit_tuning_parameter(dataset, power_tuning=False) mock_fit_tuning_parameter.assert_called_once() for received, expected in zip(mock_fit_tuning_parameter.call_args[0][0], dataset): @@ -71,13 +71,13 @@ def test_fit_tuning_parameter_delegates_to_ppi_engine(engine, dataset): assert tuning_parameter == 0.5 -# --- compute_mean_and_std --- +# --- _compute_mean_and_std --- def test_compute_mean_and_std_delegates_to_ppi_engine(engine, dataset): - with patch.object(engine._ppi_engine, "compute_mean_and_std") as mock_compute_mean_and_std: + with patch.object(engine._ppi_engine, "_compute_mean_and_std") as mock_compute_mean_and_std: mock_compute_mean_and_std.return_value = (1.5, 0.25) - mean, std = engine.compute_mean_and_std(dataset, tuning_parameter=0.5) + mean, std = engine._compute_mean_and_std(dataset, tuning_parameter=0.5) mock_compute_mean_and_std.assert_called_once() for received, expected in zip(mock_compute_mean_and_std.call_args[0][0], dataset): diff --git a/tests/unit/engines/test_multi_ppi.py b/tests/unit/engines/test_multi_ppi.py index 55af7be0..c019a08e 100644 --- a/tests/unit/engines/test_multi_ppi.py +++ b/tests/unit/engines/test_multi_ppi.py @@ -24,10 +24,10 @@ def engine(): @pytest.fixture def dataset(engine, y_true, y_proxies): - return engine.preprocess(y_true, y_proxies) + return engine._preprocess(y_true, y_proxies) -# --- preprocess --- +# --- _preprocess --- def test_preprocess_delegates_to_validation(engine, y_true, y_proxies): @@ -45,7 +45,7 @@ def test_preprocess_delegates_to_validation(engine, y_true, y_proxies): np.array([[3.0, 1.0], [4.0, 3.0]]), labeled_mask, ) - engine.preprocess(y_true, y_proxies) + engine._preprocess(y_true, y_proxies) mock_validate_equal_lengths.assert_called_once() np.testing.assert_array_equal(mock_validate_equal_lengths.call_args[0][0], y_true) @@ -70,31 +70,31 @@ def test_preprocess_delegates_to_validation(engine, y_true, y_proxies): def test_preprocess_valid_output(engine, y_true, y_proxies): - y_true_labeled, y_proxies_labeled, y_proxies_unlabeled = engine.preprocess(y_true, y_proxies) + y_true_labeled, y_proxies_labeled, y_proxies_unlabeled = engine._preprocess(y_true, y_proxies) np.testing.assert_array_equal(y_true_labeled, np.array([1.0, 2.0])) np.testing.assert_array_equal(y_proxies_labeled, np.array([[1.0, 0.0], [2.0, 2.0]])) np.testing.assert_array_equal(y_proxies_unlabeled, np.array([[3.0, 1.0], [4.0, 3.0]])) -# --- fit_tuning_parameter --- +# --- _fit_tuning_parameter --- def test_fit_tuning_parameter_power_tuning_true(engine, dataset): - tuning_parameter = engine.fit_tuning_parameter(dataset, power_tuning=True) + tuning_parameter = engine._fit_tuning_parameter(dataset, power_tuning=True) expected = np.array([-0.25, 0.5]) np.testing.assert_allclose(tuning_parameter, expected) def test_fit_tuning_parameter_power_tuning_false(engine, dataset): - tuning_parameter = engine.fit_tuning_parameter(dataset, power_tuning=False) + tuning_parameter = engine._fit_tuning_parameter(dataset, power_tuning=False) expected = np.full(2, 1 / np.sqrt(2)) np.testing.assert_allclose(tuning_parameter, expected) -# --- compute_mean_and_std --- +# --- _compute_mean_and_std --- def test_compute_mean_and_std(engine, dataset): - mean, std = engine.compute_mean_and_std(dataset, tuning_parameter=np.array([0.5, 0.5])) + mean, std = engine._compute_mean_and_std(dataset, tuning_parameter=np.array([0.5, 0.5])) assert mean == pytest.approx(3.0) assert std == pytest.approx(0.7906, abs=1e-4) diff --git a/tests/unit/engines/test_ppi.py b/tests/unit/engines/test_ppi.py index 388be6b1..60e41e99 100644 --- a/tests/unit/engines/test_ppi.py +++ b/tests/unit/engines/test_ppi.py @@ -24,10 +24,10 @@ def engine(): @pytest.fixture def dataset(engine, y_true, y_proxy): - return engine.preprocess(y_true, y_proxy) + return engine._preprocess(y_true, y_proxy) -# --- preprocess --- +# --- _preprocess --- def test_preprocess_delegates_to_validation(engine, y_true, y_proxy): @@ -44,7 +44,7 @@ def test_preprocess_delegates_to_validation(engine, y_true, y_proxy): np.array([3.0, 4.0]), labeled_mask, ) - engine.preprocess(y_true, y_proxy) + engine._preprocess(y_true, y_proxy) mock_validate_equal_lengths.assert_called_once() np.testing.assert_array_equal(mock_validate_equal_lengths.call_args[0][0], y_true) @@ -61,29 +61,29 @@ def test_preprocess_delegates_to_validation(engine, y_true, y_proxy): def test_preprocess_valid_output(engine, y_true, y_proxy): - y_true_labeled, y_proxy_labeled, y_proxy_unlabeled = engine.preprocess(y_true, y_proxy) + y_true_labeled, y_proxy_labeled, y_proxy_unlabeled = engine._preprocess(y_true, y_proxy) np.testing.assert_array_equal(y_true_labeled, np.array([1.0, 2.0])) np.testing.assert_array_equal(y_proxy_labeled, np.array([1.0, 2.0])) np.testing.assert_array_equal(y_proxy_unlabeled, np.array([3.0, 4.0])) -# --- fit_tuning_parameter --- +# --- _fit_tuning_parameter --- def test_fit_tuning_parameter_power_tuning_true(engine, dataset): - tuning_parameter = engine.fit_tuning_parameter(dataset, power_tuning=True) + tuning_parameter = engine._fit_tuning_parameter(dataset, power_tuning=True) assert tuning_parameter == pytest.approx(0.15) def test_fit_tuning_parameter_power_tuning_false(engine, dataset): - tuning_parameter = engine.fit_tuning_parameter(dataset, power_tuning=False) + tuning_parameter = engine._fit_tuning_parameter(dataset, power_tuning=False) assert tuning_parameter == pytest.approx(1.0) -# --- compute_mean_and_std --- +# --- _compute_mean_and_std --- def test_compute_mean_and_std(engine, dataset): - mean, std = engine.compute_mean_and_std(dataset, tuning_parameter=0.15) + mean, std = engine._compute_mean_and_std(dataset, tuning_parameter=0.15) assert mean == pytest.approx(1.8) assert std == pytest.approx(0.4316, abs=1e-4) diff --git a/tests/unit/engines/test_stratified_classical.py b/tests/unit/engines/test_stratified_classical.py index 23309611..0a954bc7 100644 --- a/tests/unit/engines/test_stratified_classical.py +++ b/tests/unit/engines/test_stratified_classical.py @@ -25,7 +25,7 @@ def engine(): @pytest.fixture def dataset(engine, y, groups): - return engine.preprocess(y, groups) + return engine._preprocess(y, groups) # --- __init__ --- @@ -35,7 +35,7 @@ def test_init_sets_classical_engine(engine): assert isinstance(engine._classical_engine, ClassicalMeanEngine) -# --- preprocess --- +# --- _preprocess --- def test_preprocess_delegates_to_validation(engine, y, groups): @@ -44,7 +44,7 @@ def test_preprocess_delegates_to_validation(engine, y, groups): patch.object(stratified_classical_engine_module, "_validate_equal_lengths") as mock_validate_equal_lengths, patch.object(stratified_classical_engine_module, "_validate_min_samples") as mock_validate_min_samples, ): - engine.preprocess(y, groups) + engine._preprocess(y, groups) mock_validate_has_no_nan.assert_called_once() np.testing.assert_array_equal(mock_validate_has_no_nan.call_args[0][0], groups) @@ -74,24 +74,24 @@ def test_preprocess_valid_output(dataset): def test_preprocess_custom_stratum_weights(engine, y, groups): - dataset = engine.preprocess(y, groups, stratum_weights=np.array([0.8, 0.2])) + dataset = engine._preprocess(y, groups, stratum_weights=np.array([0.8, 0.2])) assert dataset["A"][1] == pytest.approx(0.8, abs=1e-12) assert dataset["B"][1] == pytest.approx(0.2, abs=1e-12) -# --- fit_tuning_parameter --- +# --- _fit_tuning_parameter --- def test_fit_tuning_parameter_returns_none(engine, dataset): - assert engine.fit_tuning_parameter(dataset, power_tuning=True) is None - assert engine.fit_tuning_parameter(dataset, power_tuning=False) is None + assert engine._fit_tuning_parameter(dataset, power_tuning=True) is None + assert engine._fit_tuning_parameter(dataset, power_tuning=False) is None -# --- compute_mean_and_std --- +# --- _compute_mean_and_std --- def test_compute_mean_and_std(engine, dataset): - mean, std = engine.compute_mean_and_std(dataset, None) + mean, std = engine._compute_mean_and_std(dataset, None) assert mean == pytest.approx(3.6) assert std == pytest.approx(np.sqrt(0.52)) diff --git a/tests/unit/engines/test_stratified_ppi.py b/tests/unit/engines/test_stratified_ppi.py index 46b121d0..0cf1f3a2 100644 --- a/tests/unit/engines/test_stratified_ppi.py +++ b/tests/unit/engines/test_stratified_ppi.py @@ -29,17 +29,17 @@ def engine(): @pytest.fixture def dataset(engine, y_true, y_proxy, groups): - return engine.preprocess(y_true, y_proxy, groups) + return engine._preprocess(y_true, y_proxy, groups) -# --- preprocess --- +# --- _preprocess --- def test_preprocess_delegates_to_stratified_core(engine, y_true, y_proxy, groups): sentinel_dataset = object() with patch.object(stratified_ppi_engine_module, "_preprocess") as mock_preprocess: mock_preprocess.return_value = sentinel_dataset - dataset = engine.preprocess(y_true, y_proxy, groups) + dataset = engine._preprocess(y_true, y_proxy, groups) mock_preprocess.assert_called_once() np.testing.assert_array_equal(mock_preprocess.call_args[0][0], y_true) @@ -48,17 +48,17 @@ def test_preprocess_delegates_to_stratified_core(engine, y_true, y_proxy, groups assert dataset is sentinel_dataset -# --- fit_tuning_parameter --- +# --- _fit_tuning_parameter --- def test_fit_tuning_parameter_power_tuning_true(engine, dataset): - tuning_parameter = engine.fit_tuning_parameter(dataset, power_tuning=True) + tuning_parameter = engine._fit_tuning_parameter(dataset, power_tuning=True) assert tuning_parameter["A"] == pytest.approx(0.784, abs=1e-3) assert tuning_parameter["B"] == pytest.approx(0.784, abs=1e-3) def test_fit_tuning_parameter_power_tuning_false(engine, dataset): - tuning_parameter = engine.fit_tuning_parameter(dataset, power_tuning=False) + tuning_parameter = engine._fit_tuning_parameter(dataset, power_tuning=False) assert tuning_parameter["A"] == pytest.approx(1.0) assert tuning_parameter["B"] == pytest.approx(1.0) @@ -69,7 +69,7 @@ def test_fit_tuning_parameter_per_stratum_independence(engine, dataset): "B": (np.array([1.0, 2.0, 3.0]), np.array([1.1, 2.2, 3.3]), np.array([4.0, 5.0, 6.0, 7.0])), } - tuning_parameter = engine.fit_tuning_parameter(dataset_with_different_b, power_tuning=True) + tuning_parameter = engine._fit_tuning_parameter(dataset_with_different_b, power_tuning=True) assert tuning_parameter["A"] == pytest.approx(0.784, abs=1e-3) @@ -78,27 +78,27 @@ def test_fit_tuning_parameter_wraps_error_with_stratum_identifier(engine): y_true = np.array([1.0, 2.0, np.nan, np.nan, 1.0, 2.0, np.nan, np.nan]) y_proxy = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0]) groups = np.array(["A", "A", "A", "A", "B", "B", "B", "B"]) - dataset = engine.preprocess(y_true, y_proxy, groups) + dataset = engine._preprocess(y_true, y_proxy, groups) expected_message = "Proxy labels have zero variance; cannot estimate the tuning parameter. (stratum 'B')." with pytest.raises(ValueError, match=r"^Proxy labels have zero variance") as exc_info: - engine.fit_tuning_parameter(dataset, power_tuning=True) + engine._fit_tuning_parameter(dataset, power_tuning=True) assert str(exc_info.value) == expected_message -# --- compute_mean_and_std --- +# --- _compute_mean_and_std --- def test_compute_mean_and_std(engine, dataset): tuning_parameter = {"A": 0.784, "B": 0.784} - mean, std = engine.compute_mean_and_std(dataset, tuning_parameter) + mean, std = engine._compute_mean_and_std(dataset, tuning_parameter) assert mean == pytest.approx(5.617, abs=1e-3) assert std == pytest.approx(0.250, abs=1e-3) def test_compute_mean_and_std_missing_stratum_defaults_to_untuned(engine, dataset): - mean_with_missing_key, std_with_missing_key = engine.compute_mean_and_std(dataset, {"A": 0.784}) - mean_with_explicit_one, std_with_explicit_one = engine.compute_mean_and_std(dataset, {"A": 0.784, "B": 1.0}) + mean_with_missing_key, std_with_missing_key = engine._compute_mean_and_std(dataset, {"A": 0.784}) + mean_with_explicit_one, std_with_explicit_one = engine._compute_mean_and_std(dataset, {"A": 0.784, "B": 1.0}) assert mean_with_missing_key == pytest.approx(mean_with_explicit_one) assert std_with_missing_key == pytest.approx(std_with_explicit_one) diff --git a/tests/unit/estimators/test_classical.py b/tests/unit/estimators/test_classical.py index 99554c4c..14870122 100644 --- a/tests/unit/estimators/test_classical.py +++ b/tests/unit/estimators/test_classical.py @@ -33,9 +33,9 @@ def test_init_sets_engine(estimator): def test_estimate_delegates(estimator, y_array): with ( - patch.object(estimator._engine, "preprocess", wraps=estimator._engine.preprocess) as mock_preprocess, + patch.object(estimator._engine, "_preprocess", wraps=estimator._engine._preprocess) as mock_preprocess, patch.object( - estimator._engine, "compute_mean_and_std", wraps=estimator._engine.compute_mean_and_std + estimator._engine, "_compute_mean_and_std", wraps=estimator._engine._compute_mean_and_std ) as mock_compute_mean_and_std, ): estimator.estimate(y_array, confidence_level=0.90) diff --git a/tests/unit/estimators/test_clustered_classical.py b/tests/unit/estimators/test_clustered_classical.py index 74240080..a521bfab 100644 --- a/tests/unit/estimators/test_clustered_classical.py +++ b/tests/unit/estimators/test_clustered_classical.py @@ -36,9 +36,9 @@ def test_init_sets_engine(estimator): def test_estimate_delegates(estimator, y, clusters): with ( - patch.object(estimator._engine, "preprocess", wraps=estimator._engine.preprocess) as mock_preprocess, + patch.object(estimator._engine, "_preprocess", wraps=estimator._engine._preprocess) as mock_preprocess, patch.object( - estimator._engine, "compute_mean_and_std", wraps=estimator._engine.compute_mean_and_std + estimator._engine, "_compute_mean_and_std", wraps=estimator._engine._compute_mean_and_std ) as mock_compute_mean_and_std, ): estimator.estimate(y, clusters) diff --git a/tests/unit/estimators/test_multi_ppi.py b/tests/unit/estimators/test_multi_ppi.py index d86d59f2..7326ced0 100644 --- a/tests/unit/estimators/test_multi_ppi.py +++ b/tests/unit/estimators/test_multi_ppi.py @@ -42,17 +42,17 @@ def test_estimate_delegates(estimator, y_arrays): y_true, y_proxies = y_arrays with ( patch.object(multi_ppi_module, "_validate_non_constant") as mock_validate_non_constant, - patch.object(estimator._engine, "preprocess", wraps=estimator._engine.preprocess) as mock_preprocess, + patch.object(estimator._engine, "_preprocess", wraps=estimator._engine._preprocess) as mock_preprocess, patch.object( - estimator._engine, "fit_tuning_parameter", wraps=estimator._engine.fit_tuning_parameter + estimator._engine, "_fit_tuning_parameter", wraps=estimator._engine._fit_tuning_parameter ) as mock_fit_tuning_parameter, patch.object( - estimator._engine, "compute_mean_and_std", wraps=estimator._engine.compute_mean_and_std + estimator._engine, "_compute_mean_and_std", wraps=estimator._engine._compute_mean_and_std ) as mock_compute_mean_and_std, patch.object( estimator._classical_engine, - "compute_mean_and_std", - wraps=estimator._classical_engine.compute_mean_and_std, + "_compute_mean_and_std", + wraps=estimator._classical_engine._compute_mean_and_std, ) as mock_classical_engine_compute_mean_and_std, ): estimator.estimate(y_true, y_proxies) diff --git a/tests/unit/estimators/test_ppi.py b/tests/unit/estimators/test_ppi.py index 6b88690d..fb7132b0 100644 --- a/tests/unit/estimators/test_ppi.py +++ b/tests/unit/estimators/test_ppi.py @@ -42,17 +42,17 @@ def test_estimate_delegates(estimator, y_arrays): y_true, y_proxy = y_arrays with ( patch.object(ppi_module, "_validate_non_constant") as mock_validate_non_constant, - patch.object(estimator._engine, "preprocess", wraps=estimator._engine.preprocess) as mock_preprocess, + patch.object(estimator._engine, "_preprocess", wraps=estimator._engine._preprocess) as mock_preprocess, patch.object( - estimator._engine, "fit_tuning_parameter", wraps=estimator._engine.fit_tuning_parameter + estimator._engine, "_fit_tuning_parameter", wraps=estimator._engine._fit_tuning_parameter ) as mock_fit_tuning_parameter, patch.object( - estimator._engine, "compute_mean_and_std", wraps=estimator._engine.compute_mean_and_std + estimator._engine, "_compute_mean_and_std", wraps=estimator._engine._compute_mean_and_std ) as mock_compute_mean_and_std, patch.object( estimator._classical_engine, - "compute_mean_and_std", - wraps=estimator._classical_engine.compute_mean_and_std, + "_compute_mean_and_std", + wraps=estimator._classical_engine._compute_mean_and_std, ) as mock_classical_engine_compute_mean_and_std, ): estimator.estimate(y_true, y_proxy) diff --git a/tests/unit/estimators/test_stratified_classical.py b/tests/unit/estimators/test_stratified_classical.py index 56c7c247..742b4cf6 100644 --- a/tests/unit/estimators/test_stratified_classical.py +++ b/tests/unit/estimators/test_stratified_classical.py @@ -44,9 +44,9 @@ def test_init_sets_engine(estimator): def test_estimate_delegates(estimator, y, groups): with ( - patch.object(estimator._engine, "preprocess", wraps=estimator._engine.preprocess) as mock_preprocess, + patch.object(estimator._engine, "_preprocess", wraps=estimator._engine._preprocess) as mock_preprocess, patch.object( - estimator._engine, "compute_mean_and_std", wraps=estimator._engine.compute_mean_and_std + estimator._engine, "_compute_mean_and_std", wraps=estimator._engine._compute_mean_and_std ) as mock_compute_mean_and_std, ): estimator.estimate(y, groups, stratum_weights=np.array([0.8, 0.2])) diff --git a/tests/unit/estimators/test_stratified_ppi.py b/tests/unit/estimators/test_stratified_ppi.py index 9e086d5e..7bd74a93 100644 --- a/tests/unit/estimators/test_stratified_ppi.py +++ b/tests/unit/estimators/test_stratified_ppi.py @@ -45,12 +45,12 @@ def test_init_sets_engine(estimator): def test_estimate_delegates(estimator, y_true, y_proxy, groups): with ( patch.object(stratified_ppi_module, "_validate_non_constant") as mock_validate_non_constant, - patch.object(estimator._engine, "preprocess", wraps=estimator._engine.preprocess) as mock_preprocess, + patch.object(estimator._engine, "_preprocess", wraps=estimator._engine._preprocess) as mock_preprocess, patch.object( - estimator._engine, "fit_tuning_parameter", wraps=estimator._engine.fit_tuning_parameter + estimator._engine, "_fit_tuning_parameter", wraps=estimator._engine._fit_tuning_parameter ) as mock_fit_tuning_parameter, patch.object( - estimator._engine, "compute_mean_and_std", wraps=estimator._engine.compute_mean_and_std + estimator._engine, "_compute_mean_and_std", wraps=estimator._engine._compute_mean_and_std ) as mock_compute_mean_and_std, ): estimator.estimate(y_true, y_proxy, groups) diff --git a/tests/unit/monitors/test_base.py b/tests/unit/monitors/test_base.py index c6248ef5..59378605 100644 --- a/tests/unit/monitors/test_base.py +++ b/tests/unit/monitors/test_base.py @@ -33,7 +33,7 @@ def monitor(): def test_preprocess_subset_delegates(monitor, y_true, y_proxy, batches): mask = ~batches.astype(bool) - with patch.object(monitor._engine, "preprocess", wraps=monitor._engine.preprocess) as mock_preprocess: + with patch.object(monitor._engine, "_preprocess", wraps=monitor._engine._preprocess) as mock_preprocess: monitor._preprocess_subset({"y_true": y_true, "y_proxy": y_proxy}, mask) mock_preprocess.assert_called_once() @@ -49,8 +49,8 @@ def test_detect_delegates(monitor, y_true, y_proxy, batches): with ( patch.object(base_module, "_preprocess", wraps=base_module._preprocess) as mock_preprocess, patch.object(monitor, "_preprocess_subset", wraps=monitor._preprocess_subset) as mock_preprocess_subset, - patch.object(monitor._engine, "fit_tuning_parameter") as mock_fit_tuning_parameter, - patch.object(monitor._engine, "compute_mean_and_std") as mock_compute_mean_and_std, + patch.object(monitor._engine, "_fit_tuning_parameter") as mock_fit_tuning_parameter, + patch.object(monitor._engine, "_compute_mean_and_std") as mock_compute_mean_and_std, patch.object( base_module, "_compute_asymptotic_bounds", wraps=base_module._compute_asymptotic_bounds ) as mock_compute_asymptotic_bounds,