Skip to content
Merged
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
10 changes: 3 additions & 7 deletions src/phonometry/vibration/human/multiple_shock.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))


Expand Down Expand Up @@ -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)
Expand Down
17 changes: 9 additions & 8 deletions tests/vibration/human/test_multiple_shock_vibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)