Skip to content

Results that were tuples are named records, tolerance limits come lower first, and a record's required fields refuse to be left empty - #978

Open
jmrplens wants to merge 1 commit into
fix/verdicts-spell-passes-and-refuse-truthfrom
fix/records-instead-of-tuples
Open

jmrplens wants to merge 1 commit into
fix/verdicts-spell-passes-and-refuse-truthfrom
fix/records-instead-of-tuples

Conversation

@jmrplens

@jmrplens jmrplens commented Oct 17, 2026 •

Copy link
Copy Markdown
Owner

What changes for you

Four answers that came back as a tuple to be unpacked by position are records with named fields now. OctaveFilterBank.spectrogram returns a filters.OctaveSpectrogramResult with levels, a read-only frequencies and times; it checks the level grid against both axes and draws itself with .plot(), one raster over time and the logarithmic band centre with a dB colour bar, and a multichannel result asks for channel=. filters.nominal_frequencies returns a filters.FractionalOctaveBands with read-only frequencies, lower_edges and upper_edges and the IEC 61260-1 nominal labels as a tuple of text; the filter bank reads its band set from the same record, as bank.frequencies, bank.lower_edges, bank.upper_edges, bank.labels and bank.n_bands, all read-only. building.improvement_octave_bands and the octave_bands() methods of the floor-covering, laboratory lining, laboratory floor-covering, joint and rainfall results return a building.OctaveBandSpectrum with frequencies, values in dB and the quantity they hold, which plots itself in English or Spanish under the symbol its source prints. aircraft.epnl_from_pnlt returns an aircraft.EPNLIntegration with epnl, pnltm, bandsharing_adjustment, band_limits and the derived duration_correction, and effective_perceived_noise_level builds its EPNLResult from it.

The vibration tolerance limits now come lower first, (lower, upper), as the filter and weighting masks already did. vibration.weighting_tolerance_percent returns the ISO 8041-1 Table 5 band lower first, and CENTRAL_TOLERANCE_PERCENT, SKIRT_TOLERANCE_PERCENT and TAIL_TOLERANCE_PERCENT hold (lower %, upper %, phase °). vibration.response_tolerance_percent returns the DIN 45669-1 Table 2 lower limit signed, as the condition of 5.2.3.3 applies it: -10 % from 1,25 f_u to 0,8 f_o, -20 % out to 0,5 f_u and 2 f_o, and -100 %, no lower limit, beyond them. VibrationMeterVerification.lower_percent holds it the same way.

rounded is a read-only property wherever a result has one. building.CeilingAttenuationResult.rounded is read from measured, to the nearest integer as ASTM E413 clause 5.2 asks (the clause leaves a half open, and the library rounds it up), so it cannot disagree with the data. The cabin, enclosure, screen and measured barrier results expose rounded (and rounded_a_weighted on the screen) as properties.

The fields that defaulted to None only so that a hand-built result would still construct are required, and a record built without one, or with None for one, raises TypeError naming the field: the measurement chain of building.AirborneInsulationResult and building.ImpactInsulationResult, the curves of the ISO 717 ratings and their extended forms, the depth of an aperture, the elements of a façade prediction, the probe spacing of an intensity result, the five geometry fields of environment.BarrierInsertionLoss and the sound field of psychoacoustics.ZwickerLoudness. The reports, plots and geometry drawings lose the branches that refused a record without them. filters.WeightingFilter takes high_accuracy as a bool, True by default.

The errata register records one more misprint: ICAO Annex 16, Volume I (2017), Appendix 2, 4.4.2 prints the bandsharing adjustment as ΔB = Cavg C(kM), without the minus sign between the two tone corrections. The library implements the difference, which the condition of the same formula and the Nomenclature fix.

A tone-corrected perceived noise level is stated in TPNdB, the unit the Nomenclature of ICAO Annex 16, Volume I prints for PNLT and PNLTM. The PNLT series and the PNLTM of aircraft.EPNLResult, aircraft.EPNLIntegration and aircraft.RotorcraftEventResult say so in their documentation and in the notebook table, the .plot() of EPNLResult labels its PNLTM point in TPNdB and its axis in PNdB and TPNdB, and the EPNL fiche reads PNLTM [TPNdB]; the PNL stays in PNdB and the EPNL in EPNdB, and no number changes.

The EPNL flyover animation (anim_epnl_flyover) draws the PNLT series and its maximum, so its labels read TPNdB too: its frames change with this layer, and the clip is rendered and published again with it. The microphone label in that clip no longer sits under the ground line, which struck through it.

The per-band rows of the three verifiers that return them say frequency where they said freq: the bands rows of filters.FilterComplianceResult, filters.WeightingComplianceResult and emission.IntensityInstrumentComplianceResult, and worst_frequency in the between-nominals sweep of WeightingComplianceResult, the spelling every field of the library already uses for the axis.

The migration guide has grown past what one fetch of the llms-start.txt shard can carry, so it travels in a shard of its own, llms-upgrading.txt, listed in llms.txt beside the start shard.

What breaks

None of the new records unpacks: a line that still unpacks one raises TypeError instead of handing back the wrong column. Read the fields instead:

  • levels, freq, times = bank.spectrogram(x) becomes r = bank.spectrogram(x) with r.levels, r.frequencies and r.times.
  • freq, lower, upper, labels = filters.nominal_frequencies(3) becomes b = filters.nominal_frequencies(3) with b.frequencies, b.lower_edges, b.upper_edges and b.labels.
  • bank.freq, bank.freq_d, bank.freq_u, bank.nominal_freq and bank.num_bands are bank.frequencies, bank.lower_edges, bank.upper_edges, bank.labels and bank.n_bands.
  • epnl, pnltm, kf, kl = aircraft.epnl_from_pnlt(pnlt) becomes r = aircraft.epnl_from_pnlt(pnlt) with r.epnl, r.pnltm and r.band_limits.
  • freqs, values = building.improvement_octave_bands(dl, f) and result.octave_bands() become s.frequencies and s.values.

A verifier's band row is read by band["frequency"], and the between-nominals sweep by between_nominals["worst_frequency"]; band["freq"] and ["worst_freq"] raise KeyError.

The tolerance order is a silent break: upper, lower = vibration.weighting_tolerance_percent(name, f) still runs and swaps the two arrays, so every unpacking of it and of the three constants has to be read and turned around. A record built by hand needs every required field, CeilingAttenuationResult no longer takes rounded=, and WeightingFilter(..., high_accuracy=None) raises TypeError where it used to select the default. The migration guide maps each of these, in English and Spanish, with a section for the records, one for the tolerance order and one for the required fields.

How it was verified

The tolerance bands and the sign of the DIN 45669-1 lower limit were read on the printed Table 2 and the 5.2.3.3 condition above it (DIN 45669-1:2010-09, PDF page 19, printed p. 19), with the working range of 5.2.3.1 on the page before. The conformance rows still compare the magnitude Table 2 prints, and docs/CONFORMANCE.md is byte-identical. The legend symbols of the octave spectrum follow the prints: ΔL_oct of ISO 10140-1:2021 Formula (H.2), L_Ioct of Formula (K.3), ΔR_oct of ISO 717-1:2020 Formula (D.1), and the plain R_s and L_Inorm where no octave symbol is printed (ISO 10140-1:2021 Figure J.9, PDF page 53, printed p. 47, and Formula (K.5), PDF page 58, printed p. 52). The bandsharing adjustment is read on ICAO Annex 16, Volume I, Eighth Edition, Appendix 2, 4.4.2 (PDF page 158, printed p. APP 2-20) and the Nomenclature entry for ΔB (PDF page 27, printed p. I-7), and the TPNdB of PNLT and PNLTM on the Nomenclature page before it (PDF page 26, printed p. I-6); a new test runs effective_perceived_noise_level on a flyover whose tone correction is suppressed at PNLTM and checks the adjustment against C_avg - C(k_M) computed from the result's own tone corrections, and it fails if the adjustment is dropped from EPNLResult.

The full test suite passes on this branch (28943 passed, 69 skipped), and so do the 7560 documentation code blocks over 732 pages, the site build with its type check and HTML validation, the 1893 conformance checks with docs/CONFORMANCE.md unchanged, the 77 example fiches, the API reference check, mypy over src and scripts, ruff, bandit and the repository's scripts/check_*.py guards. In the new spectrogram figure the 250 Hz and 4 kHz tones of the example sit on their own bands, in English, in Spanish and on the dark page, and a content test pins where each band row is drawn. The EPNL figure and the EPNL fiche were redrawn with the TPNdB labels and read in English, in Spanish and on the dark page, and content tests pin the labels of the plot in both languages and the units of the notebook table.

The guards

The spelling guard of tests/test_public_vocabulary.py reads the public attributes a plain class writes on self, where the filter bank's five abbreviated attributes had stayed out of sight of every field and parameter check, and refuses freq and freqs inside any public name. CONTRIBUTING says so in its Words row. Red on the base:

E       AssertionError: phonometry.filters.core.OctaveFilterBank.freq: 'freq' is spelled 'frequency (one) or frequencies (an array)' everywhere else
E       AssertionError: phonometry.filters.core.OctaveFilterBank.freq: 'freq' is spelled 'frequency'
E         phonometry.filters.core.OctaveFilterBank.freq_d: 'freq' is spelled 'frequency'
E         phonometry.filters.core.OctaveFilterBank.freq_u: 'freq' is spelled 'frequency'
E         phonometry.filters.core.OctaveFilterBank.nominal_freq: 'freq' is spelled 'frequency'
E         phonometry.filters.core.OctaveFilterBank.num_bands: a count is n_<plural>, as in n_points
2 failed, 1 passed, 44 deselected

tests/test_required_fields.py replaces each required field of each of these records with None through dataclasses.replace and expects a TypeError naming the record and the field, and checks that r_prime and l_n stay optional. Before the records refused None by name, 29 of its 31 cases failed:

FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[airborne_insulation-d]
FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[airborne_insulation-l1]
FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[impact_insulation-li]
FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[extended_rating-measured]
FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[slit_aperture-depth]
FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[facade-elements]
FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[intensity-spacing_m]
FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[barrier-source_height_m]
FAILED tests/test_required_fields.py::test_a_required_field_refuses_none[zwicker_stationary-field]
29 failed, 2 passed

tests/test_public_vocabulary.py also reads the row keys of a verdict of each of the three verifiers that return per-band rows, which no signature or field list shows, and holds them to the same words. Red on the base:

E       AssertionError: FilterComplianceResult row key 'freq': 'freq' is spelled 'frequency'
E         WeightingComplianceResult row key 'freq': 'freq' is spelled 'frequency'
E         WeightingComplianceResult row key 'worst_freq': 'freq' is spelled 'frequency'
E         IntensityInstrumentComplianceResult row key 'freq': 'freq' is spelled 'frequency'
1 failed, 93 deselected

One key is exempt, with its reason in the guard: summation_max_db of FilterComplianceResult, the upper end of the range of the summation of output signals of IEC 61260-1 5.16 beside summation_min_db, a bound of a deviation and not the maximum level the max-level rule is about.

Green on this branch: 31 passed for the required fields and the whole vocabulary guard, 94 tests, with the rest of the suite.

Left for later, outside these records: a sweep of the remaining tuple-returning functions across the library; the geometry fields of open_plan, metadiffuser, junction_transmission, panel_transmission, road_absorption and the noise-control geometry records, which still default to None so that a hand-built result can skip them; a name for the two summation keys of FilterComplianceResult that says what they bound; and the unit of the bandsharing adjustment, which the Annex 16 Nomenclature also prints in TPNdB and the records still state in dB.

@sourcery-ai

sourcery-ai Bot commented Oct 17, 2026

Copy link
Copy Markdown

Sorry @jmrplens, your pull request is larger than the review limit of 150,000 diff characters

@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 221 files, which is 121 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration
  • Configuration used: Repository: jmrplens/phonometry/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4e2a5b5d-ec80-4f30-ab75-bd79094d489b
📥 Commits

Reviewing files that changed from the base of the PR and between b2cc946 and 075ac5e.

⛔ Files ignored due to path filters: 10
  • .github/images/epnl.svg is excluded by !**/*.svg
  • .github/images/epnl_dark.svg is excluded by !**/*.svg
  • .github/images/epnl_es.svg is excluded by !**/*.svg
  • .github/images/epnl_es_dark.svg is excluded by !**/*.svg
  • .github/images/rainfall_octave_bands.svg is excluded by !**/*.svg
  • .github/images/rainfall_octave_bands_dark.svg is excluded by !**/*.svg
  • .github/images/rainfall_octave_bands_es.svg is excluded by !**/*.svg
  • .github/images/rainfall_octave_bands_es_dark.svg is excluded by !**/*.svg
  • .github/reports/icao_epnl_example.pdf is excluded by !**/*.pdf
  • assets.lock is excluded by !**/*.lock
📒 Files selected for processing: 221
  • .github/images/spectrogram_example.webp
  • .github/images/spectrogram_example_dark.webp
  • .github/images/spectrogram_example_es.webp
  • .github/images/spectrogram_example_es_dark.webp
  • .github/reports/icao_epnl_example.webp
  • CHANGELOG.md
  • CONTRIBUTING.md
  • README_PYPI.md
  • docs/ERRATA.es.md
  • docs/ERRATA.md
  • docs/aircraft/aircraft-noise.md
  • docs/buildings/design/impact-improvement.md
  • docs/buildings/insulation/lab-application-rules.md
  • docs/devices/noise-control/enclosure-cabin-insulation.md
  • docs/devices/noise-control/in-situ-noise-control.md
  • docs/environment/sources/rolling-stock-noise.md
  • docs/reference/api/index.md
  • docs/reference/glossary.md
  • docs/reference/theory/signal-analysis.md
  • docs/signals/filters/filter-banks.md
  • docs/signals/filters/filter-compliance.md
  • docs/signals/filters/filter-gallery.md
  • docs/signals/filters/multichannel.md
  • docs/signals/levels/levels.md
  • docs/signals/levels/weighting.md
  • docs/start/upgrading.md
  • docs/vibration/human/meter-verification.md
  • llms-full.txt
  • llms.txt
  • scripts/animation_fingerprints.txt
  • scripts/check_figure_language.py
  • scripts/conformance/domains/aircraft.py
  • scripts/conformance/domains/enclosure_cabin_insulation.py
  • scripts/conformance/domains/filters.py
  • scripts/conformance/domains/in_situ_measurement.py
  • scripts/conformance/domains/meter_verification.py
  • scripts/conformance/domains/rolling_stock_noise.py
  • scripts/conformance/domains/vibration_immission.py
  • scripts/conformance/domains/vibration_railway.py
  • scripts/conformance/shared.py
  • scripts/figures/aircraft.py
  • scripts/figures/building_lab_rules.py
  • scripts/figures/i18n.py
  • scripts/figures/registry.py
  • scripts/figures/schematics.py
  • scripts/figures/signals.py
  • scripts/figures/vibration.py
  • scripts/generate_graphs.py
  • scripts/generate_llms.py
  • site/public/llms/llms-aircraft.txt
  • site/public/llms/llms-buildings-design.txt
  • site/public/llms/llms-buildings-insulation-laboratory.txt
  • site/public/llms/llms-devices-noise-control-measured.txt
  • site/public/llms/llms-environment-sources.txt
  • site/public/llms/llms-glossary.txt
  • site/public/llms/llms-signals-filters.txt
  • site/public/llms/llms-signals-levels.txt
  • site/public/llms/llms-start.txt
  • site/public/llms/llms-theory.txt
  • site/public/llms/llms-upgrading.txt
  • site/public/llms/llms-vibration-human.txt
  • site/src/content/docs/aircraft/aircraft-noise.mdx
  • site/src/content/docs/buildings/design/impact-improvement.mdx
  • site/src/content/docs/buildings/insulation/lab-application-rules.mdx
  • site/src/content/docs/devices/noise-control/enclosure-cabin-insulation.mdx
  • site/src/content/docs/devices/noise-control/in-situ-noise-control.mdx
  • site/src/content/docs/environment/sources/rolling-stock-noise.mdx
  • site/src/content/docs/es/aircraft/aircraft-noise.mdx
  • site/src/content/docs/es/buildings/design/impact-improvement.mdx
  • site/src/content/docs/es/buildings/insulation/lab-application-rules.mdx
  • site/src/content/docs/es/devices/noise-control/enclosure-cabin-insulation.mdx
  • site/src/content/docs/es/devices/noise-control/in-situ-noise-control.mdx
  • site/src/content/docs/es/environment/sources/rolling-stock-noise.mdx
  • site/src/content/docs/es/reference/errata.md
  • site/src/content/docs/es/reference/theory/signal-analysis.mdx
  • site/src/content/docs/es/signals/filters/block-processing.mdx
  • site/src/content/docs/es/signals/filters/filter-banks.mdx
  • site/src/content/docs/es/signals/filters/filter-compliance.mdx
  • site/src/content/docs/es/signals/filters/filter-gallery.mdx
  • site/src/content/docs/es/signals/filters/multichannel.mdx
  • site/src/content/docs/es/signals/levels/levels.mdx
  • site/src/content/docs/es/signals/levels/weighting.mdx
  • site/src/content/docs/es/signals/metrology/compliance-verification.mdx
  • site/src/content/docs/es/start/upgrading.mdx
  • site/src/content/docs/es/vibration/human/meter-verification.mdx
  • site/src/content/docs/reference/api/aeroacoustics/certification.md
  • site/src/content/docs/reference/api/building/aperture-transmission.md
  • site/src/content/docs/reference/api/building/ceiling-plenum.md
  • site/src/content/docs/reference/api/building/facade.md
  • site/src/content/docs/reference/api/building/floor-covering-improvement.md
  • site/src/content/docs/reference/api/building/insulation.md
  • site/src/content/docs/reference/api/building/joint-insulation.md
  • site/src/content/docs/reference/api/building/laboratory-improvement.md
  • site/src/content/docs/reference/api/building/rainfall-sound.md
  • site/src/content/docs/reference/api/building/ratings.md
  • site/src/content/docs/reference/api/environment/barrier-in-situ.md
  • site/src/content/docs/reference/api/environment/ground-barriers.md
  • site/src/content/docs/reference/api/filters/compliance.md
  • site/src/content/docs/reference/api/filters/core.md
  • site/src/content/docs/reference/api/filters/frequencies.md
  • site/src/content/docs/reference/api/filters/weighting-compliance.md
  • site/src/content/docs/reference/api/filters/weighting.md
  • site/src/content/docs/reference/api/noise_control/cabin-insulation.md
  • site/src/content/docs/reference/api/noise_control/enclosure-insulation.md
  • site/src/content/docs/reference/api/noise_control/screen-in-situ.md
  • site/src/content/docs/reference/api/power/intensity-compliance.md
  • site/src/content/docs/reference/api/power/intensity.md
  • site/src/content/docs/reference/api/psychoacoustics/zwicker.md
  • site/src/content/docs/reference/api/vibration/instrumentation.md
  • site/src/content/docs/reference/api/vibration/vibration-meter.md
  • site/src/content/docs/reference/errata.md
  • site/src/content/docs/reference/theory/signal-analysis.mdx
  • site/src/content/docs/signals/filters/block-processing.mdx
  • site/src/content/docs/signals/filters/filter-banks.mdx
  • site/src/content/docs/signals/filters/filter-compliance.mdx
  • site/src/content/docs/signals/filters/filter-gallery.mdx
  • site/src/content/docs/signals/filters/multichannel.mdx
  • site/src/content/docs/signals/levels/levels.mdx
  • site/src/content/docs/signals/levels/weighting.mdx
  • site/src/content/docs/signals/metrology/compliance-verification.mdx
  • site/src/content/docs/start/upgrading.mdx
  • site/src/content/docs/vibration/human/meter-verification.mdx
  • site/src/data/glossary.mjs
  • src/phonometry/_internal/validation.py
  • src/phonometry/_plot/aircraft.py
  • src/phonometry/_plot/building.py
  • src/phonometry/_plot/common.py
  • src/phonometry/_plot/filters.py
  • src/phonometry/_plot/geometry/building.py
  • src/phonometry/_plot/geometry/emission.py
  • src/phonometry/_plot/geometry/environment.py
  • src/phonometry/_plot/joint_insulation.py
  • src/phonometry/_plot/vibration.py
  • src/phonometry/_report/_i18n.py
  • src/phonometry/_report/_insulation_fiche.py
  • src/phonometry/_report/annex16_epnl.py
  • src/phonometry/_report/iec61043.py
  • src/phonometry/_report/iec61260.py
  • src/phonometry/_report/iso532.py
  • src/phonometry/_report/iso717.py
  • src/phonometry/aircraft/__init__.py
  • src/phonometry/aircraft/certification.py
  • src/phonometry/aircraft/rotorcraft_noise.py
  • src/phonometry/building/__init__.py
  • src/phonometry/building/measurement/__init__.py
  • src/phonometry/building/measurement/_rainfall_sound.py
  • src/phonometry/building/measurement/floor_covering_improvement.py
  • src/phonometry/building/measurement/insulation.py
  • src/phonometry/building/measurement/joint_insulation.py
  • src/phonometry/building/measurement/laboratory_improvement.py
  • src/phonometry/building/measurement/ratings.py
  • src/phonometry/building/prediction/aperture_transmission.py
  • src/phonometry/building/prediction/ceiling_plenum.py
  • src/phonometry/building/prediction/facade.py
  • src/phonometry/emission/intensity.py
  • src/phonometry/emission/intensity_compliance.py
  • src/phonometry/environment/propagation/barrier_in_situ.py
  • src/phonometry/environment/propagation/ground_barriers.py
  • src/phonometry/environment/sources/acoustic_roughness.py
  • src/phonometry/filters/__init__.py
  • src/phonometry/filters/compliance.py
  • src/phonometry/filters/core.py
  • src/phonometry/filters/frequencies.py
  • src/phonometry/filters/time_invariance.py
  • src/phonometry/filters/weighting.py
  • src/phonometry/filters/weighting_compliance.py
  • src/phonometry/noise_control/_cabin_insulation.py
  • src/phonometry/noise_control/enclosure_insulation.py
  • src/phonometry/noise_control/screen_in_situ.py
  • src/phonometry/psychoacoustics/loudness/zwicker.py
  • src/phonometry/speech/sti.py
  • src/phonometry/underwater/sources/pile_driving_noise.py
  • src/phonometry/vibration/human/instrumentation.py
  • src/phonometry/vibration/immission/railway.py
  • src/phonometry/vibration/immission/vibration_meter.py
  • tests/aircraft/test_certification.py
  • tests/building/measurement/test_floor_covering_improvement.py
  • tests/building/measurement/test_intensity_insulation.py
  • tests/building/measurement/test_iso10140_report.py
  • tests/building/measurement/test_iso15186_element_report.py
  • tests/building/measurement/test_iso15186_report.py
  • tests/building/measurement/test_iso16283_report.py
  • tests/building/measurement/test_iso717_report.py
  • tests/building/measurement/test_joint_insulation.py
  • tests/building/measurement/test_laboratory_improvement.py
  • tests/building/measurement/test_rainfall_sound.py
  • tests/building/prediction/test_ceiling_plenum.py
  • tests/building/test_building_result_plots.py
  • tests/emission/test_intensity.py
  • tests/environment/propagation/test_ground_barriers.py
  • tests/environment/sources/test_roughness_method_b.py
  • tests/environment/test_barrier_in_situ.py
  • tests/filters/test_compliance.py
  • tests/filters/test_design.py
  • tests/filters/test_filter_class_1995.py
  • tests/filters/test_filter_class_aliasing.py
  • tests/filters/test_iec61260_report.py
  • tests/filters/test_iec651_type0_weighting.py
  • tests/filters/test_nominal_frequencies.py
  • tests/filters/test_parametric_filters.py
  • tests/filters/test_pattern_evaluation.py
  • tests/filters/test_signal_overloads.py
  • tests/filters/test_spectrogram.py
  • tests/filters/test_time_invariance.py
  • tests/filters/test_weighting_class_verifier.py
  • tests/filters/test_zero_phase.py
  • tests/noise_control/test_cabin_insulation.py
  • tests/noise_control/test_enclosure_insulation.py
  • tests/noise_control/test_iso11546_1_oracles.py
  • tests/noise_control/test_screen_in_situ.py
  • tests/result_factories.py
  • tests/test_boundary_verdicts.py
  • tests/test_device_geometry_plots.py
  • tests/test_errors_and_edge_cases.py
  • tests/test_owns_arrays.py
  • tests/test_plot_twin_legend.py
  • tests/test_public_vocabulary.py
  • tests/test_required_fields.py
  • tests/vibration/human/test_instrumentation.py
  • tests/vibration/immission/test_vibration_meter.py
  • tests/vibration/immission/test_vibration_meter_plot.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jmrplens
jmrplens added this pull request to stack #984 October 17, 2026 17:11
@jmrplens jmrplens changed the title fix/records instead of tuples Results that were tuples are named records, tolerance limits come lower first, and a record's required fields refuse to be left empty Oct 17, 2026
@jmrplens
jmrplens force-pushed the fix/records-instead-of-tuples branch from b066ab3 to 0c39c61 Compare October 17, 2026 17:12
@github-actions github-actions Bot added documentation Improvements or additions to documentation conformance Standard clause coverage, reference values or errata errata Confirmed defect in a published standard, tracked in docs/ERRATA.md api Public API surface, naming and deprecations figures Generated plots, diagrams and animations reports Accredited-format .report() fiches and their rendering site Documentation website i18n English and Spanish translations area: aircraft Aircraft and rotorcraft noise area: building Sound insulation and building acoustics area: emission Sound power and source emission area: environment Outdoor propagation, environmental sources and noise assessment area: noise control Silencers, barriers and noise control treatments area: psychoacoustics Loudness, sharpness, roughness and annoyance area: underwater Underwater acoustics and propagation area: vibration Human vibration and structure-borne sound area: core Shared internals and cross-cutting code every domain depends on area: filters Octave filter banks, weightings and instrument class verification area: speech Speech intelligibility: STI, SII and STOI labels Oct 17, 2026
@codecov

codecov Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.11286% with 11 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (fix/verdicts-spell-passes-and-refuse-truth@b2cc946). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/phonometry/_plot/filters.py 90.62% 6 Missing ⚠️
src/phonometry/_plot/common.py 78.57% 3 Missing ⚠️
src/phonometry/filters/frequencies.py 95.34% 2 Missing ⚠️
Additional details and impacted files
@@                              Coverage Diff                              @@
##             fix/verdicts-spell-passes-and-refuse-truth     #978   +/-   ##
=============================================================================
  Coverage                                              ?   96.91%           
=============================================================================
  Files                                                 ?      445           
  Lines                                                 ?    90579           
  Branches                                              ?        0           
=============================================================================
  Hits                                                  ?    87782           
  Misses                                                ?     2797           
  Partials                                              ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Numerical conformance

All 1893 conformance checks pass, across 111 domains and 523 standards

1893/1893 checks pass across 111 domains and 523 standards (227 normative designations, 125 further published sources).

Used in the tables below is how much of that clause's published tolerance the deviation consumes: 100 % sits exactly on the limit, 5 % uses a twentieth of the allowance, and a dash means the clause states no two-sided tolerance for the quantity, so there is no budget to spend. It is reported and never used to decide a verdict, which is settled at full precision before any rounding.

Renamed (4)

Standard Base quantity Head quantity
ISO 8297:1994 Table 2 Background correction at differences of 6 to 10 dB and at 12 dB, read through plant_background_correction_db Background correction at differences of 6 to 10 dB and at 12 dB, read through plant_background_correction
Wenz wind noise (rule of fives) Wind spectrum level at 1 kHz, 5 kn (canonical anchor), dB re 1 µPa²/Hz Wind spectrum level at 1 kHz, 5 kt (canonical anchor), dB re 1 µPa²/Hz
JOMOPANS-ECHO ship source level Bulker V=13.5 kn L=211 m band level at 1 kHz (File S1 oracle), dB re 1 µPa m Bulker V=13.5 kt L=211 m band level at 1 kHz (File S1 oracle), dB re 1 µPa m
ISO 10847:1997 6.3.1 The short-distance ratio is strict at 0,1, and the after case needs both of its two inequalities The short-distance ratio is strict at 0,1, the after case needs both of its two inequalities, and a geometry past 0,1 on every ratio is short

Closest to their published limit (top 5)

The rows with the least room left, so the ones a change is most likely to push over.

Standard Quantity Deviation Used
ISO/TR 17534-3:2015 Table 3 Ground-projected path length dp, m 0.005 m 100 %
DIN 4150-2:1999-06 Annex C, Example 5 KB_FTr with hammer b) in the rest hours, Formula (5) -0.005 100 %
DIN 4150-2:1999-06 Annex C, Example 8 KB_FTm over the record with the passage maxima alone -0.0005 100 %
E DIN 4150-2:2023-08 Annex B, Table B.1 KB_FTm,Zug of the metro north by Formula (5) -0.0005 100 %
Jarvis (1996) NPL CIRA(EXT) 010 Appendix B, folio 26 Volume of the coupler of the example, v = pi r^2 L -0.00000000005 m³ 100 %

Pass Tests & coverage: 261108 tests, 0 failures (all green)
Python Version Tests Failures Coverage Status
macos-latest-3.12 29012 0 96.9% Pass Passed
macos-latest-3.13 29012 0 96.9% Pass Passed
macos-latest-3.14 29012 0 96.9% Pass Passed
ubuntu-latest-3.12 29012 0 96.9% Pass Passed
ubuntu-latest-3.13 29012 0 96.9% Pass Passed
ubuntu-latest-3.14 29012 0 96.9% Pass Passed
windows-latest-3.12 29012 0 96.9% Pass Passed
windows-latest-3.13 29012 0 96.9% Pass Passed
windows-latest-3.14 29012 0 96.9% Pass Passed

Full report at this commit: docs/CONFORMANCE.md · docs/conformance.json · full CI artifacts

…er first, and a record's required fields refuse to be left empty

Four answers that came back as a tuple to be unpacked by position are records with named fields now. `OctaveFilterBank.spectrogram` returns a `filters.OctaveSpectrogramResult` with `levels`, a read-only `frequencies` and `times`; it checks the level grid against both axes and draws itself with `.plot()`, one raster over time and the logarithmic band centre with a dB colour bar, and a multichannel result asks for `channel=`. `filters.nominal_frequencies` returns a `filters.FractionalOctaveBands` with read-only `frequencies`, `lower_edges` and `upper_edges` and the IEC 61260-1 nominal `labels` as a tuple of text; the filter bank reads its band set from the same record, as `bank.frequencies`, `bank.lower_edges`, `bank.upper_edges`, `bank.labels` and `bank.n_bands`, all read-only. `building.improvement_octave_bands` and the `octave_bands()` methods of the floor-covering, laboratory lining, laboratory floor-covering, joint and rainfall results return a `building.OctaveBandSpectrum` with `frequencies`, `values` in dB and the `quantity` they hold, which plots itself in English or Spanish under the symbol its source prints. `aircraft.epnl_from_pnlt` returns an `aircraft.EPNLIntegration` with `epnl`, `pnltm`, `bandsharing_adjustment`, `band_limits` and the derived `duration_correction`, and `effective_perceived_noise_level` builds its `EPNLResult` from it.
@jmrplens
jmrplens force-pushed the fix/records-instead-of-tuples branch from 0c39c61 to 075ac5e Compare October 20, 2026 01:45
@greptile-apps

greptile-apps Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] Refactors result types from tuples to named records across multiple domains.

The PR appears safe to merge, with non-blocking fixes needed for single-band plotting and missing octave-spectrum columns.

Findings

  1. P2 One band looks too wide ▶
  2. P2 Incomplete records still construct ▶

Reviews (1) · Last reviewed commit: "Results that were tuples are named recor..." · Reviewed by Greptile

Comment on lines +1187 to +1188
else:
half_step = math.sqrt(2.0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 One band looks too wide

For OctaveFilterBank(48000, fraction=3, limits=[990, 1010]), the 1000 Hz band has edges around 891–1122 Hz. Its spectrogram instead spans 707–1414 Hz because this branch always uses sqrt(2). That shows colour outside the measured band. Keep the bank’s edges or band fraction in the result and use them here.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +590 to +592
require_choice(self.quantity, "quantity", _OCTAVE_BAND_QUANTITIES)
require_ranks(self, frequencies=1, values=1)
require_same_length(self, "frequencies", "values")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Incomplete records still construct

OctaveBandSpectrum accepts None for its required columns because both guards skip it and OwnsArrays leaves it unchanged. For example, dataclasses.replace(spectrum, frequencies=None) succeeds, but .plot() then fails when _band_axis tries to iterate over None. Call require_present(self, "frequencies", "values") before these guards and cover both fields in the required-field tests.

@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Public API surface, naming and deprecations area: aircraft Aircraft and rotorcraft noise area: building Sound insulation and building acoustics area: core Shared internals and cross-cutting code every domain depends on area: emission Sound power and source emission area: environment Outdoor propagation, environmental sources and noise assessment area: filters Octave filter banks, weightings and instrument class verification area: noise control Silencers, barriers and noise control treatments area: psychoacoustics Loudness, sharpness, roughness and annoyance area: speech Speech intelligibility: STI, SII and STOI area: underwater Underwater acoustics and propagation area: vibration Human vibration and structure-borne sound conformance Standard clause coverage, reference values or errata documentation Improvements or additions to documentation errata Confirmed defect in a published standard, tracked in docs/ERRATA.md figures Generated plots, diagrams and animations i18n English and Spanish translations reports Accredited-format .report() fiches and their rendering site Documentation website

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant