Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7677b26
Every call in the API table binds to the signature it shows, and the …
jmrplens Oct 21, 2026
3c7d09c
The module gate reads where a relative import resolves, so a package …
jmrplens Oct 21, 2026
e3449b0
The prose around a count says the noun again (planes, sections, axles…
jmrplens Oct 21, 2026
019a86a
Each comment in the calibration, induction-loop and room-to-room exam…
jmrplens Oct 21, 2026
b86eba7
A record built by hand meets the checks its builder's answer meets: t…
jmrplens Oct 21, 2026
5d28c64
A spectrogram carries the band edges of its bank, so a single band is…
jmrplens Oct 21, 2026
a7a1d07
A renderer's keyword no longer collides with the caller's: plot(zorde…
jmrplens Oct 21, 2026
b093916
The unit and spelling gates read what a published class inherits from…
jmrplens Oct 21, 2026
20b5e69
The contributor guide test holds every rule to its Why, Do and Don't,…
jmrplens Oct 21, 2026
1374f9e
The hearing groups a guidance lists, and the group a criteria record …
jmrplens Oct 21, 2026
f1f5f18
A source names its cell by a whole number held as an int, so ix=2.0 r…
jmrplens Oct 21, 2026
f043e3c
The CuPy proof is re-run on the engine as it stands
jmrplens Oct 21, 2026
9d74da5
A clip worker no longer keeps the figures of every wavefront clip it …
jmrplens Oct 21, 2026
c801d57
The style gate reads the keywords beside **kwargs one function at a t…
jmrplens Oct 21, 2026
3d93547
The conformance record asks each of its numbers its rank before anyth…
jmrplens Oct 21, 2026
9054091
A keyword written beside a mapping built from the caller's, **{...} o…
jmrplens Oct 21, 2026
0abadef
The reflection index records refuse single numbers where they hold ba…
jmrplens Oct 21, 2026
fc49131
A spectrogram's band edges are the bands of one bank: positive, enclo…
jmrplens Oct 21, 2026
4e553c4
An elided argument list in the API table spares only the call that el…
jmrplens Oct 21, 2026
8733e0e
The reflection index records hold the layout of EN 1793-5, eighteen b…
jmrplens Oct 21, 2026
a5130a9
A renderer refuses by name the keywords it computes from the data, an…
jmrplens Oct 21, 2026
f6d80b5
The guide test reads extend-ignore too, and the count-name test reads…
jmrplens Oct 21, 2026
de9e23e
The levels guide draws its spectrogram by hand from the band edges th…
jmrplens Oct 21, 2026
76d0948
The style gate counts a key taken out of the caller's keywords only b…
jmrplens Oct 21, 2026
96d2637
The style gate follows an annotated or a walrus copy of the caller's …
jmrplens Oct 21, 2026
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
10 changes: 6 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3742,10 +3742,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- **Results that were tuples are records: the spectrogram, the band set, the
octave bands of the building improvements and the EPNL integration.**
`OctaveFilterBank.spectrogram` returns a `filters.OctaveSpectrogramResult`
(`levels`, `frequencies` as a read-only array, `times`) that checks its
level grid against both axes and draws itself with `.plot()`: one raster on
a logarithmic frequency axis, each row the band it was measured in, with a
dB colour bar, and `channel=` to pick the channel of a multichannel result.
(`levels`, `frequencies` as a read-only array, `times`, and the
`lower_edges` and `upper_edges` of the bank's bands) that checks its level
grid against every axis and draws itself with `.plot()`: one raster on a
logarithmic frequency axis, each row the band it was measured in, between
that band's edges, with a dB colour bar, and `channel=` to pick the channel
of a multichannel result.
`filters.nominal_frequencies` returns a `filters.FractionalOctaveBands`
(`frequencies`, `lower_edges`, `upper_edges` and the nominal `labels` as a
tuple of text). `building.improvement_octave_bands` and the `octave_bands()`
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Each rule on a page has the same parts:
- **Enforced by**: the check that holds the rule: a script, a test (`path::test_name`), a Makefile target (`make target`), a ruff code (`ruff CODE`), a CI job or step (`CI: its name`), `mypy` or `bandit`, or review when no check does.
- **Exceptions**: only when there are some, with how one is declared.

`tests/test_contributing_guide.py` holds the guide to this shape: it fails when a page and this index disagree, when an enforcer names a check that does not exist, or when a link into the guide misses its anchor.
`tests/test_contributing_guide.py` holds the guide to this shape: it fails when a rule lacks its Why, its Do or its Don't, or an example label has no fence after it, when a page and this index disagree, when an enforcer names a check that does not exist or that the configuration switches off, or when a link into the guide misses its anchor.

## Pages

Expand Down
4 changes: 2 additions & 2 deletions docs/devices/electroacoustics/induction-loops.md
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,8 @@ section 6:

```python
lift = electroacoustics.amplifier_frequency_response(
[2.0, 2.0, 2.4, 2.9, 3.2, 3.5, 3.6],
frequencies=[100.0, 1000.0, 2000.0, 3150.0, 4000.0, 5000.0, 8000.0], # output current, A
[2.0, 2.0, 2.4, 2.9, 3.2, 3.5, 3.6], # output current, A
frequencies=[100.0, 1000.0, 2000.0, 3150.0, 4000.0, 5000.0, 8000.0],
)
print(lift.response_db.round(2)) # [0. 0. 1.58 3.23 4.08 4.86 5.11] dB re 1 kHz
speech = electroacoustics.verify_amplifier_overload(current, z, 11.0, current_response=lift)
Expand Down
2 changes: 1 addition & 1 deletion docs/devices/electroacoustics/swept-sine-distortion.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ grids.
- [`impulse_response`](../../buildings/rooms/room-acoustics.md) recovers the *linear* IR from the
same sweep recording and simply discards the negative-time distortion
products; `swept_sine_distortion` is the tool that reads them.
- [`thd_ratio` / `harmonic_analysis`](electroacoustics.md) measure distortion
- [`thd` / `harmonic_analysis`](electroacoustics.md) measure distortion
from a steady tone at one frequency; the sweep separator returns the same
ratios as a continuous function of frequency, from one measurement.
- The phase utilities operate on any one-sided *complex* response: an
Expand Down
6 changes: 3 additions & 3 deletions docs/devices/noise-control/room-to-room.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ operator = [(25.0, [0.08, 0.24, 0.57, 0.69, 0.71, 0.73]),
(25.0, ceiling), (60.0, walls)]

chain = noise_control.room_to_room_transmission(
[39.0, 42.0, 50.0, 58.0, 63.0, 67.0],
5.0 * 3.0, # TL of the separating wall
room.equivalent_absorption_area(operator), # the wall is 5 m x 3 m
[39.0, 42.0, 50.0, 58.0, 63.0, 67.0], # TL of the separating wall
5.0 * 3.0, # the wall is 5 m x 3 m
room.equivalent_absorption_area(operator),
frequencies=bands,
source=noise_control.SourceRoom(
power_level=[105.0, 103.0, 98.0, 108.0, 107.0, 109.0],
Expand Down
30 changes: 15 additions & 15 deletions docs/reference/api/index.md

Large diffs are not rendered by default.

20 changes: 11 additions & 9 deletions docs/signals/levels/levels.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,15 +408,16 @@ result = bank.spectrogram(x, window_time=0.125, overlap=0.875)
result.plot()
plt.show()

# By hand, from the result's fields. The rows are spaced evenly in log10
# of the frequency, so the raster is laid out there, half a band step
# either side of each centre, and carried onto the logarithmic axis through
# 10**y: an image placed straight on a log axis spreads its rows evenly in Hz.
# By hand, from the result's fields. The bands are equally wide in log10 of
# the frequency, so the raster is laid out there, from the lower edge of the
# first band to the upper edge of the last, and carried onto the logarithmic
# axis through 10**y: an image placed straight on a log axis spreads its rows
# evenly in Hz.
from matplotlib.scale import LogTransform
from matplotlib.transforms import IdentityTransform, blended_transform_factory

f, t = result.frequencies, result.times
half_band = np.log10(f[-1] / f[0]) / (2 * (f.size - 1))
t = result.times
lower, upper = result.lower_edges, result.upper_edges
half_hop = (t[1] - t[0]) / 2
fig, ax = plt.subplots()
ax.set_yscale("log")
Expand All @@ -426,9 +427,9 @@ image = ax.imshow(result.levels, origin="lower", aspect="auto", cmap="magma",
interpolation="nearest", transform=rows,
vmin=result.levels.max() - 80.0, vmax=result.levels.max(),
extent=(t[0] - half_hop, t[-1] + half_hop,
np.log10(f[0]) - half_band, np.log10(f[-1]) + half_band))
np.log10(lower[0]), np.log10(upper[-1])))
ax.set_xlim(t[0] - half_hop, t[-1] + half_hop)
ax.set_ylim(f[0] / 10**half_band, f[-1] * 10**half_band)
ax.set_ylim(lower[0], upper[-1])
ax.set(xlabel="Time [s]", ylabel="Frequency [Hz]")
fig.colorbar(image, label="Band level [dB]")
plt.show()
Expand All @@ -440,7 +441,8 @@ plt.show()
`times` by name, or draw it with `result.plot()`.
- Multichannel input `(channels, samples)` gives `levels` shaped
`(channels, bands, frames)`; `result.plot(channel=0)` draws one channel.
- `times` holds each window's center in seconds.
- `times` holds each window's center in seconds, and `lower_edges` and
`upper_edges` hold each band's edges, between which the plot draws its row.
- `mode='peak'` gives per-window peak-holding levels instead of RMS.
- `zero_phase=True` filters bands forward-backward so per-band group delay does
not skew the frames (offline analysis only).
Expand Down
6 changes: 3 additions & 3 deletions docs/signals/metrology/comparison-calibration.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ def free_field_budget(fx):

free = metrology.sequential_comparison(
l_ref_p,
l_ref_p + c_ff + field_1,
l_ws2f + field_2, # the reference's output, dB re 1 V
frequencies=ff, # the WS2F's output in its place
l_ref_p + c_ff + field_1, # the reference's output, dB re 1 V
l_ws2f + field_2, # the WS2F's output in its place
frequencies=ff,
monitor=metrology.MonitorReadings(
reference_level=monitor + field_1, test_level=monitor + field_2
),
Expand Down
10 changes: 5 additions & 5 deletions docs/signals/metrology/free-field-corrections.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ pressure = -0.1 * x**1.5 # the meter on the calibrator, r
spread = np.array([[0.0], [0.02], [-0.03]]) * x**0.8 # three microphones of the model

c = metrology.sound_calibrator_correction(
94.0 + free + spread,
94.0 + c_ff_rm, # L_ind1: the meter in the free field
94.0 + pressure + spread / 2, # L_ind2: the reference in its place
94.0, # L_ind3: the calibrator on the meter
frequencies=f, # L_ind4: the calibrator on the reference
94.0 + free + spread, # L_ind1: the meter in the free field
94.0 + c_ff_rm, # L_ind2: the reference in its place
94.0 + pressure + spread / 2, # L_ind3: the calibrator on the meter
94.0, # L_ind4: the calibrator on the reference
frequencies=f,
reference_free_field_correction=c_ff_rm,
)
print(c.correction.round(2)) # [-0.04 -0.09 -0.1 -0.05 0.05 0.23 0.63 1.72 4.95]
Expand Down
6 changes: 3 additions & 3 deletions docs/signals/metrology/random-incidence.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,9 @@ print(metrology.IEC61183_TABLE_B1[8000.0])
delta_dp = np.array([metrology.IEC61183_TABLE_B1[f].diffuse_pressure_difference_db
for f in bands])
dd = metrology.diffuse_field_sensitivity(
80.0 + r.random_incidence_level,
80.0 + delta_dp, # L_D, the meter under test
frequencies=bands, # L_D,ref, a pressure-calibrated LS2aP
80.0 + r.random_incidence_level, # L_D, the meter under test
80.0 + delta_dp, # L_D,ref, a pressure-calibrated LS2aP
frequencies=bands,
reference_pressure_level=0.0, # G_P,ref; Delta_DP from Table B.1
)
print(dd.reference_correction[shown]) # [0. 0.25 1.2 3.05]
Expand Down
2 changes: 1 addition & 1 deletion gpu-parity.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"cuda_driver_api": "13.3",
"cupy": "14.2.0",
"cupy_cuda_runtime": "13.2",
"engine_fingerprint": "14a4ef9ecbe3224022fb53be2918faea06f1c41d2d2dc8f1cda7a06d150d5119",
"engine_fingerprint": "65eb48cbf55579100b2b50a1e4e5c5e4702ad3d914d6d4841dc39d746b703068",
"fields_bit_identical": true,
"fields_max_relative": {
"contour": 0.0,
Expand Down
Loading
Loading