From 0b21f48f0c44d9c536e102976e053a64ba945ca7 Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 10:53:11 +0900 Subject: [PATCH 1/9] fix: Update type hints for cdf and icdf methods to accept int and float types about PEP484 --- src/cenreg/distribution/cdf.py | 8 ++++---- src/cenreg/distribution/quantile.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cenreg/distribution/cdf.py b/src/cenreg/distribution/cdf.py index db888e1..982cc0e 100644 --- a/src/cenreg/distribution/cdf.py +++ b/src/cenreg/distribution/cdf.py @@ -73,7 +73,7 @@ def __init__( self.interpolate = interpolate self.confidence_interval = confidence_interval - def cdf(self, y: float | np.ndarray): + def cdf(self, y: int | float | np.ndarray): """ Cumulative distribution function (i.e., inverse of quantile function). @@ -87,6 +87,8 @@ def cdf(self, y: float | np.ndarray): cum_p : np.ndarray CDF values for each value in y. """ + if isinstance(y, int | float): + y = np.array([y]) if self.cum_p.ndim == 1: assert y.ndim == 1 @@ -95,8 +97,6 @@ def cdf(self, y: float | np.ndarray): else: raise ValueError("cum_p must be one-dimensional or two-dimensional.") - if isinstance(y, float): - y = np.array([y]) if self.cum_p.ndim == 2 and y.ndim == 1: y = np.tile(y, (self.cum_p.shape[0], 1)) @@ -154,7 +154,7 @@ def icdf(self, quantiles: float | np.ndarray) -> np.ndarray: Compute inverse CDF values for each value in quantiles. """ - if isinstance(quantiles, float): + if isinstance(quantiles, int | float): quantiles = np.array([quantiles]) if np.any(quantiles < 0.0): raise ValueError("quantiles must be non-negative.") diff --git a/src/cenreg/distribution/quantile.py b/src/cenreg/distribution/quantile.py index b2101f7..7cd2f08 100644 --- a/src/cenreg/distribution/quantile.py +++ b/src/cenreg/distribution/quantile.py @@ -61,7 +61,7 @@ def cdf(self, y: float | np.ndarray): CDF values for each value in y. Array shape is equal to the shape of y. """ - if isinstance(y, float): + if isinstance(y, int | float): y = np.array([y]) if self.interpolate == "linear": @@ -97,7 +97,7 @@ def icdf(self, quantiles: float | np.ndarray) -> np.ndarray: Array shape is equal to the shape of quantiles. """ - if isinstance(quantiles, float): + if isinstance(quantiles, int | float): quantiles = np.array([quantiles]) if np.any(quantiles < 0.0): raise ValueError("quantiles must be non-negative.") From e9821dba871ec2666c70bf950f7ebec94ca96cc7 Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 11:10:40 +0900 Subject: [PATCH 2/9] fix: Update type hint for interpolate parameter to use Literal for specific string values --- src/cenreg/distribution/cdf.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cenreg/distribution/cdf.py b/src/cenreg/distribution/cdf.py index 982cc0e..797dfbc 100644 --- a/src/cenreg/distribution/cdf.py +++ b/src/cenreg/distribution/cdf.py @@ -1,5 +1,6 @@ import numpy as np +from typing import Literal from cenreg.distribution.interpolate import linear_interpolation @@ -13,7 +14,7 @@ def __init__( b: np.ndarray, p: np.ndarray | None = None, cum_p: np.ndarray | None = None, - interpolate: str = "linear", + interpolate: Literal["linear", "left", "right"] = "linear", confidence_interval: np.ndarray | None = None, ): """ @@ -31,7 +32,7 @@ def __init__( Cumulative probability distribution. cum_p must be one-dimensional or two-dimensional. If both p and cum_p are given, cum_p is used. - interpolate : str + interpolate : Literal["linear", "left", "right"] 'linear', 'left', or 'right' indicating the interpolation method. If 'linear' is set, linear interpolation is used. If 'left' is set, the CDF value at the left edge of each bin is used. From 26fcdfd41b5e83f04949b39704a59043fcabfeec Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 11:10:52 +0900 Subject: [PATCH 3/9] fix: Comment out unused attributes in kaplan_meier_estimator function --- src/cenreg/model/nonparametric.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cenreg/model/nonparametric.py b/src/cenreg/model/nonparametric.py index 0f3b349..58767e2 100644 --- a/src/cenreg/model/nonparametric.py +++ b/src/cenreg/model/nonparametric.py @@ -205,8 +205,8 @@ def kaplan_meier_estimator( else: survival_rates = survival_rates[:-1] dist = CumulativeDist(b=b, cum_p=1.0 - survival_rates, interpolate="right") - dist.alive = num_alive - dist.dead = num_death + # dist.alive = num_alive + # dist.dead = num_death return dist From c4d5edd513b9fdc9f3e3334813276ba4989fdca0 Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 11:24:08 +0900 Subject: [PATCH 4/9] fix: Update init_f parameter in MseModel constructor to be required --- src/cenreg/pytorch/cjd2F.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cenreg/pytorch/cjd2F.py b/src/cenreg/pytorch/cjd2F.py index 2a4e0e1..9366762 100644 --- a/src/cenreg/pytorch/cjd2F.py +++ b/src/cenreg/pytorch/cjd2F.py @@ -14,9 +14,9 @@ def __init__( self, jd_pred: np.ndarray, copula, + init_f: np.ndarray, learning_rate: float = 0.01, focal_risk: int = -1, - init_f: np.ndarray | None = None, optimizer=None, ): super().__init__() From 742348f43823fec5e319bbd48790f6aeebe2e6c6 Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 11:29:54 +0900 Subject: [PATCH 5/9] fix: Update type hint for idx_list parameter to use nested list for better clarity --- src/cenreg/pytorch/cjd2F.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cenreg/pytorch/cjd2F.py b/src/cenreg/pytorch/cjd2F.py index 9366762..d2c41b2 100644 --- a/src/cenreg/pytorch/cjd2F.py +++ b/src/cenreg/pytorch/cjd2F.py @@ -61,7 +61,7 @@ def _copula_sum_sub( self, F_pred: torch.Tensor, c, - idx_list: list[int], + idx_list: list[list[int]], i: int, k: int, idx_list_use_Ft: Sequence[int], From 310f04dbee9cdc2b977e92ac2db5aee402d8729f Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 11:31:04 +0900 Subject: [PATCH 6/9] fix: Add assertion to ensure path is not None before loading checkpoint --- src/cenreg/pytorch/cjd2F.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cenreg/pytorch/cjd2F.py b/src/cenreg/pytorch/cjd2F.py index d2c41b2..fcd180f 100644 --- a/src/cenreg/pytorch/cjd2F.py +++ b/src/cenreg/pytorch/cjd2F.py @@ -235,6 +235,7 @@ def minimize_mse(model, num_epochs: int) -> np.ndarray: loss.backward() optimizer.step() + assert path is not None checkpoint = torch.load(path) model.load_state_dict(checkpoint["model_state_dict"]) model.eval() From a3302a0336997a5f3031a85dc9d0de228aba3298 Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 11:31:52 +0900 Subject: [PATCH 7/9] fix: Move import statement for Literal to the top of the file --- src/cenreg/distribution/cdf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cenreg/distribution/cdf.py b/src/cenreg/distribution/cdf.py index 797dfbc..78b98ef 100644 --- a/src/cenreg/distribution/cdf.py +++ b/src/cenreg/distribution/cdf.py @@ -1,6 +1,7 @@ +from typing import Literal + import numpy as np -from typing import Literal from cenreg.distribution.interpolate import linear_interpolation From 45dab573ec16d2eb8da51719ea28ea657645a24e Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 13:40:43 +0900 Subject: [PATCH 8/9] fix: Ensure float dtype for single values in cdf and icdf methods; add assertion for positive num_epochs in minimize_mse function --- src/cenreg/distribution/cdf.py | 4 ++-- src/cenreg/distribution/quantile.py | 2 +- src/cenreg/pytorch/cjd2F.py | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cenreg/distribution/cdf.py b/src/cenreg/distribution/cdf.py index 78b98ef..ee43381 100644 --- a/src/cenreg/distribution/cdf.py +++ b/src/cenreg/distribution/cdf.py @@ -90,7 +90,7 @@ def cdf(self, y: int | float | np.ndarray): CDF values for each value in y. """ if isinstance(y, int | float): - y = np.array([y]) + y = np.array([y], dtype=float) if self.cum_p.ndim == 1: assert y.ndim == 1 @@ -157,7 +157,7 @@ def icdf(self, quantiles: float | np.ndarray) -> np.ndarray: """ if isinstance(quantiles, int | float): - quantiles = np.array([quantiles]) + quantiles = np.array([quantiles], dtype=float) if np.any(quantiles < 0.0): raise ValueError("quantiles must be non-negative.") if np.any(quantiles > 1.0): diff --git a/src/cenreg/distribution/quantile.py b/src/cenreg/distribution/quantile.py index 7cd2f08..e053433 100644 --- a/src/cenreg/distribution/quantile.py +++ b/src/cenreg/distribution/quantile.py @@ -62,7 +62,7 @@ def cdf(self, y: float | np.ndarray): Array shape is equal to the shape of y. """ if isinstance(y, int | float): - y = np.array([y]) + y = np.array([y], dtype=float) if self.interpolate == "linear": # linear interpolation implementation diff --git a/src/cenreg/pytorch/cjd2F.py b/src/cenreg/pytorch/cjd2F.py index fcd180f..a79a211 100644 --- a/src/cenreg/pytorch/cjd2F.py +++ b/src/cenreg/pytorch/cjd2F.py @@ -187,6 +187,7 @@ def minimize_mse(model, num_epochs: int) -> np.ndarray: F_pred: estimated CDF. np.ndarray of shape [batch_size, num_risks, num_bin_predictions+1] """ + assert num_epochs > 0 best_epoch = -1 best_loss = float("inf") From 0ef9083a336fd2d4c48b3b58307138db8319736d Mon Sep 17 00:00:00 2001 From: Seiichiro Yoshioka Date: Tue, 26 May 2026 17:26:07 +0900 Subject: [PATCH 9/9] fix: Update init_f parameter in MseModel constructor to be optional and add shape validation --- src/cenreg/pytorch/cjd2F.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cenreg/pytorch/cjd2F.py b/src/cenreg/pytorch/cjd2F.py index a79a211..b487fc3 100644 --- a/src/cenreg/pytorch/cjd2F.py +++ b/src/cenreg/pytorch/cjd2F.py @@ -14,19 +14,20 @@ def __init__( self, jd_pred: np.ndarray, copula, - init_f: np.ndarray, learning_rate: float = 0.01, focal_risk: int = -1, + init_f: np.ndarray | None = None, optimizer=None, ): super().__init__() - assert len(init_f.shape) == 3 + if init_f is not None: + assert len(init_f.shape) == 3 assert len(jd_pred.shape) == 3 self.jd_pred = torch.tensor(jd_pred, dtype=torch.float32).detach() self.focal_risk = focal_risk self.fc = nn.Linear(1, jd_pred.size, bias=False) - self.shape = init_f.shape + self.shape = init_f.shape if init_f is not None else jd_pred.shape self.copula = copula self.learning_rate = learning_rate if init_f is not None: