Skip to content

Commit f74c8bc

Browse files
committed
Convert uniform dist validation to exception-based approach
1 parent d861529 commit f74c8bc

2 files changed

Lines changed: 42 additions & 40 deletions

File tree

src/semeio/fmudesign/design_distributions.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,24 @@ def _check_dist_params_lognormal(dist_params: Sequence[str]) -> tuple[bool, str]
6262
return status, msg
6363

6464

65-
def _check_dist_params_uniform(dist_params: Sequence[str]) -> tuple[bool, str]:
65+
def parse_and_validate_uniform_params(
66+
dist_params: Sequence[int | str | float],
67+
) -> tuple[float, float]:
6668
if len(dist_params) != 2:
67-
status = False
68-
msg = (
69-
"Uniform distribution must have 2 parameters, "
70-
"but had " + str(len(dist_params)) + " parameters. "
69+
raise ValueError(
70+
f"Uniform distribution requires exactly 2 parameters, got {len(dist_params)}"
7171
)
72-
elif not (is_number(dist_params[0]) and is_number(dist_params[1])):
73-
status = False
74-
msg = "Parameters for uniform distribution must be numbers. "
75-
elif float(dist_params[1]) < float(dist_params[0]):
76-
status = False
77-
msg = "Uniform distribution must have dist_param2 >= dist_param1"
78-
else:
79-
status = True
80-
msg = ""
81-
82-
return status, msg
72+
try:
73+
low, high = [float(p) for p in dist_params]
74+
except (ValueError, TypeError) as e:
75+
raise ValueError(
76+
f"All parameters must be convertible to numbers. Got: {dist_params}"
77+
) from e
78+
if np.any(np.isnan([low, high])):
79+
raise ValueError(f"Parameters cannot be NaN. Got: low={low}, high={high}")
80+
if high < low:
81+
raise ValueError(f"Parameters must satisfy low <= high, got [{low}, {high}]")
82+
return low, high
8383

8484

8585
def parse_and_validate_triangular_params(
@@ -265,7 +265,7 @@ def draw_values_lognormal(
265265

266266

267267
def draw_values_uniform(
268-
dist_parameters: Sequence[str],
268+
dist_parameters: Sequence[int | str | float],
269269
numreals: int,
270270
rng: np.random.Generator,
271271
normalscoresamples: npt.NDArray[Any] | None = None,
@@ -285,12 +285,8 @@ def draw_values_uniform(
285285
if numreals == 0:
286286
return np.array([])
287287

288-
status, msg = _check_dist_params_uniform(dist_parameters)
289-
if not status:
290-
raise ValueError(msg)
288+
low, high = parse_and_validate_uniform_params(dist_parameters)
291289

292-
low = float(dist_parameters[0])
293-
high = float(dist_parameters[1])
294290
uscale = high - low
295291

296292
if normalscoresamples is not None:

tests/fmudesign/test_design_distributions.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,29 @@ def test_check_dist_params_lognormal():
4646
assert dists._check_dist_params_lognormal([0, 0])[0] # edge case
4747

4848

49-
def test_check_dist_params_uniform():
50-
"""Test lognormal dist param checker"""
51-
assert not dists._check_dist_params_uniform([])[0]
52-
assert not dists._check_dist_params_uniform(())[0]
53-
54-
assert not dists._check_dist_params_uniform([0])[0]
55-
assert not dists._check_dist_params_uniform([0, 0, 0])[0]
49+
def test_parse_and_validate_uniform_params():
50+
"""Test uniform distribution parameter validation"""
51+
# Test wrong number of parameters
52+
with pytest.raises(ValueError, match="requires exactly 2 parameters"):
53+
dists.parse_and_validate_uniform_params([])
54+
with pytest.raises(ValueError, match="requires exactly 2 parameters"):
55+
dists.parse_and_validate_uniform_params(())
56+
with pytest.raises(ValueError, match="requires exactly 2 parameters"):
57+
dists.parse_and_validate_uniform_params([0])
58+
with pytest.raises(ValueError, match="requires exactly 2 parameters"):
59+
dists.parse_and_validate_uniform_params([0, 0, 0])
5660

57-
assert not dists._check_dist_params_uniform(["mean", "mu"])[0]
61+
# Test non-numeric parameters
62+
with pytest.raises(ValueError, match="must be convertible to numbers"):
63+
dists.parse_and_validate_uniform_params(["mean", "mu"])
5864

59-
assert dists._check_dist_params_uniform([0, 1])[0]
60-
assert not dists._check_dist_params_uniform([0, -1])[0]
65+
# Test invalid parameter ordering
66+
with pytest.raises(ValueError, match="must satisfy low <= high"):
67+
dists.parse_and_validate_uniform_params([0, -1])
6168

62-
assert dists._check_dist_params_uniform([0, 0])[0] # edge case
69+
# Test valid parameters
70+
assert dists.parse_and_validate_uniform_params([0, 1]) == (0.0, 1.0)
71+
assert dists.parse_and_validate_uniform_params([0, 0]) == (0.0, 0.0) # edge case
6372

6473

6574
def test_validate_triangular_params():
@@ -188,20 +197,17 @@ def test_draw_values_uniform():
188197
assert all(isinstance(value, numbers.Number) for value in values)
189198
assert all(10 <= value <= 100 for value in values)
190199

200+
# Updated to match new error messages
191201
with pytest.raises(
192202
ValueError,
193-
match="Uniform distribution must have 2 parameters, but had 3 parameters.",
203+
match="requires exactly 2 parameters, got 3",
194204
):
195205
values = dists.draw_values_uniform([10, 50, 100], 10, rng)
196206

197-
with pytest.raises(
198-
ValueError, match="Uniform distribution must have dist_param2 >= dist_param1"
199-
):
207+
with pytest.raises(ValueError, match="must satisfy low <= high"):
200208
values = dists.draw_values_uniform([50, 10], 10, rng)
201209

202-
with pytest.raises(
203-
ValueError, match="Parameters for uniform distribution must be numbers."
204-
):
210+
with pytest.raises(ValueError, match="must be convertible to numbers"):
205211
values = dists.draw_values_uniform(["a", 10], 10, rng)
206212

207213
with pytest.raises(ValueError, match="numreal must be a positive integer"):

0 commit comments

Comments
 (0)