diff --git a/CHANGELOG.md b/CHANGELOG.md index b317b16c9..8a5fe34ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -999,6 +999,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ### Changed +- The multiple-shock time guards go through `require_positive` like the rest + of the library. They were written as `not t > 0.0`, which rejects NaN where + `t <= 0.0` would accept it, and that reason lived in a comment. The shared + validator says the same thing in the form the whole package uses, rejects + infinities too, and names the parameter that failed instead of both at once. + - `phonometry.vibration` has three families, by who reads them. `vibration.structural` is the structural acoustics that feeds building prediction: mobility (ISO 7626), plate junctions, radiation efficiency, diff --git a/src/phonometry/vibration/human/multiple_shock.py b/src/phonometry/vibration/human/multiple_shock.py index d0e3f73cf..b0f9913c9 100644 --- a/src/phonometry/vibration/human/multiple_shock.py +++ b/src/phonometry/vibration/human/multiple_shock.py @@ -252,10 +252,8 @@ def daily_dose(dose: float, exposure_time: float, measurement_time: float) -> fl was measured (same unit as ``exposure_time``). :return: The daily dose :math:`D_{zd} = D_z (t_d/t_m)^{1/6}`, m/s2. """ - # Negated ">" rather than "<=" on purpose: it rejects NaN as well, which - # the opposite operator would let through. - if not measurement_time > 0.0 or not exposure_time > 0.0: # NOSONAR - NaN - raise ValueError("exposure_time and measurement_time must be positive.") + exposure_time = require_positive(exposure_time, "exposure_time") + measurement_time = require_positive(measurement_time, "measurement_time") return float(dose * (exposure_time / measurement_time) ** (1.0 / DOSE_EXPONENT)) @@ -358,9 +356,7 @@ def injury_risk( require_choice(sex, "sex", _SEXES) if years <= 0: raise ValueError("years must be a positive integer.") - # Negated ">" rather than "<=" on purpose: it rejects NaN as well. - if not days_per_year > 0.0: # NOSONAR - NaN - raise ValueError("days_per_year must be positive.") + days_per_year = require_positive(days_per_year, "days_per_year") mz = _mz_for_sex(sex) if mz is None else mz s_stat = static_stress(mz) ages = start_age + np.arange(years, dtype=np.float64) diff --git a/tests/vibration/human/test_multiple_shock_vibration.py b/tests/vibration/human/test_multiple_shock_vibration.py index 5abd570b6..051e9c74a 100644 --- a/tests/vibration/human/test_multiple_shock_vibration.py +++ b/tests/vibration/human/test_multiple_shock_vibration.py @@ -230,11 +230,12 @@ def test_response_peaks_rejects_2d() -> None: with pytest.raises(ValueError, match="1-D time series"): v.response_peaks(np.zeros((2, 100))) -def test_the_time_guards_reject_nan() -> None: - """``not t > 0`` is deliberate: ``t <= 0`` would let NaN through.""" - with pytest.raises(ValueError, match="must be positive"): - v.daily_dose(1.0, exposure_time=math.nan, measurement_time=1.0) - with pytest.raises(ValueError, match="must be positive"): - v.daily_dose(1.0, exposure_time=1.0, measurement_time=math.nan) - with pytest.raises(ValueError, match="days_per_year must be positive"): - v.injury_risk(0.5, start_age=20.0, years=20, days_per_year=math.nan) +def test_the_time_guards_reject_nan_and_infinity() -> None: + """The guards go through require_positive, which rejects both.""" + for bad in (math.nan, math.inf): + with pytest.raises(ValueError, match="'exposure_time' must be positive"): + v.daily_dose(1.0, exposure_time=bad, measurement_time=1.0) + with pytest.raises(ValueError, match="'measurement_time' must be positive"): + v.daily_dose(1.0, exposure_time=1.0, measurement_time=bad) + with pytest.raises(ValueError, match="'days_per_year' must be positive"): + v.injury_risk(0.5, start_age=20.0, years=20, days_per_year=bad)