diff --git a/.github/labeler.yml b/.github/labeler.yml index acb35543f..a7b3a649f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -32,7 +32,6 @@ figures: - scripts/check_figures.py - scripts/generated_assets.py - src/phonometry/_plot/** - - src/phonometry/_plotting.py - requirements-figures.txt reports: diff --git a/CHANGELOG.md b/CHANGELOG.md index 408bb055e..b1082654d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1061,6 +1061,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/). from the top level; from `phonometry.filters` it still resolves until 5.0, with the usual notice. +- The eighteen domain packages are named explicitly in `phonometry/__init__.py` + rather than bound as a side effect of importing the flat API. Nothing changes + at runtime, where `phonometry.building` already resolved; what changes is + that a type checker can follow it, which the removal of the package-level + `__getattr__` shim would otherwise have taken away. + - `phonometry.underwater` has three families, along the three questions an underwater problem asks. `underwater.sources` is what makes the sound: ISO 17208 ship radiated noise, shipping traffic, impact pile driving and the @@ -1866,6 +1872,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/). ### Removed +- The 3.1 renames, at the release their notices named. The function aliases + `octavefilter`, `getansifrequencies`, `normalizedfreq` and + `calculate_sensitivity` are gone; use `octave_filter`, `nominal_frequencies`, + `normalized_frequencies` and `sensitivity`. The ISO 12999-1 pair that + shadowed the GUM functions at the package root, the bare `coverage_factor` + and `expanded_uncertainty`, are gone; use `insulation_coverage_factor` and + `insulation_expanded_uncertainty`, and read the GUM pair from + `phonometry.metrology.uncertainty`. The renamed constants + `OCTAVE_BANDS_HZ`, `THIRD_OCTAVE_BANDS_HZ`, `BASE_PLATE_BANDS_HZ`, + `BAND_CENTRES` and `ExposureWarning` are gone; use `OCTAVE_BANDS`, + `THIRD_OCTAVE_BANDS`, `BASE_PLATE_BANDS`, `BAND_CENTERS` and + `OccupationalExposureWarning`. The deprecated keywords are gone too: + `sample_rate` is `fs` in the ISO 13472 functions, `humidity` is + `relative_humidity` in the ISO 9613 ones, and `room_volume` is `volume` in + the ISO 3744 pair. + + `phonometry._plotting`, the 3.2 re-export of the renderers that moved to + `phonometry._plot`, is gone with them. + - The flat pre-3.2 module paths, as 3.2 announced when it deprecated them: `phonometry.levels`, `phonometry.insulation`, `phonometry.room_ir` and the eighty-odd siblings that the modularization grouped into domain subpackages diff --git a/docs/api-reference.md b/docs/api-reference.md index 2a9149a1d..9ca8c1210 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -1234,7 +1234,6 @@ well. The pre-3.2 flat paths, written without a subpackage, were removed in | `FilterBankWarning` | `warning class` | **Fractional-octave filter-bank advisory.**
Emitted for filter-bank processing pitfalls | `warnings.simplefilter('error', FilterBankWarning)` | | `TonalityWarning` | `warning class` | **Tonality advisory.**
Emitted for biased tonality estimates (e.g. coarse FFT resolution) | `warnings.simplefilter('error', TonalityWarning)` | | `STIWarning` | `warning class` | **STI/STIPA advisory.**
Emitted for suspect speech-intelligibility measurements or inputs | `warnings.simplefilter('error', STIWarning)` | -| `octavefilter` / `getansifrequencies` / `normalizedfreq` / `calculate_sensitivity` / `coverage_factor` / `expanded_uncertainty` | `function` | **Deprecated aliases (warn on use; removal in 4.0).**
New names: `octave_filter`, `nominal_frequencies`, `normalized_frequencies`, `sensitivity`, `insulation_coverage_factor`, `insulation_expanded_uncertainty` | `octave_filter(x, fs) # not octavefilter` | | `__version__` | `str` | **Package version string.**
(no parameters) | `phonometry.__version__ # '3.2.0'` | | `.plot()` | `method` | **One-line canonical figure on every result object (soft matplotlib dependency).**
Available on `ZwickerLoudness`, `MooreGlasbergLoudness`, `MooreGlasbergTimeVaryingLoudness`, `EcmaLoudness`, `EcmaTonality`, `EcmaRoughness`, `PsychoacousticAnnoyanceResult`, `FluctuationStrengthResult`, `ProgramLoudnessResult`, `KWeightingResponse`, `STIResult`, `SIIResult`, `SIIProcedure`, `StandardSpeechSpectrum`, `NCResult`, `RCResult`, `AgeThresholdResult`, `NiptsResult`, `HtlanResult`, `ImpulseProminenceResult`, `ImpulsiveSoundResult`, `MultipleShockResult`, `ImpulseResponseResult`, `DecayCurve`, `RoomAcousticsResult`, `ReverberationResult`, `ReverberationModelResult`, `DynamicStiffnessResult`, `MobilityResult`, `TransferStiffnessResult`, `VibrationSoundPowerResult`, `StructureBornePowerResult`, `InstalledSourceResult`, `WeightedRatingResult`, `ImpactRatingResult`, `FacadeInsulationResult`, `LabAirborneInsulationResult`, `LabImpactInsulationResult`, `SoundPowerResult`, `ReverberationSoundPowerResult`, `SoundPowerIntensityResult`, `PrecisionSoundPowerResult`, `PrecisionIntensityResult`, `IntensityResult`, `UncertaintyResult`, `AbsorptionRatingResult`, `ScatteringResult`, `DiffusionResult`, `DiffusionSpectrum`, `InsituAbsorptionResult`, `WeightingResponse`, `WeightedSpectrum` and `DailyVibrationExposure`.
• `ax`: existing Axes, or None to build a fresh figure (Default: None)
• returns the Matplotlib `Axes` (an array of Axes for multi-panel figures); never calls `plt.show()`
• needs matplotlib (`pip install phonometry[plot]`) | `res.plot()`
`decay_curve(ir, fs).plot()` | @@ -1252,12 +1251,15 @@ well. The pre-3.2 flat paths, written without a subpackage, were removed in - `octave_filter()` caches filter bank designs internally (32 entries), so repeated calls with the same parameters skip the design phase. For explicit control use `OctaveFilterBank`. -- Deprecated aliases (kept for one cycle, warn on use, removal in 4.0): - `octavefilter` → `octave_filter`, `getansifrequencies` → - `nominal_frequencies`, `normalizedfreq` → `normalized_frequencies`, - `calculate_sensitivity` → `sensitivity`, `coverage_factor` → - `insulation_coverage_factor`, `expanded_uncertainty` → - `insulation_expanded_uncertainty`, plus the renamed names - `OCTAVE_BANDS_HZ` → `OCTAVE_BANDS`, `THIRD_OCTAVE_BANDS_HZ` → - `THIRD_OCTAVE_BANDS`, `BASE_PLATE_BANDS_HZ` → `BASE_PLATE_BANDS` and - `ExposureWarning` → `OccupationalExposureWarning`. +- The 3.1 aliases are gone, as their notices said they would be in 4.0: + `octavefilter`, `getansifrequencies`, `normalizedfreq`, + `calculate_sensitivity`, the bare `coverage_factor` and + `expanded_uncertainty` of ISO 12999-1, the `OCTAVE_BANDS_HZ`, + `THIRD_OCTAVE_BANDS_HZ` and `BASE_PLATE_BANDS_HZ` constants, + `BAND_CENTRES`, `ExposureWarning`, and the `sample_rate`, `humidity` and + `room_volume` keywords. Use `octave_filter`, `nominal_frequencies`, + `normalized_frequencies`, `sensitivity`, `insulation_coverage_factor`, + `insulation_expanded_uncertainty`, `OCTAVE_BANDS`, `THIRD_OCTAVE_BANDS`, + `BASE_PLATE_BANDS`, `phonometry.speech.sii.BAND_CENTERS`, + `OccupationalExposureWarning`, `fs`, + `relative_humidity` and `volume`. diff --git a/llms-full.txt b/llms-full.txt index d7b08f935..527482b27 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -3447,7 +3447,6 @@ well. The pre-3.2 flat paths, written without a subpackage, were removed in | `FilterBankWarning` | `warning class` | **Fractional-octave filter-bank advisory.**
Emitted for filter-bank processing pitfalls | `warnings.simplefilter('error', FilterBankWarning)` | | `TonalityWarning` | `warning class` | **Tonality advisory.**
Emitted for biased tonality estimates (e.g. coarse FFT resolution) | `warnings.simplefilter('error', TonalityWarning)` | | `STIWarning` | `warning class` | **STI/STIPA advisory.**
Emitted for suspect speech-intelligibility measurements or inputs | `warnings.simplefilter('error', STIWarning)` | -| `octavefilter` / `getansifrequencies` / `normalizedfreq` / `calculate_sensitivity` / `coverage_factor` / `expanded_uncertainty` | `function` | **Deprecated aliases (warn on use; removal in 4.0).**
New names: `octave_filter`, `nominal_frequencies`, `normalized_frequencies`, `sensitivity`, `insulation_coverage_factor`, `insulation_expanded_uncertainty` | `octave_filter(x, fs) # not octavefilter` | | `__version__` | `str` | **Package version string.**
(no parameters) | `phonometry.__version__ # '3.2.0'` | | `.plot()` | `method` | **One-line canonical figure on every result object (soft matplotlib dependency).**
Available on `ZwickerLoudness`, `MooreGlasbergLoudness`, `MooreGlasbergTimeVaryingLoudness`, `EcmaLoudness`, `EcmaTonality`, `EcmaRoughness`, `PsychoacousticAnnoyanceResult`, `FluctuationStrengthResult`, `ProgramLoudnessResult`, `KWeightingResponse`, `STIResult`, `SIIResult`, `SIIProcedure`, `StandardSpeechSpectrum`, `NCResult`, `RCResult`, `AgeThresholdResult`, `NiptsResult`, `HtlanResult`, `ImpulseProminenceResult`, `ImpulsiveSoundResult`, `MultipleShockResult`, `ImpulseResponseResult`, `DecayCurve`, `RoomAcousticsResult`, `ReverberationResult`, `ReverberationModelResult`, `DynamicStiffnessResult`, `MobilityResult`, `TransferStiffnessResult`, `VibrationSoundPowerResult`, `StructureBornePowerResult`, `InstalledSourceResult`, `WeightedRatingResult`, `ImpactRatingResult`, `FacadeInsulationResult`, `LabAirborneInsulationResult`, `LabImpactInsulationResult`, `SoundPowerResult`, `ReverberationSoundPowerResult`, `SoundPowerIntensityResult`, `PrecisionSoundPowerResult`, `PrecisionIntensityResult`, `IntensityResult`, `UncertaintyResult`, `AbsorptionRatingResult`, `ScatteringResult`, `DiffusionResult`, `DiffusionSpectrum`, `InsituAbsorptionResult`, `WeightingResponse`, `WeightedSpectrum` and `DailyVibrationExposure`.
• `ax`: existing Axes, or None to build a fresh figure (Default: None)
• returns the Matplotlib `Axes` (an array of Axes for multi-panel figures); never calls `plt.show()`
• needs matplotlib (`pip install phonometry[plot]`) | `res.plot()`
`decay_curve(ir, fs).plot()` | @@ -3465,15 +3464,18 @@ well. The pre-3.2 flat paths, written without a subpackage, were removed in - `octave_filter()` caches filter bank designs internally (32 entries), so repeated calls with the same parameters skip the design phase. For explicit control use `OctaveFilterBank`. -- Deprecated aliases (kept for one cycle, warn on use, removal in 4.0): - `octavefilter` → `octave_filter`, `getansifrequencies` → - `nominal_frequencies`, `normalizedfreq` → `normalized_frequencies`, - `calculate_sensitivity` → `sensitivity`, `coverage_factor` → - `insulation_coverage_factor`, `expanded_uncertainty` → - `insulation_expanded_uncertainty`, plus the renamed names - `OCTAVE_BANDS_HZ` → `OCTAVE_BANDS`, `THIRD_OCTAVE_BANDS_HZ` → - `THIRD_OCTAVE_BANDS`, `BASE_PLATE_BANDS_HZ` → `BASE_PLATE_BANDS` and - `ExposureWarning` → `OccupationalExposureWarning`. +- The 3.1 aliases are gone, as their notices said they would be in 4.0: + `octavefilter`, `getansifrequencies`, `normalizedfreq`, + `calculate_sensitivity`, the bare `coverage_factor` and + `expanded_uncertainty` of ISO 12999-1, the `OCTAVE_BANDS_HZ`, + `THIRD_OCTAVE_BANDS_HZ` and `BASE_PLATE_BANDS_HZ` constants, + `BAND_CENTRES`, `ExposureWarning`, and the `sample_rate`, `humidity` and + `room_volume` keywords. Use `octave_filter`, `nominal_frequencies`, + `normalized_frequencies`, `sensitivity`, `insulation_coverage_factor`, + `insulation_expanded_uncertainty`, `OCTAVE_BANDS`, `THIRD_OCTAVE_BANDS`, + `BASE_PLATE_BANDS`, `phonometry.speech.sii.BAND_CENTERS`, + `OccupationalExposureWarning`, `fs`, + `relative_humidity` and `volume`. --- diff --git a/site/src/content/docs/reference/api/building/uncertainty.md b/site/src/content/docs/reference/api/building/uncertainty.md index c77feb1a9..ea8546e87 100644 --- a/site/src/content/docs/reference/api/building/uncertainty.md +++ b/site/src/content/docs/reference/api/building/uncertainty.md @@ -153,14 +153,6 @@ coefficients, also the model/reality combination of Formula (A.2). | :--- | :--- | | ValueError | No components, or a negative component. | -## coverage_factor - -```python -coverage_factor(confidence: float = 0.95, one_sided: bool = False) -> float -``` - -Deprecated alias of [`insulation_coverage_factor`](/phonometry/reference/api/building/uncertainty/#insulation_coverage_factor). - ## COVERAGE_FACTORS *Constant* (`mappingproxy`). @@ -169,18 +161,6 @@ Deprecated alias of [`insulation_coverage_factor`](/phonometry/reference/api/bui COVERAGE_FACTORS = {(0.68, False): 1.0, (0.8, False): 1.28, (0.9, False): 1.65, (0.95, False): 1.96, (0.99, False): 2.58, (0.999, False): 3.29, (0.84, True): 1.0, (0.9, True): 1.28, (0.95, True): 1.65, (0.975, True): 1.96, (0.995, True): 2.58, (0.9995, True): 3.29} ``` -## expanded_uncertainty - -```python -expanded_uncertainty( - u: float, - coverage: float = 0.95, - one_sided: bool = False, -) -> float -``` - -Deprecated alias of [`insulation_expanded_uncertainty`](/phonometry/reference/api/building/uncertainty/#insulation_expanded_uncertainty). - ## insulation_coverage_factor ```python diff --git a/site/src/content/docs/reference/api/environment/outdoor-propagation.md b/site/src/content/docs/reference/api/environment/outdoor-propagation.md index b6d5f8491..91b177974 100644 --- a/site/src/content/docs/reference/api/environment/outdoor-propagation.md +++ b/site/src/content/docs/reference/api/environment/outdoor-propagation.md @@ -57,8 +57,6 @@ atmospheric_absorption( temperature: float = 20.0, relative_humidity: float | None = None, pressure: float = 101.325, - *, - humidity: float | str = 'deprecated', ) -> NDArray[np.float64] ``` @@ -87,7 +85,6 @@ the nearest exact midband. | `temperature` | Air temperature, in degrees Celsius. | | `relative_humidity` | Relative humidity, in percent (default 70). | | `pressure` | Atmospheric pressure, in kilopascals. | -| `humidity` | Deprecated alias of `relative_humidity` (remove in 4.0). | **Returns:** `Aatm` per band, in decibels. @@ -385,8 +382,6 @@ outdoor_propagation_attenuation( relative_humidity: float | None = None, pressure: float = 101.325, projected_distance: float | None = None, - *, - humidity: float | str = 'deprecated', ) -> OutdoorAttenuation ``` @@ -417,7 +412,6 @@ barrier $A_{bar} = D_z$ | `relative_humidity` | Relative humidity, in percent (default 70). | | `pressure` | Atmospheric pressure, in kilopascals. | | `projected_distance` | Ground-plane projected distance `dp`, in metres; defaults to $\sqrt{d^2 - (h_s - h_r)^2}$. | -| `humidity` | Deprecated alias of `relative_humidity` (remove in 4.0). | **Returns:** [`OutdoorAttenuation`](/phonometry/reference/api/environment/outdoor-propagation/#outdoorattenuation) with the per-band term breakdown. @@ -549,8 +543,6 @@ predicted_receiver_level( d_omega: float = 0.0, c0: float | None = None, projected_distance: float | None = None, - *, - humidity: float | str = 'deprecated', ) -> NDArray[np.float64] ``` @@ -588,7 +580,6 @@ convenience. | `d_omega` | Solid-angle index `DOmega`, in decibels (see [`directivity_omega`](/phonometry/reference/api/environment/outdoor-propagation/#directivity_omega) for the alternative ground method). | | `c0` | Meteorological factor `C0`, in decibels; `None` returns the downwind level `LfT(DW)` ($C_{met} = 0$). | | `projected_distance` | Ground-plane projected distance `dp`, in metres. | -| `humidity` | Deprecated alias of `relative_humidity` (remove in 4.0). | **Returns:** Predicted octave-band level per frequency, in decibels. diff --git a/site/src/content/docs/reference/api/filters/core.md b/site/src/content/docs/reference/api/filters/core.md index e2a45c5cf..e9af2382f 100644 --- a/site/src/content/docs/reference/api/filters/core.md +++ b/site/src/content/docs/reference/api/filters/core.md @@ -67,14 +67,6 @@ Multichannel support: If x is 2D (channels, samples), each channel is filtered. **Returns:** A tuple containing (SPL_array, Frequencies_list) or (SPL_array, Frequencies_list, signals). When *nominal=True*, the frequency list contains `List[str]` labels instead of floats. (*Union[Tuple[np.ndarray, List[float]], Tuple[np.ndarray, List[str]], Tuple[np.ndarray, List[float], List[np.ndarray]], Tuple[np.ndarray, List[str], List[np.ndarray]]]*) -## octavefilter - -```python -octavefilter(*args: Any, **kwargs: Any) -> Any -``` - -Deprecated alias of [`octave_filter`](/phonometry/reference/api/filters/core/#octave_filter). - ## OctaveFilterBank ```python diff --git a/site/src/content/docs/reference/api/filters/frequencies.md b/site/src/content/docs/reference/api/filters/frequencies.md index de6ff7239..4e3e0a8e6 100644 --- a/site/src/content/docs/reference/api/filters/frequencies.md +++ b/site/src/content/docs/reference/api/filters/frequencies.md @@ -9,17 +9,6 @@ Frequency calculation logic according to ANSI/IEC standards. > Auto-generated from the source docstrings by `scripts/generate_api_docs.py` (`make api-docs`). Do not edit by hand. -## getansifrequencies - -```python -getansifrequencies( - fraction: float, - limits: list[float] | None = None, -) -> tuple[list[float], list[float], list[float], list[str]] -``` - -Deprecated alias of [`nominal_frequencies`](/phonometry/reference/api/filters/frequencies/#nominal_frequencies). - ## nominal_frequencies ```python @@ -55,11 +44,3 @@ Get standardized IEC center frequencies. | `fraction` | 1 or 3 (Octave or 1/3 Octave). | **Returns:** List of standard frequencies. - -## normalizedfreq - -```python -normalizedfreq(fraction: int) -> list[float] -``` - -Deprecated alias of [`normalized_frequencies`](/phonometry/reference/api/filters/frequencies/#normalized_frequencies). diff --git a/site/src/content/docs/reference/api/materials/road-absorption.md b/site/src/content/docs/reference/api/materials/road-absorption.md index adc4f76d6..cd1e9af20 100644 --- a/site/src/content/docs/reference/api/materials/road-absorption.md +++ b/site/src/content/docs/reference/api/materials/road-absorption.md @@ -111,7 +111,6 @@ adrienne_window( trailing_duration: float = 0.005, leading_edge: str = 'blackman-harris', trailing_edge: str = 'blackman-harris', - sample_rate: float | str = 'deprecated', ) -> Real ``` @@ -144,7 +143,6 @@ normative fixed set of timings. The lower usable frequency scales as | `trailing_duration` | Trailing-edge (fall) duration, in seconds. | | `leading_edge` | Leading-edge shape, `"blackman-harris"` or `"cosine-squared"`. | | `trailing_edge` | Trailing-edge shape, `"blackman-harris"` or `"cosine-squared"`. | -| `sample_rate` | Deprecated alias of `fs` (remove in 4.0). | **Returns:** The time-domain window, one sample per `1 / fs` (length `round((leading + flat + trailing) * fs)` samples). @@ -333,7 +331,6 @@ insitu_absorption_spectrum( f_min: float = 250.0, f_max: float = 4000.0, clip_negative: bool = True, - sample_rate: float | str = 'deprecated', ) -> InsituAbsorptionResult ``` @@ -359,7 +356,6 @@ in a plottable [`InsituAbsorptionResult`](/phonometry/reference/api/materials/ro | `f_min` | Lowest band centre to report, in hertz (default 250 Hz). | | `f_max` | Highest band centre to report, in hertz (default 4000 Hz). | | `clip_negative` | Clip negative band results to zero (default `True`). | -| `sample_rate` | Deprecated alias of `fs` (remove in 4.0). | **Returns:** An [`InsituAbsorptionResult`](/phonometry/reference/api/materials/road-absorption/#insituabsorptionresult) with `.plot()`. @@ -382,7 +378,6 @@ insitu_reflection_factor( fs: float | None = None, delay: float | None = None, n: int | None = None, - sample_rate: float | str = 'deprecated', ) -> Complex ``` @@ -411,7 +406,6 @@ Annex C; the frequency-dependent form of Annex G). | `fs` | Sampling frequency, in hertz; required with `delay` for phase restoration. | | `delay` | Reflected-path delay `dtau` to undo, in seconds; `None` returns the raw spectral ratio. | | `n` | FFT length; defaults to the longer of the two impulse responses. | -| `sample_rate` | Deprecated alias of `fs` (remove in 4.0). | **Returns:** Complex reflection factor `r(f)` at the `rfft` frequency bins. diff --git a/site/src/content/docs/reference/api/metrology/calibration.md b/site/src/content/docs/reference/api/metrology/calibration.md index d77a25896..231c54b29 100644 --- a/site/src/content/docs/reference/api/metrology/calibration.md +++ b/site/src/content/docs/reference/api/metrology/calibration.md @@ -9,23 +9,6 @@ Calibration utilities for mapping digital signals to physical SPL levels. > Auto-generated from the source docstrings by `scripts/generate_api_docs.py` (`make api-docs`). Do not edit by hand. -## calculate_sensitivity - -```python -calculate_sensitivity( - ref_signal: list[float] | np.ndarray, - target_spl: float = 94.0, - ref_pressure: float = 2e-05, - fs: int | None = None, - validate: bool = True, - max_fluctuation_db: float | None = None, - frequency: float = 1000.0, - narrowband: bool = False, -) -> float -``` - -Deprecated alias of [`sensitivity`](/phonometry/reference/api/metrology/calibration/#sensitivity). - ## CalibrationWarning The calibration reference recording looks unreliable. diff --git a/site/src/content/docs/reference/api/power/sound-power-reverberation.md b/site/src/content/docs/reference/api/power/sound-power-reverberation.md index 5efe99876..23aee0bb3 100644 --- a/site/src/content/docs/reference/api/power/sound-power-reverberation.md +++ b/site/src/content/docs/reference/api/power/sound-power-reverberation.md @@ -214,7 +214,7 @@ the two sources, so the room absorption need not be known. ```python sound_power_reverberation( levels: np.ndarray, - t60: np.ndarray, + t60: float | np.ndarray, volume: float, surface_area: float, frequencies: np.ndarray, diff --git a/site/src/content/docs/reference/api/power/sound-power.md b/site/src/content/docs/reference/api/power/sound-power.md index cc5ac7ecb..3fe72a678 100644 --- a/site/src/content/docs/reference/api/power/sound-power.md +++ b/site/src/content/docs/reference/api/power/sound-power.md @@ -103,7 +103,6 @@ environmental_correction( volume: float | None = None, mean_absorption_coefficient: float | np.ndarray | None = None, room_surface: float | None = None, - room_volume: float | str | None = 'deprecated', ) -> float | np.ndarray ``` @@ -135,7 +134,6 @@ with that shape; scalar inputs return a scalar, unchanged. | `volume` | Room volume `V` (m^3), with `reverberation_time`. | | `mean_absorption_coefficient` | `alpha` in (0, 1], scalar or per band, with `room_surface` (Eq. A.7). | | `room_surface` | Room boundary area `Sv` (m^2), with `alpha`. | -| `room_volume` | Deprecated alias of `volume` (remove in 4.0). | **Returns:** `K2` in decibels; a scalar for scalar inputs, otherwise an array per band. @@ -763,7 +761,6 @@ sound_power_pressure( room_surface: float | None = None, grade: Grade = 'engineering', omc_uncertainty: float = 0.0, - room_volume: float | str | None = 'deprecated', ) -> SoundPowerResult ``` @@ -804,7 +801,6 @@ sound power level is combined via ISO 3744 Annex E. | `room_surface` | Room boundary area `Sv` (m^2), with `alpha`. | | `grade` | `'engineering'` (ISO 3744) or `'survey'` (ISO 3746). | | `omc_uncertainty` | `sigma_omc` (dB), operating/mounting instability. | -| `room_volume` | Deprecated alias of `volume` (remove in 4.0). | **Returns:** [`SoundPowerResult`](/phonometry/reference/api/power/sound-power/#soundpowerresult). diff --git a/site/src/content/docs/reference/api/psychoacoustics/ecma.md b/site/src/content/docs/reference/api/psychoacoustics/ecma.md index fdc24d8fd..323b2d0e6 100644 --- a/site/src/content/docs/reference/api/psychoacoustics/ecma.md +++ b/site/src/content/docs/reference/api/psychoacoustics/ecma.md @@ -84,7 +84,7 @@ EcmaLoudness.plot( ) -> Axes | np.ndarray ``` -Plot the average specific loudness N'(z) (see `._plotting`). +Plot the average specific loudness N'(z) (see `phonometry._plot.psychoacoustics`). Adds a loudness-vs-time panel. Requires matplotlib (`pip install phonometry[plot]`). diff --git a/site/src/content/docs/reference/api/psychoacoustics/fluctuation-strength-ecma.md b/site/src/content/docs/reference/api/psychoacoustics/fluctuation-strength-ecma.md index 660980fb5..7d7403c1a 100644 --- a/site/src/content/docs/reference/api/psychoacoustics/fluctuation-strength-ecma.md +++ b/site/src/content/docs/reference/api/psychoacoustics/fluctuation-strength-ecma.md @@ -137,7 +137,7 @@ EcmaFluctuationStrength.plot( ) -> Axes | np.ndarray ``` -Plot the fluctuation-strength result (see `._plotting`). +Plot the fluctuation-strength result (see `phonometry._plot.psychoacoustics`). Draws the time-dependent fluctuation strength F(l50) and a specific-fluctuation-strength heatmap. Requires matplotlib diff --git a/site/src/content/docs/reference/api/psychoacoustics/moore-glasberg-time.md b/site/src/content/docs/reference/api/psychoacoustics/moore-glasberg-time.md index 9b9ea792e..20f5dea6d 100644 --- a/site/src/content/docs/reference/api/psychoacoustics/moore-glasberg-time.md +++ b/site/src/content/docs/reference/api/psychoacoustics/moore-glasberg-time.md @@ -145,4 +145,4 @@ MooreGlasbergTimeVaryingLoudness.plot( Plot the short-term and long-term loudness against time. Requires matplotlib (`pip install phonometry[plot]`); returns the -`Axes`. See `._plotting`. +`Axes`. See `phonometry._plot.psychoacoustics`. diff --git a/site/src/content/docs/reference/api/psychoacoustics/moore-glasberg.md b/site/src/content/docs/reference/api/psychoacoustics/moore-glasberg.md index e1eb36e8c..bb6558500 100644 --- a/site/src/content/docs/reference/api/psychoacoustics/moore-glasberg.md +++ b/site/src/content/docs/reference/api/psychoacoustics/moore-glasberg.md @@ -178,4 +178,4 @@ MooreGlasbergLoudness.plot( Plot the specific loudness N'(i) over the ERB-number scale. Requires matplotlib (`pip install phonometry[plot]`); returns the -`Axes`. See `._plotting`. +`Axes`. See `phonometry._plot.psychoacoustics`. diff --git a/site/src/content/docs/reference/api/psychoacoustics/roughness-ecma.md b/site/src/content/docs/reference/api/psychoacoustics/roughness-ecma.md index 88c4fa552..85a97a48b 100644 --- a/site/src/content/docs/reference/api/psychoacoustics/roughness-ecma.md +++ b/site/src/content/docs/reference/api/psychoacoustics/roughness-ecma.md @@ -91,7 +91,7 @@ EcmaRoughness.plot( ) -> Axes | np.ndarray ``` -Plot the roughness result (see `._plotting`). +Plot the roughness result (see `phonometry._plot.psychoacoustics`). Draws the time-dependent roughness R(l50) and a specific-roughness heatmap. Requires matplotlib (`pip install phonometry[plot]`). diff --git a/site/src/content/docs/reference/api/psychoacoustics/tonality-ecma.md b/site/src/content/docs/reference/api/psychoacoustics/tonality-ecma.md index ac47d44b9..9afe4226f 100644 --- a/site/src/content/docs/reference/api/psychoacoustics/tonality-ecma.md +++ b/site/src/content/docs/reference/api/psychoacoustics/tonality-ecma.md @@ -72,7 +72,7 @@ EcmaTonality.plot( ) -> Axes | np.ndarray ``` -Plot the average specific tonality T'(z) (see `._plotting`). +Plot the average specific tonality T'(z) (see `phonometry._plot.psychoacoustics`). Adds a tonality-vs-time panel. Requires matplotlib (`pip install phonometry[plot]`). diff --git a/site/src/content/docs/reference/api/psychoacoustics/zwicker.md b/site/src/content/docs/reference/api/psychoacoustics/zwicker.md index 415a2cb6b..f46a240cc 100644 --- a/site/src/content/docs/reference/api/psychoacoustics/zwicker.md +++ b/site/src/content/docs/reference/api/psychoacoustics/zwicker.md @@ -144,7 +144,7 @@ ZwickerLoudness.plot( ) -> Axes | np.ndarray ``` -Plot the specific loudness N'(z) over Bark (see `._plotting`). +Plot the specific loudness N'(z) over Bark (see `phonometry._plot.psychoacoustics`). Adds a loudness-vs-time panel when the time-varying trace is present. Requires matplotlib (`pip install phonometry[plot]`); diff --git a/src/phonometry/__init__.py b/src/phonometry/__init__.py index d1c97e577..63b2e63f3 100644 --- a/src/phonometry/__init__.py +++ b/src/phonometry/__init__.py @@ -6,9 +6,7 @@ from __future__ import annotations -from typing import Any - -from ._internal.warnings import PhonometryWarning, _warn_renamed +from ._internal.warnings import PhonometryWarning from ._plot.geometry import ( plot_absorber_stack, plot_aperture_geometry, @@ -214,8 +212,6 @@ UncertainValue, band_uncertainty, combine_uncertainties, - coverage_factor, - expanded_uncertainty, insulation_coverage_factor, insulation_expanded_uncertainty, maximum_repeatability_standard_deviation, @@ -702,7 +698,6 @@ FilterBankWarning, OctaveFilterBank, octave_filter, - octavefilter, ) from .filters.equalizer import ( EQResponseResult, @@ -711,10 +706,8 @@ parametric_eq, ) from .filters.frequencies import ( - getansifrequencies, nominal_frequencies, normalized_frequencies, - normalizedfreq, ) from .filters.weighting import ( TimeWeighting, @@ -953,7 +946,6 @@ ) from .metrology.calibration import ( CalibrationWarning, - calculate_sensitivity, sensitivity, ) from .metrology.data_qualification import ( @@ -2047,7 +2039,6 @@ "blocking_force_ratio", "bottom_reflection_loss", "bridge_transfer", - "calculate_sensitivity", "calculated_sound_reduction_index", "cam_from_frequency", "ceiling_attenuation_class", @@ -2092,7 +2083,6 @@ "coupling_term", "coupling_term_force_source", "coupling_term_velocity_source", - "coverage_factor", "covering_contact_stiffness", "covering_improvement", "crest_factor", @@ -2188,7 +2178,6 @@ "evaluation_period_level", "event_level", "excess_phase", - "expanded_uncertainty", "expansion_chamber", "exposure_assessment", "exposure_criteria", @@ -2248,7 +2237,6 @@ "geometric_divergence", "geometric_spreading_factor", "geometric_spreading_factor_angle", - "getansifrequencies", "golay_impulse_response", "golay_pair", "ground_attenuation", @@ -2445,14 +2433,12 @@ "normalized_frequencies", "normalized_surface_admittance", "normalized_surface_impedance", - "normalizedfreq", "npd_curve", "npd_level", "object_fraction", "ocean_ambient_noise", "octave_bands_from_third_octaves", "octave_filter", - "octavefilter", "one_third_octave_absorption", "open_microphone_correction", "open_plan_metrics", @@ -2825,33 +2811,30 @@ ] -#: Deprecated root-level name -> canonical name (phonometry 3.1 renames). -_RENAMED_ATTRIBUTES: dict[str, str] = { - "OCTAVE_BANDS_HZ": "OCTAVE_BANDS", - "THIRD_OCTAVE_BANDS_HZ": "THIRD_OCTAVE_BANDS", - "BASE_PLATE_BANDS_HZ": "BASE_PLATE_BANDS", - "ExposureWarning": "OccupationalExposureWarning", -} - - -def __getattr__(name: str) -> Any: - """PEP 562 shim warning for names renamed in phonometry 3.1. - - Constants cannot warn through a wrapper, so the deprecated names live - here (and in their home modules) as module ``__getattr__`` aliases. - Remove in 4.0. - """ - try: - canonical = _RENAMED_ATTRIBUTES[name] - except KeyError: - raise AttributeError( - f"module 'phonometry' has no attribute {name!r}" - ) from None - _warn_renamed(name, canonical) - return globals()[canonical] - - # Deprecated module-path aliases for the 4.0 taxonomy: importing the package # installs sys.modules shims for every moved public module (see # phonometry/_compat.py; removed in 5.0). from . import _compat as _compat + +# The domain packages are part of the public surface: ``phonometry.building`` +# reads the same as ``from phonometry import building``. Importing the flat API +# already binds every one of them; naming them here says so, and lets a type +# checker follow ``ph.building`` the way the interpreter does. +from . import aircraft as aircraft +from . import broadcast as broadcast +from . import building as building +from . import electroacoustics as electroacoustics +from . import emission as emission +from . import environment as environment +from . import filters as filters +from . import hearing as hearing +from . import materials as materials +from . import metrology as metrology +from . import noise_control as noise_control +from . import psychoacoustics as psychoacoustics +from . import room as room +from . import signals as signals +from . import simulation as simulation +from . import speech as speech +from . import underwater as underwater +from . import vibration as vibration diff --git a/src/phonometry/_plotting.py b/src/phonometry/_plotting.py deleted file mode 100644 index 7004882ff..000000000 --- a/src/phonometry/_plotting.py +++ /dev/null @@ -1,205 +0,0 @@ -# Copyright (c) 2026. Jose Manuel Requena Plens -"""Deprecated location of the plot renderers (moved to ``phonometry._plot``). - -Kept as a silent re-export for one deprecation cycle (removed in 4.0): -result ``.plot()`` call sites are being retargeted per domain during the -3.2 package reorganization, and external users of this private module keep -working unchanged.""" - -from __future__ import annotations - -from ._plot.aircraft import ( - plot_aircraft_band_attenuation, - plot_epnl, - plot_flyover, - plot_noise_contour, - plot_npd_level, - plot_rotorcraft_hemisphere, -) -from ._plot.building import ( - plot_airborne_insulation, - plot_airborne_prediction, - plot_band_uncertainty, - plot_facade_insulation, - plot_facade_prediction, - plot_floor_covering_improvement, - plot_impact_insulation, - plot_impact_prediction, - plot_impact_rating, - plot_installed_structure_borne, - plot_radiated_power, - plot_structure_borne_power, - plot_vibration_reduction, - plot_weighted_rating, -) -from ._plot.electroacoustics import ( - plot_frequency_response, - plot_harmonic_distortion, -) -from ._plot.emission import ( - plot_intensity, - plot_sound_power, - plot_vibration_sound_power, -) -from ._plot.environment import ( - plot_impulse_prominence, - plot_outdoor_attenuation, - plot_tonal_adjustment, - plot_wind_turbine_tonality, -) -from ._plot.hearing import ( - plot_age_threshold, - plot_htlan, - plot_nipts, - plot_occupational_exposure, -) -from ._plot.materials import ( - plot_absorption_uncertainty, - plot_diffusion_polar, - plot_dynamic_stiffness, - plot_impedance_tube, - plot_insitu_absorption, - plot_scattering_coefficient, - plot_static_airflow, - plot_weighted_absorption, -) -from ._plot.metrology import ( - plot_monte_carlo, - plot_uncertainty_budget, -) -from ._plot.psychoacoustics import ( - plot_ecma_loudness, - plot_ecma_roughness, - plot_ecma_tonality, - plot_fluctuation_strength, - plot_moore_glasberg_loudness, - plot_moore_glasberg_time_loudness, - plot_psychoacoustic_annoyance, - plot_tone_audibility, - plot_zwicker_loudness, -) -from ._plot.room import ( - plot_decay_curve, - plot_enclosed_space_absorption, - plot_excitation, - plot_impulse_response, - plot_noise_criterion, - plot_open_plan, - plot_reverberation_models, - plot_room_acoustics, - plot_room_criterion, -) -from ._plot.simulation import ( - plot_fdtd_probes, - plot_fdtd_snapshot, -) -from ._plot.speech import ( - plot_sii, - plot_sti, -) -from ._plot.underwater import ( - plot_ambient_noise, - plot_bottom_loss, - plot_normal_modes, - plot_parabolic_equation, - plot_pile_strike, - plot_ray_trace, - plot_ship_source_level, - plot_ship_traffic_spectrum, - plot_sonar_equation, - plot_sound_speed_profile, - plot_transmission_loss, -) -from ._plot.vibration import ( - plot_daily_exposure, - plot_mobility, - plot_multiple_shock, - plot_transfer_stiffness, - plot_vibration_weighting, - plot_weighted_spectrum, -) - -__all__ = [ - "plot_absorption_uncertainty", - "plot_age_threshold", - "plot_airborne_insulation", - "plot_airborne_prediction", - "plot_aircraft_band_attenuation", - "plot_ambient_noise", - "plot_band_uncertainty", - "plot_bottom_loss", - "plot_daily_exposure", - "plot_decay_curve", - "plot_diffusion_polar", - "plot_dynamic_stiffness", - "plot_ecma_loudness", - "plot_ecma_roughness", - "plot_ecma_tonality", - "plot_enclosed_space_absorption", - "plot_epnl", - "plot_excitation", - "plot_facade_insulation", - "plot_facade_prediction", - "plot_fdtd_probes", - "plot_fdtd_snapshot", - "plot_floor_covering_improvement", - "plot_fluctuation_strength", - "plot_flyover", - "plot_frequency_response", - "plot_harmonic_distortion", - "plot_htlan", - "plot_impact_insulation", - "plot_impact_prediction", - "plot_impact_rating", - "plot_impedance_tube", - "plot_impulse_prominence", - "plot_impulse_response", - "plot_insitu_absorption", - "plot_installed_structure_borne", - "plot_intensity", - "plot_mobility", - "plot_monte_carlo", - "plot_moore_glasberg_loudness", - "plot_moore_glasberg_time_loudness", - "plot_multiple_shock", - "plot_nipts", - "plot_noise_contour", - "plot_noise_criterion", - "plot_normal_modes", - "plot_npd_level", - "plot_occupational_exposure", - "plot_open_plan", - "plot_outdoor_attenuation", - "plot_parabolic_equation", - "plot_pile_strike", - "plot_psychoacoustic_annoyance", - "plot_radiated_power", - "plot_ray_trace", - "plot_reverberation_models", - "plot_room_acoustics", - "plot_room_criterion", - "plot_rotorcraft_hemisphere", - "plot_scattering_coefficient", - "plot_ship_source_level", - "plot_ship_traffic_spectrum", - "plot_sii", - "plot_sonar_equation", - "plot_sound_power", - "plot_sound_speed_profile", - "plot_static_airflow", - "plot_sti", - "plot_structure_borne_power", - "plot_tonal_adjustment", - "plot_tone_audibility", - "plot_transfer_stiffness", - "plot_transmission_loss", - "plot_uncertainty_budget", - "plot_vibration_reduction", - "plot_vibration_sound_power", - "plot_vibration_weighting", - "plot_weighted_absorption", - "plot_weighted_rating", - "plot_weighted_spectrum", - "plot_wind_turbine_tonality", - "plot_zwicker_loudness", -] diff --git a/src/phonometry/building/__init__.py b/src/phonometry/building/__init__.py index eb01a1207..580dddad1 100644 --- a/src/phonometry/building/__init__.py +++ b/src/phonometry/building/__init__.py @@ -64,7 +64,6 @@ check_heavy_impact_source, combine_subareas, combine_uncertainties, - coverage_factor, critical_frequency, direction_averaged_level_difference, energy_average_level, @@ -72,7 +71,6 @@ equivalent_blocked_force_level, equivalent_free_velocity_level, estimate_reverberation_index, - expanded_uncertainty, facade_insulation, fast_reverberation_correction, heavy_impact_octave_levels, @@ -370,7 +368,6 @@ "coupling_term", "coupling_term_force_source", "coupling_term_velocity_source", - "coverage_factor", "covering_contact_stiffness", "covering_improvement", "critical_frequency", @@ -396,7 +393,6 @@ "equivalent_free_velocity_level", "equivalent_impact_level", "estimate_reverberation_index", - "expanded_uncertainty", "facade_insulation", "facade_shape_level_difference", "facade_sound_reduction", diff --git a/src/phonometry/building/measurement/__init__.py b/src/phonometry/building/measurement/__init__.py index 360d850ca..3481d5eff 100644 --- a/src/phonometry/building/measurement/__init__.py +++ b/src/phonometry/building/measurement/__init__.py @@ -111,8 +111,6 @@ UncertainValue, band_uncertainty, combine_uncertainties, - coverage_factor, - expanded_uncertainty, insulation_coverage_factor, insulation_expanded_uncertainty, maximum_repeatability_standard_deviation, @@ -169,7 +167,6 @@ "check_heavy_impact_source", "combine_subareas", "combine_uncertainties", - "coverage_factor", "critical_frequency", "direction_averaged_level_difference", "energy_average_level", @@ -177,7 +174,6 @@ "equivalent_blocked_force_level", "equivalent_free_velocity_level", "estimate_reverberation_index", - "expanded_uncertainty", "facade_insulation", "fast_reverberation_correction", "heavy_impact_octave_levels", diff --git a/src/phonometry/building/measurement/survey_insulation.py b/src/phonometry/building/measurement/survey_insulation.py index af87d7f76..8b85ab7f5 100644 --- a/src/phonometry/building/measurement/survey_insulation.py +++ b/src/phonometry/building/measurement/survey_insulation.py @@ -70,7 +70,7 @@ from collections.abc import Sequence from dataclasses import dataclass -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Literal, overload import numpy as np @@ -247,6 +247,18 @@ def reverberation_index( return 10.0 * np.log10(tt / _positive(t0, "t0")) +@overload +def estimate_reverberation_index( + volume: float, room: str, *, weighted: Literal[False] = False +) -> np.ndarray: ... + + +@overload +def estimate_reverberation_index( + volume: float, room: str, *, weighted: Literal[True] +) -> float: ... + + def estimate_reverberation_index( volume: float, room: str, *, weighted: bool = False ) -> np.ndarray | float: diff --git a/src/phonometry/building/measurement/uncertainty.py b/src/phonometry/building/measurement/uncertainty.py index c0f5f2021..120f3aa79 100644 --- a/src/phonometry/building/measurement/uncertainty.py +++ b/src/phonometry/building/measurement/uncertainty.py @@ -608,36 +608,3 @@ def satisfies_upper_requirement( **{(level, True): k for level, k in _COVERAGE_ONE_SIDED.items()}, } ) - - -# --------------------------------------------------------------------------- # -# Deprecated aliases (the bare names shadowed the GUM functions of -# :mod:`phonometry.metrology.uncertainty` at the top level; remove in the next -# major). -# --------------------------------------------------------------------------- # -def _warn_renamed(old: str, new: str) -> None: - import warnings - - warnings.warn( - f"phonometry {old} (ISO 12999-1) is deprecated since phonometry 3.1 " - f"and will be removed in 4.0; use {new}. For the GUM function use " - f"phonometry.metrology.uncertainty.{old}.", - DeprecationWarning, - stacklevel=3, - ) - - -def coverage_factor(confidence: float = 0.95, one_sided: bool = False) -> float: - """Deprecated alias of :func:`insulation_coverage_factor`.""" - _warn_renamed("coverage_factor", "insulation_coverage_factor") - return insulation_coverage_factor(confidence, one_sided) - - -def expanded_uncertainty( - u: float, - coverage: float = 0.95, - one_sided: bool = False, -) -> float: - """Deprecated alias of :func:`insulation_expanded_uncertainty`.""" - _warn_renamed("expanded_uncertainty", "insulation_expanded_uncertainty") - return insulation_expanded_uncertainty(u, coverage, one_sided) diff --git a/src/phonometry/emission/sound_power.py b/src/phonometry/emission/sound_power.py index fe6574a5a..49ab71b3e 100644 --- a/src/phonometry/emission/sound_power.py +++ b/src/phonometry/emission/sound_power.py @@ -56,7 +56,7 @@ from .._internal.levels_math import energy_mean, energy_sum, weighted_energy_mean from .._internal.types import as_float_or_array -from .._internal.warnings import PhonometryWarning, _warn_renamed +from .._internal.warnings import PhonometryWarning if TYPE_CHECKING: from collections.abc import Sequence @@ -374,7 +374,6 @@ def environmental_correction( volume: float | None = None, mean_absorption_coefficient: float | np.ndarray | None = None, room_surface: float | None = None, - room_volume: float | str | None = "deprecated", ) -> float | np.ndarray: r"""Environmental correction ``K2`` (ISO 3744:2010 Eq. A.2). @@ -403,23 +402,9 @@ def environmental_correction( :param mean_absorption_coefficient: ``alpha`` in (0, 1], scalar or per band, with ``room_surface`` (Eq. A.7). :param room_surface: Room boundary area ``Sv`` (m^2), with ``alpha``. - :param room_volume: Deprecated alias of ``volume`` (remove in 4.0). :return: ``K2`` in decibels; a scalar for scalar inputs, otherwise an array per band. """ - # An explicit None matches the old default and stays silent; only a real - # value through the deprecated alias warns. - if not isinstance(room_volume, str) and room_volume is not None: - _warn_renamed( - "the 'room_volume' keyword of environmental_correction()", - "'volume'", - ) - if volume is not None: - raise ValueError( - "environmental_correction() got both 'volume' and its " - "deprecated alias 'room_volume'; pass only 'volume'." - ) - volume = room_volume if absorption_area is None: # A half-specified room pair must never be read as free field: naming # only one member of a pair is a mistake, not a K2 = 0 request. @@ -586,7 +571,6 @@ def sound_power_pressure( room_surface: float | None = None, grade: Grade = "engineering", omc_uncertainty: float = 0.0, - room_volume: float | str | None = "deprecated", ) -> SoundPowerResult: r"""Sound power level from surface pressure levels (ISO 3744/3746:2010). @@ -623,19 +607,8 @@ def sound_power_pressure( :param room_surface: Room boundary area ``Sv`` (m^2), with ``alpha``. :param grade: ``'engineering'`` (ISO 3744) or ``'survey'`` (ISO 3746). :param omc_uncertainty: ``sigma_omc`` (dB), operating/mounting instability. - :param room_volume: Deprecated alias of ``volume`` (remove in 4.0). :return: :class:`SoundPowerResult`. """ - if not isinstance(room_volume, str) and room_volume is not None: - _warn_renamed( - "the 'room_volume' keyword of sound_power_pressure()", "'volume'" - ) - if volume is not None: - raise ValueError( - "sound_power_pressure() got both 'volume' and its deprecated " - "alias 'room_volume'; pass only 'volume'." - ) - volume = room_volume grade = _check_grade(grade) levels = np.atleast_2d(np.asarray(levels_positions, dtype=np.float64)) if levels.ndim != 2: diff --git a/src/phonometry/emission/sound_power_reverberation.py b/src/phonometry/emission/sound_power_reverberation.py index 32a8d6fd0..f98888080 100644 --- a/src/phonometry/emission/sound_power_reverberation.py +++ b/src/phonometry/emission/sound_power_reverberation.py @@ -406,7 +406,7 @@ def _a_weighted_total( def sound_power_reverberation( levels: np.ndarray, - t60: np.ndarray, + t60: float | np.ndarray, volume: float, surface_area: float, frequencies: np.ndarray, diff --git a/src/phonometry/environment/propagation/outdoor_propagation.py b/src/phonometry/environment/propagation/outdoor_propagation.py index 5f5cc9720..d5d3e52a5 100644 --- a/src/phonometry/environment/propagation/outdoor_propagation.py +++ b/src/phonometry/environment/propagation/outdoor_propagation.py @@ -50,7 +50,6 @@ import numpy as np from numpy.typing import ArrayLike, NDArray -from ..._internal.warnings import _warn_renamed from .air_absorption import air_attenuation if TYPE_CHECKING: @@ -297,37 +296,12 @@ def geometric_divergence(distance: float) -> float: return float(20.0 * np.log10(distance / _D0) + 11.0) -def _resolve_humidity( - func: str, relative_humidity: float | None, humidity: float | str -) -> float: - """Resolve the deprecated ``humidity`` alias onto ``relative_humidity``. - - ``stacklevel=4`` skips this helper *and* the public function so the - :class:`DeprecationWarning` points at the caller's line. - """ - if not isinstance(humidity, str): - _warn_renamed( - f"the 'humidity' keyword of {func}()", - "'relative_humidity'", - stacklevel=4, - ) - if relative_humidity is not None: - raise ValueError( - f"{func}() got both 'relative_humidity' and its deprecated " - "alias 'humidity'; pass only 'relative_humidity'." - ) - relative_humidity = humidity - return 70.0 if relative_humidity is None else relative_humidity - - def atmospheric_absorption( distance: float, frequencies: ArrayLike = DEFAULT_FREQUENCIES, temperature: float = 20.0, relative_humidity: float | None = None, pressure: float = 101.325, - *, - humidity: float | str = "deprecated", ) -> NDArray[np.float64]: r"""Attenuation due to atmospheric absorption (ISO 9613-2:1996, Eq. (8)). @@ -350,12 +324,9 @@ def atmospheric_absorption( :param temperature: Air temperature, in degrees Celsius. :param relative_humidity: Relative humidity, in percent (default 70). :param pressure: Atmospheric pressure, in kilopascals. - :param humidity: Deprecated alias of ``relative_humidity`` (remove in 4.0). :return: ``Aatm`` per band, in decibels. """ - relative_humidity = _resolve_humidity( - "atmospheric_absorption", relative_humidity, humidity - ) + relative_humidity = 70.0 if relative_humidity is None else relative_humidity alpha = air_attenuation( frequencies, temperature, relative_humidity, pressure, exact_midband=True ) @@ -704,8 +675,6 @@ def outdoor_propagation_attenuation( relative_humidity: float | None = None, pressure: float = 101.325, projected_distance: float | None = None, - *, - humidity: float | str = "deprecated", ) -> OutdoorAttenuation: r"""Total octave-band outdoor attenuation (ISO 9613-2:1996, Eq. (4)). @@ -735,13 +704,10 @@ def outdoor_propagation_attenuation( :param pressure: Atmospheric pressure, in kilopascals. :param projected_distance: Ground-plane projected distance ``dp``, in metres; defaults to :math:`\sqrt{d^2 - (h_s - h_r)^2}`. - :param humidity: Deprecated alias of ``relative_humidity`` (remove in 4.0). :return: :class:`OutdoorAttenuation` with the per-band term breakdown. :raises ValueError: If ``distance`` is not positive. """ - relative_humidity = _resolve_humidity( - "outdoor_propagation_attenuation", relative_humidity, humidity - ) + relative_humidity = 70.0 if relative_humidity is None else relative_humidity if distance <= 0.0: raise ValueError("'distance' must be positive.") freqs = np.atleast_1d(np.asarray(frequencies, dtype=np.float64)) @@ -791,8 +757,6 @@ def predicted_receiver_level( d_omega: float = 0.0, c0: float | None = None, projected_distance: float | None = None, - *, - humidity: float | str = "deprecated", ) -> NDArray[np.float64]: r"""Predicted octave-band receiver level (ISO 9613-2:1996, Eq. (3)/(6)). @@ -827,12 +791,9 @@ def predicted_receiver_level( :param c0: Meteorological factor ``C0``, in decibels; ``None`` returns the downwind level ``LfT(DW)`` (:math:`C_{met} = 0`). :param projected_distance: Ground-plane projected distance ``dp``, in metres. - :param humidity: Deprecated alias of ``relative_humidity`` (remove in 4.0). :return: Predicted octave-band level per frequency, in decibels. """ - relative_humidity = _resolve_humidity( - "predicted_receiver_level", relative_humidity, humidity - ) + relative_humidity = 70.0 if relative_humidity is None else relative_humidity lw = np.atleast_1d(np.asarray(sound_power_level, dtype=np.float64)) attenuation = outdoor_propagation_attenuation( distance, source_height, receiver_height, frequencies, diff --git a/src/phonometry/filters/__init__.py b/src/phonometry/filters/__init__.py index 505ad2a91..529b775ec 100644 --- a/src/phonometry/filters/__init__.py +++ b/src/phonometry/filters/__init__.py @@ -12,13 +12,11 @@ verify_weighting_class, weighting_class_limits, ) -from .core import FilterBankWarning, OctaveFilterBank, octave_filter, octavefilter +from .core import FilterBankWarning, OctaveFilterBank, octave_filter from .equalizer import EQResponseResult, EQSection, ParametricEQ, parametric_eq from .frequencies import ( - getansifrequencies, nominal_frequencies, normalized_frequencies, - normalizedfreq, ) from .weighting import ( TimeWeighting, @@ -39,13 +37,10 @@ "WeightingFilter", "class_limits", "filter_class_compliance", - "getansifrequencies", "linkwitz_riley", "nominal_frequencies", "normalized_frequencies", - "normalizedfreq", "octave_filter", - "octavefilter", "parametric_eq", "time_weighting", "verify_filter_class", diff --git a/src/phonometry/filters/core.py b/src/phonometry/filters/core.py index 37da4342f..e9f70d009 100644 --- a/src/phonometry/filters/core.py +++ b/src/phonometry/filters/core.py @@ -7,13 +7,13 @@ import warnings from functools import lru_cache -from typing import Any, Literal, cast, overload +from typing import Literal, cast, overload import numpy as np from scipy import signal from .._internal.utils import _downsamplingfactor, _resample_to_length, _typesignal -from .._internal.warnings import PhonometryWarning, _warn_renamed +from .._internal.warnings import PhonometryWarning from .design import _cheby2_headroom, _design_sos_filter from .frequencies import _genfreqs @@ -693,9 +693,3 @@ def octave_filter( ) return filter_bank.filter(x, sigbands=sigbands, mode=mode, detrend=detrend, nominal=nominal) # type: ignore[call-overload,no-any-return] - - -def octavefilter(*args: Any, **kwargs: Any) -> Any: - """Deprecated alias of :func:`octave_filter`.""" - _warn_renamed("octavefilter()", "octave_filter()") - return octave_filter(*args, **kwargs) diff --git a/src/phonometry/filters/frequencies.py b/src/phonometry/filters/frequencies.py index 4ebf25f14..53787d8ef 100644 --- a/src/phonometry/filters/frequencies.py +++ b/src/phonometry/filters/frequencies.py @@ -10,7 +10,7 @@ import numpy as np -from .._internal.warnings import PhonometryWarning, _warn_renamed +from .._internal.warnings import PhonometryWarning def nominal_frequencies( @@ -204,21 +204,3 @@ def normalized_frequencies(fraction: int) -> list[float]: if fraction not in predefined: raise ValueError("Normalized frequencies only available for fraction=1 or 3") return predefined[fraction] - - -# --------------------------------------------------------------------------- # -# Deprecated aliases (pre-3.1 names; remove in the next major). -# --------------------------------------------------------------------------- # -def getansifrequencies( - fraction: float, - limits: list[float] | None = None, -) -> tuple[list[float], list[float], list[float], list[str]]: - """Deprecated alias of :func:`nominal_frequencies`.""" - _warn_renamed("getansifrequencies()", "nominal_frequencies()") - return nominal_frequencies(fraction, limits) - - -def normalizedfreq(fraction: int) -> list[float]: - """Deprecated alias of :func:`normalized_frequencies`.""" - _warn_renamed("normalizedfreq()", "normalized_frequencies()") - return normalized_frequencies(fraction) \ No newline at end of file diff --git a/src/phonometry/hearing/occupational_exposure.py b/src/phonometry/hearing/occupational_exposure.py index b933b4e8a..87f7874c1 100644 --- a/src/phonometry/hearing/occupational_exposure.py +++ b/src/phonometry/hearing/occupational_exposure.py @@ -54,7 +54,7 @@ import numpy as np from .._internal.levels_math import energy_mean -from .._internal.warnings import PhonometryWarning, _warn_renamed +from .._internal.warnings import PhonometryWarning if TYPE_CHECKING: from matplotlib.axes import Axes @@ -633,19 +633,3 @@ def full_day_exposure( def _with_advisory(result: ExposureResult) -> ExposureResult: """Return a copy of ``result`` with the sampling advisory flag set.""" return replace(result, sampling_advisory=True) - - -# --- Deprecated alias (phonometry 3.1 rename; remove in 4.0) ------------- - -def __getattr__(name: str) -> Any: - """PEP 562 shim warning for the renamed warning class. - - Returns the class object itself, so ``isinstance``/``except`` checks and - warning filters against the old name keep matching the new one. - """ - if name == "ExposureWarning": - _warn_renamed("ExposureWarning", "OccupationalExposureWarning") - return OccupationalExposureWarning - raise AttributeError( - f"module 'phonometry.hearing.occupational_exposure' has no attribute {name!r}" - ) diff --git a/src/phonometry/materials/absorbers/rating.py b/src/phonometry/materials/absorbers/rating.py index 1d8770290..e3cf7c032 100644 --- a/src/phonometry/materials/absorbers/rating.py +++ b/src/phonometry/materials/absorbers/rating.py @@ -56,8 +56,6 @@ import numpy as np from numpy.typing import ArrayLike, NDArray -from ..._internal.warnings import _warn_renamed - if TYPE_CHECKING: # pragma: no cover - typing only from matplotlib.axes import Axes @@ -464,24 +462,3 @@ def absorption_class(alpha_w: float) -> str: if units >= lowest: return letter return _NOT_CLASSIFIED - - -# --- Deprecated aliases (phonometry 3.1 renames; remove in 4.0) ---------- - -#: Old constant name -> canonical name (units moved to the docstring). -_RENAMED_CONSTANTS: dict[str, str] = { - "OCTAVE_BANDS_HZ": "OCTAVE_BANDS", - "THIRD_OCTAVE_BANDS_HZ": "THIRD_OCTAVE_BANDS", -} - - -def __getattr__(name: str) -> Any: - """PEP 562 shim warning for the renamed band constants.""" - try: - canonical = _RENAMED_CONSTANTS[name] - except KeyError: - raise AttributeError( - f"module 'phonometry.materials.absorbers.rating' has no attribute {name!r}" - ) from None - _warn_renamed(name, canonical) - return globals()[canonical] diff --git a/src/phonometry/materials/diffusers/scattering_diffusion.py b/src/phonometry/materials/diffusers/scattering_diffusion.py index 30437391d..92ce53ea4 100644 --- a/src/phonometry/materials/diffusers/scattering_diffusion.py +++ b/src/phonometry/materials/diffusers/scattering_diffusion.py @@ -52,7 +52,7 @@ from numpy.typing import ArrayLike from ..._internal.types import Real -from ..._internal.warnings import PhonometryWarning, _warn_renamed +from ..._internal.warnings import PhonometryWarning if TYPE_CHECKING: # pragma: no cover - typing only from matplotlib.axes import Axes @@ -1177,15 +1177,3 @@ def random_incidence_diffusion( if total <= 0.0: raise ValueError("The total source weight must be positive.") return float(np.sum(w * d) / total) - - -# --- Deprecated alias (phonometry 3.1 rename; remove in 4.0) ------------- - -def __getattr__(name: str) -> Any: - """PEP 562 shim warning for the renamed band constant.""" - if name == "BASE_PLATE_BANDS_HZ": - _warn_renamed("BASE_PLATE_BANDS_HZ", "BASE_PLATE_BANDS") - return BASE_PLATE_BANDS - raise AttributeError( - f"module 'phonometry.materials.diffusers.scattering_diffusion' has no attribute {name!r}" - ) diff --git a/src/phonometry/materials/surfaces/road_absorption.py b/src/phonometry/materials/surfaces/road_absorption.py index e287b8ef5..7ca328fc1 100644 --- a/src/phonometry/materials/surfaces/road_absorption.py +++ b/src/phonometry/materials/surfaces/road_absorption.py @@ -70,7 +70,7 @@ from numpy.typing import ArrayLike, NDArray from ..._internal.types import Real -from ..._internal.warnings import PhonometryWarning, _warn_renamed +from ..._internal.warnings import PhonometryWarning if TYPE_CHECKING: # pragma: no cover - typing only from matplotlib.axes import Axes @@ -266,7 +266,6 @@ def adrienne_window( trailing_duration: float = _ADRIENNE_TRAILING, leading_edge: str = "blackman-harris", trailing_edge: str = "blackman-harris", - sample_rate: float | str = "deprecated", ) -> Real: """Adrienne-type temporal window (ISO 13472-1:2002, Clause 6.4). @@ -295,21 +294,12 @@ def adrienne_window( ``"cosine-squared"``. :param trailing_edge: Trailing-edge shape, ``"blackman-harris"`` or ``"cosine-squared"``. - :param sample_rate: Deprecated alias of ``fs`` (remove in 4.0). :return: The time-domain window, one sample per ``1 / fs`` (length ``round((leading + flat + trailing) * fs)`` samples). :raises ValueError: If ``fs`` is missing or not positive, a duration is negative, the flat duration is not positive, or an edge shape is unknown. """ - if not isinstance(sample_rate, str): - _warn_renamed("the 'sample_rate' keyword of adrienne_window()", "'fs'") - if fs is not None: - raise ValueError( - "adrienne_window() got both 'fs' and its deprecated alias " - "'sample_rate'; pass only 'fs'." - ) - fs = sample_rate if fs is None: raise ValueError("adrienne_window() missing required argument: 'fs'.") if fs <= 0.0: @@ -371,7 +361,6 @@ def insitu_reflection_factor( fs: float | None = None, delay: float | None = None, n: int | None = None, - sample_rate: float | str = "deprecated", ) -> Complex: r"""Complex pressure reflection factor ``r(f)`` (ISO 13472-1, Clause 4.1). @@ -398,21 +387,10 @@ def insitu_reflection_factor( :param delay: Reflected-path delay ``dtau`` to undo, in seconds; ``None`` returns the raw spectral ratio. :param n: FFT length; defaults to the longer of the two impulse responses. - :param sample_rate: Deprecated alias of ``fs`` (remove in 4.0). :return: Complex reflection factor ``r(f)`` at the ``rfft`` frequency bins. :raises ValueError: On empty inputs, invalid geometry, or ``delay`` given without ``fs``. """ - if not isinstance(sample_rate, str): - _warn_renamed( - "the 'sample_rate' keyword of insitu_reflection_factor()", "'fs'" - ) - if fs is not None: - raise ValueError( - "insitu_reflection_factor() got both 'fs' and its deprecated " - "alias 'sample_rate'; pass only 'fs'." - ) - fs = sample_rate kr = geometric_spreading_factor_angle( incidence_angle, source_height, mic_height ) @@ -665,7 +643,6 @@ def insitu_absorption_spectrum( f_min: float = PART1_FREQUENCY_RANGE[0], f_max: float = PART1_FREQUENCY_RANGE[1], clip_negative: bool = True, - sample_rate: float | str = "deprecated", ) -> InsituAbsorptionResult: """In-situ one-third-octave absorption spectrum (ISO 13472-1, Clause 4.1). @@ -685,21 +662,10 @@ def insitu_absorption_spectrum( :param f_min: Lowest band centre to report, in hertz (default 250 Hz). :param f_max: Highest band centre to report, in hertz (default 4000 Hz). :param clip_negative: Clip negative band results to zero (default ``True``). - :param sample_rate: Deprecated alias of ``fs`` (remove in 4.0). :return: An :class:`InsituAbsorptionResult` with ``.plot()``. :raises ValueError: On empty inputs, invalid geometry, or a missing or non-positive ``fs``. """ - if not isinstance(sample_rate, str): - _warn_renamed( - "the 'sample_rate' keyword of insitu_absorption_spectrum()", "'fs'" - ) - if fs is not None: - raise ValueError( - "insitu_absorption_spectrum() got both 'fs' and its deprecated " - "alias 'sample_rate'; pass only 'fs'." - ) - fs = sample_rate if fs is None: raise ValueError( "insitu_absorption_spectrum() missing required argument: 'fs'." diff --git a/src/phonometry/metrology/__init__.py b/src/phonometry/metrology/__init__.py index 14dd51e36..55cb444ab 100644 --- a/src/phonometry/metrology/__init__.py +++ b/src/phonometry/metrology/__init__.py @@ -12,7 +12,7 @@ from __future__ import annotations from .._compat import _namespace_dir, _namespace_shim -from .calibration import CalibrationWarning, calculate_sensitivity, sensitivity +from .calibration import CalibrationWarning, sensitivity from .data_qualification import ( LevelCrossingResult, PeakStatisticsResult, @@ -69,7 +69,6 @@ "TrendTestResult", "UncertaintyResult", "UncertaintyWarning", - "calculate_sensitivity", "combine_uncertainty", "level_crossing_rate", "monte_carlo", diff --git a/src/phonometry/metrology/calibration.py b/src/phonometry/metrology/calibration.py index c4aa47ccb..c68c84731 100644 --- a/src/phonometry/metrology/calibration.py +++ b/src/phonometry/metrology/calibration.py @@ -9,7 +9,7 @@ import numpy as np -from .._internal.warnings import PhonometryWarning, _warn_renamed +from .._internal.warnings import PhonometryWarning class CalibrationWarning(PhonometryWarning): @@ -118,30 +118,6 @@ def sensitivity( return float(factor) -def calculate_sensitivity( - ref_signal: list[float] | np.ndarray, - target_spl: float = 94.0, - ref_pressure: float = 2e-5, - fs: int | None = None, - validate: bool = True, - max_fluctuation_db: float | None = None, - frequency: float = 1000.0, - narrowband: bool = False, -) -> float: - """Deprecated alias of :func:`sensitivity`.""" - _warn_renamed("calculate_sensitivity()", "sensitivity()") - return sensitivity( - ref_signal, - target_spl=target_spl, - ref_pressure=ref_pressure, - fs=fs, - validate=validate, - max_fluctuation_db=max_fluctuation_db, - frequency=frequency, - narrowband=narrowband, - ) - - def _validate_reference_stability( signal_arr: np.ndarray, fs: int, max_fluctuation_db: float ) -> None: diff --git a/src/phonometry/psychoacoustics/loudness/ecma.py b/src/phonometry/psychoacoustics/loudness/ecma.py index 8d17210ec..69999c8a2 100644 --- a/src/phonometry/psychoacoustics/loudness/ecma.py +++ b/src/phonometry/psychoacoustics/loudness/ecma.py @@ -197,7 +197,7 @@ class EcmaLoudness: field: str def plot(self, ax: Axes | None = None, *, language: str = "en", **kwargs: Any) -> Axes | np.ndarray: - """Plot the average specific loudness N'(z) (see :mod:`._plotting`). + """Plot the average specific loudness N'(z) (see :mod:`phonometry._plot.psychoacoustics`). Adds a loudness-vs-time panel. Requires matplotlib (``pip install phonometry[plot]``). diff --git a/src/phonometry/psychoacoustics/loudness/moore_glasberg.py b/src/phonometry/psychoacoustics/loudness/moore_glasberg.py index c88053ccd..f1ce77933 100644 --- a/src/phonometry/psychoacoustics/loudness/moore_glasberg.py +++ b/src/phonometry/psychoacoustics/loudness/moore_glasberg.py @@ -535,7 +535,7 @@ def plot(self, ax: Axes | None = None, *, language: str = "en", **kwargs: Any) - """Plot the specific loudness N'(i) over the ERB-number scale. Requires matplotlib (``pip install phonometry[plot]``); returns the - :class:`~matplotlib.axes.Axes`. See :mod:`._plotting`. + :class:`~matplotlib.axes.Axes`. See :mod:`phonometry._plot.psychoacoustics`. """ from ..._i18n import check_language from ..._plot.psychoacoustics import plot_moore_glasberg_loudness diff --git a/src/phonometry/psychoacoustics/loudness/moore_glasberg_time.py b/src/phonometry/psychoacoustics/loudness/moore_glasberg_time.py index d390405bb..2b6f9171d 100644 --- a/src/phonometry/psychoacoustics/loudness/moore_glasberg_time.py +++ b/src/phonometry/psychoacoustics/loudness/moore_glasberg_time.py @@ -374,7 +374,7 @@ def plot(self, ax: Axes | None = None, *, language: str = "en", **kwargs: Any) - """Plot the short-term and long-term loudness against time. Requires matplotlib (``pip install phonometry[plot]``); returns the - :class:`~matplotlib.axes.Axes`. See :mod:`._plotting`. + :class:`~matplotlib.axes.Axes`. See :mod:`phonometry._plot.psychoacoustics`. """ from ..._i18n import check_language from ..._plot.psychoacoustics import plot_moore_glasberg_time_loudness diff --git a/src/phonometry/psychoacoustics/loudness/zwicker.py b/src/phonometry/psychoacoustics/loudness/zwicker.py index 629141cbf..89febcfca 100644 --- a/src/phonometry/psychoacoustics/loudness/zwicker.py +++ b/src/phonometry/psychoacoustics/loudness/zwicker.py @@ -118,7 +118,7 @@ class ZwickerLoudness: field: str | None = None def plot(self, ax: Axes | None = None, *, language: str = "en", **kwargs: Any) -> Axes | np.ndarray: - """Plot the specific loudness N'(z) over Bark (see :mod:`._plotting`). + """Plot the specific loudness N'(z) over Bark (see :mod:`phonometry._plot.psychoacoustics`). Adds a loudness-vs-time panel when the time-varying trace is present. Requires matplotlib (``pip install phonometry[plot]``); diff --git a/src/phonometry/psychoacoustics/quality/fluctuation_strength_ecma.py b/src/phonometry/psychoacoustics/quality/fluctuation_strength_ecma.py index 3b1bef368..f571d043f 100644 --- a/src/phonometry/psychoacoustics/quality/fluctuation_strength_ecma.py +++ b/src/phonometry/psychoacoustics/quality/fluctuation_strength_ecma.py @@ -216,7 +216,7 @@ class EcmaFluctuationStrength: field: str def plot(self, ax: Axes | None = None, *, language: str = "en", **kwargs: Any) -> Axes | np.ndarray: - """Plot the fluctuation-strength result (see :mod:`._plotting`). + """Plot the fluctuation-strength result (see :mod:`phonometry._plot.psychoacoustics`). Draws the time-dependent fluctuation strength F(l50) and a specific-fluctuation-strength heatmap. Requires matplotlib diff --git a/src/phonometry/psychoacoustics/quality/roughness_ecma.py b/src/phonometry/psychoacoustics/quality/roughness_ecma.py index b4f13d8de..76344e505 100644 --- a/src/phonometry/psychoacoustics/quality/roughness_ecma.py +++ b/src/phonometry/psychoacoustics/quality/roughness_ecma.py @@ -176,7 +176,7 @@ class EcmaRoughness: field: str def plot(self, ax: Axes | None = None, *, language: str = "en", **kwargs: Any) -> Axes | np.ndarray: - """Plot the roughness result (see :mod:`._plotting`). + """Plot the roughness result (see :mod:`phonometry._plot.psychoacoustics`). Draws the time-dependent roughness R(l50) and a specific-roughness heatmap. Requires matplotlib (``pip install phonometry[plot]``). diff --git a/src/phonometry/psychoacoustics/quality/tonality_ecma.py b/src/phonometry/psychoacoustics/quality/tonality_ecma.py index 97bd42e19..27ea27410 100644 --- a/src/phonometry/psychoacoustics/quality/tonality_ecma.py +++ b/src/phonometry/psychoacoustics/quality/tonality_ecma.py @@ -93,7 +93,7 @@ class EcmaTonality: field: str def plot(self, ax: Axes | None = None, *, language: str = "en", **kwargs: Any) -> Axes | np.ndarray: - """Plot the average specific tonality T'(z) (see :mod:`._plotting`). + """Plot the average specific tonality T'(z) (see :mod:`phonometry._plot.psychoacoustics`). Adds a tonality-vs-time panel. Requires matplotlib (``pip install phonometry[plot]``). diff --git a/src/phonometry/speech/sii.py b/src/phonometry/speech/sii.py index b180e7add..b0ea64dcb 100644 --- a/src/phonometry/speech/sii.py +++ b/src/phonometry/speech/sii.py @@ -55,8 +55,6 @@ from numpy.typing import ArrayLike -from .._internal.warnings import _warn_renamed - #: The four band procedures of ANSI S3.5-1997, in the order of its Tables 1 #: to 4: the critical-band procedure (21 bands), the equally-contributing #: critical-band procedure (17 bands), the one-third-octave-band procedure @@ -868,13 +866,3 @@ def sii_procedure(method: str = "one-third-octave") -> SIIProcedure: internal_noise=proc.internal_noise.copy(), speech_spectrum=proc.speech_spectrum.copy(), ) - - -# --- Deprecated alias (phonometry 3.1 rename; remove in 4.0) ------------- - -def __getattr__(name: str) -> Any: - """PEP 562 shim warning for the renamed band-center constant.""" - if name == "BAND_CENTRES": - _warn_renamed("BAND_CENTRES", "BAND_CENTERS") - return BAND_CENTERS - raise AttributeError(f"module 'phonometry.speech.sii' has no attribute {name!r}") diff --git a/tests/building/measurement/test_building_uncertainty.py b/tests/building/measurement/test_building_uncertainty.py index abb4f81f9..821e57f5c 100644 --- a/tests/building/measurement/test_building_uncertainty.py +++ b/tests/building/measurement/test_building_uncertainty.py @@ -415,15 +415,16 @@ def test_prediction_input_rejects_bad_n(): prediction_input_uncertainty(1.2, 1.0, 0) -def test_deprecated_bare_names_warn_and_delegate(): - # The bare names shadowed the GUM pair at the package root; they now warn - # and delegate to the insulation_* canonical functions. +def test_the_bare_names_are_gone(): + # The bare names shadowed the GUM pair at the package root. They were + # deprecated in 3.1 and removed in 4.0; only the insulation_* names remain. import phonometry.building.measurement.uncertainty as bu - with pytest.warns(DeprecationWarning, match="insulation_coverage_factor"): - assert bu.coverage_factor(0.95) == insulation_coverage_factor(0.95) - with pytest.warns(DeprecationWarning, match="insulation_expanded_uncertainty"): - assert bu.expanded_uncertainty(1.2) == insulation_expanded_uncertainty(1.2) + for name in ("coverage_factor", "expanded_uncertainty"): + with pytest.raises(AttributeError): + getattr(bu, name) + assert bu.insulation_coverage_factor(0.95) == insulation_coverage_factor(0.95) + assert bu.insulation_expanded_uncertainty(1.2) == insulation_expanded_uncertainty(1.2) # --------------------------------------------------------------------------- diff --git a/tests/materials/surfaces/test_road_absorption.py b/tests/materials/surfaces/test_road_absorption.py index 44dd74751..03692c8f5 100644 --- a/tests/materials/surfaces/test_road_absorption.py +++ b/tests/materials/surfaces/test_road_absorption.py @@ -375,6 +375,20 @@ def test_insitu_absorption_spectrum_rejects_nonpositive_fs() -> None: insitu_absorption_spectrum(hi, hr, -48000.0) +def test_the_functions_that_took_a_deprecated_fs_alias_still_require_fs() -> None: + """``fs`` is keyword-optional in the signature and required in fact. + + It reads as optional because it once shared the slot with the + ``sample_rate`` alias that 4.0 removed. Leaving it out has to say so. + """ + hi = _incident_ir() + hr = 0.4 * np.roll(hi, 96) + with pytest.raises(ValueError, match="missing required argument: 'fs'"): + adrienne_window(flat_duration=0.005) + with pytest.raises(ValueError, match="missing required argument: 'fs'"): + insitu_absorption_spectrum(hi, hr) + + def test_insitu_absorption_spectrum_plot_returns_axes() -> None: import matplotlib diff --git a/tests/test_deprecated_aliases.py b/tests/test_deprecated_aliases.py index 29e1f56a3..3ede76789 100644 --- a/tests/test_deprecated_aliases.py +++ b/tests/test_deprecated_aliases.py @@ -1,15 +1,11 @@ # Copyright (c) 2026. Jose Manuel Requena Plens -"""One-cycle deprecation shims of the phonometry renames. +"""Deprecation shims of the phonometry renames, and what 4.0 removed. -One :func:`pytest.warns` test per alias (CONTRIBUTING, "Deprecations"): -the renamed ``loudness`` module (PEP 562 shim), the legacy snake_case -function aliases and the renamed keyword arguments (scikit-learn -``"deprecated"`` sentinel). Every alias must warn with the NEP 23 message -and delegate to the canonical name. - -The 3.2 module moves were removed in 4.0, as announced; what is left here is -the 3.1 function and keyword renames and the 4.0 taxonomy aliases, which go in -5.0. +The 3.1 renames (function aliases, renamed constants, deprecated keywords) and +the 3.2 module moves both named 4.0 as their removal, and 4.0 removed them: the +first half of this file pins them gone. What is left alive is the 4.0 taxonomy, +whose aliases warn with the NEP 23 message, delegate to the canonical name and +go in 5.0 (CONTRIBUTING, "Deprecations"). """ from __future__ import annotations @@ -28,243 +24,78 @@ # --------------------------------------------------------------------------- # -# Legacy snake_case function aliases -# --------------------------------------------------------------------------- # -def test_octavefilter_warns_and_delegates() -> None: - canonical_spl, canonical_freq = ph.octave_filter(SIGNAL, 48000) - with pytest.warns(DeprecationWarning, match=r"octave_filter\(\)"): - spl, freq = ph.octavefilter(SIGNAL, 48000) - np.testing.assert_allclose(spl, canonical_spl) - assert freq == canonical_freq - - -def test_filters_octavefilter_warns_and_delegates() -> None: - """The alias exported by phonometry.filters keeps the top-level behavior.""" - from phonometry import filters - - assert filters.octave_filter is ph.octave_filter - assert filters.octavefilter is ph.octavefilter - canonical_spl, canonical_freq = filters.octave_filter(SIGNAL, 48000) - with pytest.warns(DeprecationWarning, match=r"octave_filter\(\)"): - spl, freq = filters.octavefilter(SIGNAL, 48000) - np.testing.assert_allclose(spl, canonical_spl) - assert freq == canonical_freq - - -def test_getansifrequencies_warns_and_delegates() -> None: - canonical = ph.nominal_frequencies(3, [100, 5000]) - with pytest.warns(DeprecationWarning, match=r"nominal_frequencies\(\)"): - legacy = ph.getansifrequencies(3, [100, 5000]) - assert legacy == canonical - - -def test_normalizedfreq_warns_and_delegates() -> None: - canonical = ph.normalized_frequencies(1) - with pytest.warns(DeprecationWarning, match=r"normalized_frequencies\(\)"): - legacy = ph.normalizedfreq(1) - assert legacy == canonical - - -def test_calculate_sensitivity_warns_and_delegates() -> None: - tone = np.sin(2 * np.pi * 1000.0 * np.arange(4800) / FS) - canonical = ph.sensitivity(tone, target_spl=94.0) - with pytest.warns(DeprecationWarning, match=r"sensitivity\(\)"): - legacy = ph.calculate_sensitivity(tone, target_spl=94.0) - assert legacy == canonical - - -# --------------------------------------------------------------------------- # -# Renamed keyword: road_absorption sample_rate -> fs -# --------------------------------------------------------------------------- # -def test_adrienne_window_sample_rate_warns_and_forwards() -> None: - canonical = ph.adrienne_window(FS) - with pytest.warns(DeprecationWarning, match="'sample_rate' keyword"): - legacy = ph.adrienne_window(sample_rate=FS) - np.testing.assert_allclose(legacy, canonical) - with pytest.warns(DeprecationWarning), pytest.raises(ValueError, match="both"): - ph.adrienne_window(FS, sample_rate=FS) - with pytest.raises(ValueError, match="missing required argument: 'fs'"): - ph.adrienne_window() - - -def test_insitu_reflection_factor_sample_rate_warns_and_forwards() -> None: - hi = np.zeros(256) - hi[8] = 1.0 - hr = 0.5 * np.roll(hi, 16) - delay = 16 / FS - canonical = ph.insitu_reflection_factor(hi, hr, fs=FS, delay=delay) - with pytest.warns(DeprecationWarning, match="'sample_rate' keyword"): - legacy = ph.insitu_reflection_factor(hi, hr, sample_rate=FS, delay=delay) - np.testing.assert_allclose(legacy, canonical) - with pytest.warns(DeprecationWarning), pytest.raises(ValueError, match="both"): - ph.insitu_reflection_factor(hi, hr, fs=FS, sample_rate=FS) - - -def test_insitu_absorption_spectrum_sample_rate_warns_and_forwards() -> None: - hi = np.zeros(4096) - hi[16] = 1.0 - hr = 0.5 * np.roll(hi, 32) - canonical = ph.insitu_absorption_spectrum(hi, hr, FS) - with pytest.warns(DeprecationWarning, match="'sample_rate' keyword"): - legacy = ph.insitu_absorption_spectrum(hi, hr, sample_rate=FS) - np.testing.assert_allclose(legacy.absorption, canonical.absorption) - with pytest.raises(ValueError, match="missing required argument: 'fs'"): - ph.insitu_absorption_spectrum(hi, hr) - - -# --------------------------------------------------------------------------- # -# Renamed keyword: outdoor_propagation humidity -> relative_humidity +# 3.1 renames: the function aliases, the renamed constants and the deprecated +# keywords were removed in 4.0, as their notices said since 3.1. Frozen lists; +# the point is that they stay gone. # --------------------------------------------------------------------------- # -def test_atmospheric_absorption_humidity_warns_and_forwards() -> None: - canonical = ph.atmospheric_absorption(200.0, [1000.0], relative_humidity=50.0) - with pytest.warns(DeprecationWarning, match="'humidity' keyword"): - legacy = ph.atmospheric_absorption(200.0, [1000.0], humidity=50.0) - np.testing.assert_allclose(legacy, canonical) - with pytest.warns(DeprecationWarning), pytest.raises(ValueError, match="both"): - ph.atmospheric_absorption( - 200.0, [1000.0], relative_humidity=50.0, humidity=50.0 - ) - - -def test_outdoor_propagation_attenuation_humidity_warns_and_forwards() -> None: - canonical = ph.outdoor_propagation_attenuation( - 100.0, 2.0, 4.0, [500.0], relative_humidity=50.0 - ) - with pytest.warns(DeprecationWarning, match="'humidity' keyword"): - legacy = ph.outdoor_propagation_attenuation( - 100.0, 2.0, 4.0, [500.0], humidity=50.0 - ) - np.testing.assert_allclose(legacy.a_total, canonical.a_total) - - -def test_predicted_receiver_level_humidity_warns_and_forwards() -> None: - canonical = ph.predicted_receiver_level( - [95.0], 100.0, 2.0, 4.0, [500.0], relative_humidity=50.0 - ) - with pytest.warns(DeprecationWarning, match="'humidity' keyword"): - legacy = ph.predicted_receiver_level( - [95.0], 100.0, 2.0, 4.0, [500.0], humidity=50.0 - ) - np.testing.assert_allclose(legacy, canonical) - - -# --------------------------------------------------------------------------- # -# Renamed keyword: sound_power room_volume -> volume -# --------------------------------------------------------------------------- # -def test_environmental_correction_room_volume_warns_and_forwards() -> None: - canonical = ph.environmental_correction( - 40.0, reverberation_time=1.2, volume=300.0 - ) - with pytest.warns(DeprecationWarning, match="'room_volume' keyword"): - legacy = ph.environmental_correction( - 40.0, reverberation_time=1.2, room_volume=300.0 - ) - assert legacy == canonical - with pytest.warns(DeprecationWarning), pytest.raises(ValueError, match="both"): - ph.environmental_correction( - 40.0, reverberation_time=1.2, volume=300.0, room_volume=300.0 - ) - - -def test_sound_power_pressure_room_volume_warns_and_forwards() -> None: - levels = np.tile(np.array([90.0, 92.0, 95.0]), (10, 1)) - canonical = ph.sound_power_pressure( - levels, "hemisphere", radius=2.0, reverberation_time=1.0, volume=2000.0 - ) - with pytest.warns(DeprecationWarning, match="'room_volume' keyword"): - legacy = ph.sound_power_pressure( - levels, - "hemisphere", - radius=2.0, - reverberation_time=1.0, - room_volume=2000.0, - ) - np.testing.assert_allclose( - legacy.sound_power_level, canonical.sound_power_level - ) - - -def test_room_volume_explicit_none_stays_silent() -> None: - # None was the old default; passing it through the deprecated alias must - # not warn (only a real value does). - import warnings - - import phonometry as ph - - with warnings.catch_warnings(): - warnings.simplefilter("error", DeprecationWarning) - ph.environmental_correction(50.0, absorption_area=10.0, room_volume=None) - - -# --------------------------------------------------------------------------- # -# Renamed constants (unit suffixes dropped) and the renamed warning class, -# aliased through module-level PEP 562 __getattr__ (constants cannot warn as -# wrappers). Each alias exists in its home module and, when re-exported, at -# the package root. -# --------------------------------------------------------------------------- # -def test_octave_bands_hz_warns_and_delegates() -> None: - from phonometry.materials.absorbers import rating as absorption_rating - - with pytest.warns(DeprecationWarning, match="use OCTAVE_BANDS"): - legacy = ph.OCTAVE_BANDS_HZ - assert legacy is ph.OCTAVE_BANDS - with pytest.warns(DeprecationWarning, match="deprecated since phonometry 3.1"): - module_legacy = absorption_rating.OCTAVE_BANDS_HZ - assert module_legacy is absorption_rating.OCTAVE_BANDS - - -def test_third_octave_bands_hz_warns_and_delegates() -> None: - from phonometry.materials.absorbers import rating as absorption_rating +_REMOVED_FUNCTIONS = [ + ("phonometry", "octavefilter"), + ("phonometry.filters", "octavefilter"), + ("phonometry.filters.core", "octavefilter"), + ("phonometry.filters.frequencies", "getansifrequencies"), + ("phonometry.filters.frequencies", "normalizedfreq"), + ("phonometry.metrology.calibration", "calculate_sensitivity"), + ("phonometry.building.measurement.uncertainty", "coverage_factor"), + ("phonometry.building.measurement.uncertainty", "expanded_uncertainty"), +] - with pytest.warns(DeprecationWarning, match="use THIRD_OCTAVE_BANDS"): - legacy = ph.THIRD_OCTAVE_BANDS_HZ - assert legacy is ph.THIRD_OCTAVE_BANDS - with pytest.warns(DeprecationWarning, match="deprecated since phonometry 3.1"): - module_legacy = absorption_rating.THIRD_OCTAVE_BANDS_HZ - assert module_legacy is absorption_rating.THIRD_OCTAVE_BANDS +_REMOVED_CONSTANTS = [ + ("phonometry", "OCTAVE_BANDS_HZ"), + ("phonometry", "THIRD_OCTAVE_BANDS_HZ"), + ("phonometry", "BASE_PLATE_BANDS_HZ"), + ("phonometry", "ExposureWarning"), + ("phonometry.materials.absorbers.rating", "OCTAVE_BANDS_HZ"), + ("phonometry.materials.diffusers.scattering_diffusion", "BASE_PLATE_BANDS_HZ"), + ("phonometry.speech.sii", "BAND_CENTRES"), + ("phonometry.hearing.occupational_exposure", "ExposureWarning"), +] +_REMOVED_KEYWORDS = [ + ("adrienne_window", "sample_rate"), + ("insitu_reflection_factor", "sample_rate"), + ("insitu_absorption_spectrum", "sample_rate"), + ("atmospheric_absorption", "humidity"), + ("outdoor_propagation_attenuation", "humidity"), + ("predicted_receiver_level", "humidity"), + ("environmental_correction", "room_volume"), + ("sound_power_pressure", "room_volume"), +] -def test_base_plate_bands_hz_warns_and_delegates() -> None: - from phonometry.materials.diffusers import scattering_diffusion - with pytest.warns(DeprecationWarning, match="use BASE_PLATE_BANDS"): - legacy = ph.BASE_PLATE_BANDS_HZ - assert legacy is ph.BASE_PLATE_BANDS - with pytest.warns(DeprecationWarning, match="deprecated since phonometry 3.1"): - module_legacy = scattering_diffusion.BASE_PLATE_BANDS_HZ - assert module_legacy is scattering_diffusion.BASE_PLATE_BANDS +@pytest.mark.parametrize(("module", "name"), _REMOVED_FUNCTIONS + _REMOVED_CONSTANTS) +def test_removed_3_1_alias_is_gone(module: str, name: str) -> None: + import importlib + home = importlib.import_module(module) + with pytest.raises(AttributeError): + getattr(home, name) -def test_band_centres_warns_and_delegates() -> None: - from phonometry.speech import sii - with pytest.warns(DeprecationWarning, match="use BAND_CENTERS"): - legacy = sii.BAND_CENTRES - assert legacy is sii.BAND_CENTERS +@pytest.mark.parametrize(("func", "keyword"), _REMOVED_KEYWORDS) +def test_removed_3_1_keyword_is_gone(func: str, keyword: str) -> None: + import inspect + assert keyword not in inspect.signature(getattr(ph, func)).parameters -def test_exposure_warning_warns_and_delegates() -> None: - from phonometry.hearing import occupational_exposure - with pytest.warns(DeprecationWarning, match="use OccupationalExposureWarning"): - legacy = ph.ExposureWarning - # Same class object: isinstance/except/filters via the old name still match. - assert legacy is ph.OccupationalExposureWarning - with pytest.warns(DeprecationWarning, match="deprecated since phonometry 3.1"): - module_legacy = occupational_exposure.ExposureWarning - assert module_legacy is ph.OccupationalExposureWarning +def test_the_canonical_names_the_3_1_aliases_pointed_at_are_all_here() -> None: + """The removal took the aliases, not the functions they delegated to.""" + for name in ( + "octave_filter", "nominal_frequencies", "normalized_frequencies", + "sensitivity", "insulation_coverage_factor", + "insulation_expanded_uncertainty", "OCTAVE_BANDS", "THIRD_OCTAVE_BANDS", + "BASE_PLATE_BANDS", "OccupationalExposureWarning", + ): + assert hasattr(ph, name), name -def test_renamed_attribute_shims_reject_unknown_names() -> None: - from phonometry.hearing import occupational_exposure - from phonometry.materials.absorbers import rating as absorption_rating +def test_the_plot_renderers_moved_out_of_the_deprecated_module() -> None: + """``phonometry._plotting`` was the 3.2 re-export; ``_plot`` is the home.""" + import importlib - with pytest.raises(AttributeError, match="phonometry"): - _ = ph.does_not_exist - with pytest.raises(AttributeError, match="absorbers.rating"): - _ = absorption_rating.does_not_exist - with pytest.raises(AttributeError, match="occupational_exposure"): - _ = occupational_exposure.does_not_exist + with pytest.raises(ModuleNotFoundError): + importlib.import_module("phonometry._plotting") + assert callable(importlib.import_module("phonometry._plot.room").plot_excitation) # --------------------------------------------------------------------------- # @@ -606,107 +437,6 @@ def test_narrowed_namespace_falls_back_to_the_module_alias() -> None: assert metrology.correlation is ph.correlation -# Frozen snapshot of the ``phonometry._plotting`` re-export surface (the -# renderers as of the 3.2 move); do NOT regenerate from the live tree. -_PLOTTING_RENDERERS = [ - "plot_absorption_uncertainty", - "plot_age_threshold", - "plot_airborne_insulation", - "plot_airborne_prediction", - "plot_aircraft_band_attenuation", - "plot_ambient_noise", - "plot_band_uncertainty", - "plot_bottom_loss", - "plot_daily_exposure", - "plot_decay_curve", - "plot_diffusion_polar", - "plot_dynamic_stiffness", - "plot_ecma_loudness", - "plot_ecma_roughness", - "plot_ecma_tonality", - "plot_enclosed_space_absorption", - "plot_epnl", - "plot_excitation", - "plot_facade_insulation", - "plot_facade_prediction", - "plot_fdtd_probes", - "plot_fdtd_snapshot", - "plot_floor_covering_improvement", - "plot_fluctuation_strength", - "plot_flyover", - "plot_frequency_response", - "plot_harmonic_distortion", - "plot_htlan", - "plot_impact_insulation", - "plot_impact_prediction", - "plot_impact_rating", - "plot_impedance_tube", - "plot_impulse_prominence", - "plot_impulse_response", - "plot_insitu_absorption", - "plot_installed_structure_borne", - "plot_intensity", - "plot_mobility", - "plot_monte_carlo", - "plot_moore_glasberg_loudness", - "plot_moore_glasberg_time_loudness", - "plot_multiple_shock", - "plot_nipts", - "plot_noise_contour", - "plot_noise_criterion", - "plot_normal_modes", - "plot_npd_level", - "plot_occupational_exposure", - "plot_open_plan", - "plot_outdoor_attenuation", - "plot_parabolic_equation", - "plot_pile_strike", - "plot_psychoacoustic_annoyance", - "plot_radiated_power", - "plot_ray_trace", - "plot_reverberation_models", - "plot_room_acoustics", - "plot_room_criterion", - "plot_rotorcraft_hemisphere", - "plot_scattering_coefficient", - "plot_ship_source_level", - "plot_ship_traffic_spectrum", - "plot_sii", - "plot_sonar_equation", - "plot_sound_power", - "plot_sound_speed_profile", - "plot_static_airflow", - "plot_sti", - "plot_structure_borne_power", - "plot_tonal_adjustment", - "plot_tone_audibility", - "plot_transfer_stiffness", - "plot_transmission_loss", - "plot_uncertainty_budget", - "plot_vibration_reduction", - "plot_vibration_sound_power", - "plot_vibration_weighting", - "plot_weighted_absorption", - "plot_weighted_rating", - "plot_weighted_spectrum", - "plot_wind_turbine_tonality", - "plot_zwicker_loudness", -] - - -def test_plotting_shim_re_exports_every_renderer() -> None: - """``phonometry._plotting`` silently re-exports the full renderer set.""" - import importlib - import warnings - - with warnings.catch_warnings(): - warnings.simplefilter("error", DeprecationWarning) - module = importlib.import_module("phonometry._plotting") - assert sorted(module.__all__) == _PLOTTING_RENDERERS - for name in _PLOTTING_RENDERERS: - assert callable(getattr(module, name)), name - - def test_moved_module_shims_warn_and_delegate() -> None: import importlib