A hearing protector's measured attenuation comes with its uncertainty and significance test, and an active noise reduction earmuff with its total attenuation (#866)
* A hearing protector's measured attenuation comes with its uncertainty and a test of whether two measurements differ
ISO 4869-1:2018 is where the attenuation grid of ISO 4869-2 comes from, and
none of it was implemented. hearing.real_ear_attenuation takes the individual
attenuations, or the open and occluded thresholds they are the difference of,
and returns per test signal the mean, the standard deviation, u = s/sqrt(N) and
U95 = 2u of Annex A; its grid goes into assumed_protection_value, hml_rating
and snr_rating unchanged, and .plot() draws the mean downwards on the IEC 60263
grid Clause 6 l) asks for.
hearing.assess_attenuation_difference applies the Annex B test band by band,
hearing.minimum_significant_difference gives its sqrt(2) U95 form, and the
typical budgets of Tables A.2 and B.2 are published as their three components,
with the combined and expanded values derived. hearing.check_reat_sound_field
judges the test room against 4.2.2 and Table 1.
Every derived cell of Tables A.2, A.3, B.1 and B.2 and the four minimum
differences of B.1.1 and B.2 are conformance rows. B.1.1 and B.2 compute those
differences from the rounded U95 their tables print and write that input out,
so they are a stated convention, not a misprint; the unrounded earplug values
are 3.21 dB and 9.37 dB, and the module and the guide say so.
* An active noise reduction earmuff's total attenuation, its uncertainty and where it stops being linear
ISO 4869-6:2019 was not implemented. hearing.active_insertion_loss takes the
MIRE levels at both ears with the circuit off and on, or the insertion loss
directly, keeps the ear with the lower value in each band as 5.5 b) asks, and
returns the mean, the standard deviation, u = s/4 and U95 = 2u of Annex A. The
typical budget of Table A.2 is hearing.ANR_WITHIN_LABORATORY_UNCERTAINTY, an
instance of the ISO 4869-1 budget type.
hearing.anr_total_attenuation runs the chain of 5.5: the ISO 4869-1 attenuation
interpolated into one-third octaves linearly in hertz, as the calculation
workbook ISO publishes with the standard does it, the lower-ear insertion loss
added, Formula (1) back to octave bands, and the ISO 4869-2 APV, HML and SNR at
84 %. hearing.assess_anr_linearity finds the highest external level up to which
every ear follows the 5 dB steps of 5.4.4 within 1 dB. Each result has .plot().
The mean and standard deviation of Table A.3 and every stored step of the
workbook are conformance rows; the workbook rounds each step to 0.1 dB and the
library does not, so its octave totals agree to within that rounding. Table
A.3 forms its u and U95 rows from the rounded row above each, which puts one u
cell and six of its eight U95 cells a tenth above the values A.1 and A.2 define;
the library returns the defined values, the table's own arithmetic is a
separate conformance row, and the defect is registered in the errata.
* The active insertion loss reads its three inputs through one helper each
active_insertion_loss splits into a helper for an insertion loss given
directly, one for the loss formed from the passive and active levels, and one
for the band frequencies, so each form is read in one place. The APV84 and
5 dB step labels of the hearing plots are named once. No result changes.
* The active noise reduction section states the scope of ISO 4869-6
Its methods are meant for steady noise exposures and do not apply to noise
with impulsive components (Clause 1); the guide now says so in English, in
Spanish and in the docs mirror.
A hearing protector's measured attenuation comes with its uncertainty and significance test, and an active noise reduction earmuff with its total attenuation (#866)
* A hearing protector's measured attenuation comes with its uncertainty and a test of whether two measurements differ
ISO 4869-1:2018 is where the attenuation grid of ISO 4869-2 comes from, and
none of it was implemented. hearing.real_ear_attenuation takes the individual
attenuations, or the open and occluded thresholds they are the difference of,
and returns per test signal the mean, the standard deviation, u = s/sqrt(N) and
U95 = 2u of Annex A; its grid goes into assumed_protection_value, hml_rating
and snr_rating unchanged, and .plot() draws the mean downwards on the IEC 60263
grid Clause 6 l) asks for.
hearing.assess_attenuation_difference applies the Annex B test band by band,
hearing.minimum_significant_difference gives its sqrt(2) U95 form, and the
typical budgets of Tables A.2 and B.2 are published as their three components,
with the combined and expanded values derived. hearing.check_reat_sound_field
judges the test room against 4.2.2 and Table 1.
Every derived cell of Tables A.2, A.3, B.1 and B.2 and the four minimum
differences of B.1.1 and B.2 are conformance rows. B.1.1 and B.2 compute those
differences from the rounded U95 their tables print and write that input out,
so they are a stated convention, not a misprint; the unrounded earplug values
are 3.21 dB and 9.37 dB, and the module and the guide say so.
* An active noise reduction earmuff's total attenuation, its uncertainty and where it stops being linear
ISO 4869-6:2019 was not implemented. hearing.active_insertion_loss takes the
MIRE levels at both ears with the circuit off and on, or the insertion loss
directly, keeps the ear with the lower value in each band as 5.5 b) asks, and
returns the mean, the standard deviation, u = s/4 and U95 = 2u of Annex A. The
typical budget of Table A.2 is hearing.ANR_WITHIN_LABORATORY_UNCERTAINTY, an
instance of the ISO 4869-1 budget type.
hearing.anr_total_attenuation runs the chain of 5.5: the ISO 4869-1 attenuation
interpolated into one-third octaves linearly in hertz, as the calculation
workbook ISO publishes with the standard does it, the lower-ear insertion loss
added, Formula (1) back to octave bands, and the ISO 4869-2 APV, HML and SNR at
84 %. hearing.assess_anr_linearity finds the highest external level up to which
every ear follows the 5 dB steps of 5.4.4 within 1 dB. Each result has .plot().
The mean and standard deviation of Table A.3 and every stored step of the
workbook are conformance rows; the workbook rounds each step to 0.1 dB and the
library does not, so its octave totals agree to within that rounding. Table
A.3 forms its u and U95 rows from the rounded row above each, which puts one u
cell and six of its eight U95 cells a tenth above the values A.1 and A.2 define;
the library returns the defined values, the table's own arithmetic is a
separate conformance row, and the defect is registered in the errata.
* The active insertion loss reads its three inputs through one helper each
active_insertion_loss splits into a helper for an insertion loss given
directly, one for the loss formed from the passive and active levels, and one
for the band frequencies, so each form is read in one place. The APV84 and
5 dB step labels of the hearing plots are named once. No result changes.
* The active noise reduction section states the scope of ISO 4869-6
Its methods are meant for steady noise exposures and do not apply to noise
with impulsive components (Clause 1); the guide now says so in English, in
Spanish and in the docs mirror.
Estimate what a hearing protector leaves at the ear (ISO 4869-2) (#676)
* Estimate what a hearing protector leaves at the ear (ISO 4869-2)
A protector is measured on people rather than on a coupler, so ISO 4869-1
returns a distribution: one attenuation per subject per octave band, with a
spread often a third of the mean. ISO 4869-2 turns that into a number someone
can act on, and Clause 5 refuses to use the mean.
Adds assumed_protection_value (Formula (1), with all seven protection
performances of Table 1) and the three methods built on it:
octave_band_protected_level (Clause 6), hml_rating with hml_protected_level
(Clause 7) and snr_rating with snr_protected_level (Clause 8).
The two rating methods consume their ratings as the standard publishes them,
rounded to the nearest integer, and the reported levels round halves away from
zero rather than to even.
Every printed number of the worked example that runs through Annexes A to D is
reproduced: the per-band mean and spread, the band table and 81 dB, all sixteen
HML triples with their statistics and the 82 dB, and all sixteen single-number
ratings with both applications.
One erratum. Annex C reprints the normative Table 2 as its Table C.1 and the
reprint disagrees in two cells; Table 2 is the reading that reproduces the
annex's own results, and the suite computes the same row from the reprint to
show it missing thirteen of the sixteen printed values.
* List the new guide in the index, and narrow without asserting
The guides index carries its own count, in figures and in words and in two
languages, so a new page has to be entered in four places. It is 112 now.
Bandit refuses assert in src (B101), and the two that narrowed the
optional levels for mypy were there only to say what the pairing check
above them had already decided. Folding the check into the branch that
uses it removes them: the elif narrows, mypy is satisfied, and passing a
C-weighted level together with half of the other pairing is now refused
rather than silently ignoring one of the two.
* Declare the new guide in its sidebar topic
Starlight's topic plugin refuses to render a page it cannot place, so a
guide is entered twice: once in the guides index, which the count gate
watches, and once in site/src/data/topics.mjs, which the build does. The
first was done and the second was not, and the build says so page by page.
* Answer the review: the band axis, the weighting and what PNR means
Three of the seven were mine to fix in the code.
octave_band_protected_level matched only the number of bands, so a result
computed over one axis could be applied to a noise measured over another,
and a band set that is not the standard octaves silently received the
63 Hz to 8 kHz weighting. The axis a result carries is now compared with
the one in play, and the default weighting is keyed to the frequencies
rather than to how many there are.
A weighting holding nan or an infinity now raises rather than returning a
level that is not a level.
The SNR method given only a C-weighted level never learns LpA, so it has
no predicted noise level reduction to report: what it was reporting was
the rating back again, 21 dB where the reduction is 22 dB. The field is
None on that path and carries the real PNR on the other.
The prose said all three methods begin at 125 Hz, which is only true of
two: the octave-band method starts at 63 Hz when both inputs have it
(Clause 6). Corrected in the docstring and the three editions, with the
clause numbers for HML and SNR added.
Both ISO catalogue links were wrong. ISO 4869-2:2018 is 65582 and
ISO 4869-1:2018 is 65581; 70090 and 69233 are other standards entirely.
* Cover the four figures, which nothing was exercising
Sonar put coverage on new code at 68,8 %, and the hole was the whole of
the plotting: four renderers and four .plot() methods with no test behind
them. Thirteen content assertions now hold what each figure draws, plus
the four kwarg-forwarding cases of the generic contract.
That contract found a real defect on its first run: two renderers set
their default line width as 'lw' while a caller passing 'linewidth', which
is what the contract does, made matplotlib refuse both as aliases of one
another. They use the same spelling now.
* Exercise the refusals too, and close the module
Six paths had no test on them: the two band-count defaults that give up
rather than guess an axis, the mismatched frequency and weighting counts,
the seven-band grid read as starting at 125 Hz, and a non-finite level
reaching either application.
Both new modules are at every statement now, hearing_protectors.py and
the four renderers in _plot/hearing.py, which is the half Sonar was
counting against the gate.
* Name the two labels the module was repeating
Sonar found both, and one of them was hiding something worse. The HML
curve took its legend label by formatting the title and splitting it on
the em dash, which is clever and breaks the moment a translation
punctuates differently. It has its own string now, with its own Spanish
twin, which also says what the curve is rather than a fragment of what
the figure is.
The other is the spread band's label, which appeared as key, as value and
at the point of use. This module already names its repeated labels; these
two had escaped that.
* Style both HML segments alike, since they are one line
The right segment took only the colour and the width, so a caller passing
linestyle, alpha or zorder got a curve whose two halves looked different
either side of the corner. It takes everything now, except the label,
which stays on the left so the legend shows one entry for what reads as
one line.
The kwarg-forwarding contract could not have found this: it checks the
primary artist, and the second segment is not it.
Every verdict reads its pass and fail flags, grades and classes from the values it holds (#949)
A result no longer stores a verdict beside the readings it came from. Sixty-two result classes used to keep the flag, grade or class their function had worked out (`passes`, `complies`, `qualified`, the `*_met` and `*_ok` flags, the advisories, the per-band classes of the IEC 61260-1, IEC 61672-1 and IEC 61043 verdicts, the ISO 9614-2 grade, the ISO/PAS 1996-3 category, the IEC TS 61400-11-2 block status and the rest), so a result built by hand or rewritten with `dataclasses.replace` could hold readings that fail and a flag that says they pass. Each of them is now a read-only property, read from the values the result keeps and the limit the standard prints, and so is any figure that only fed it, such as the rounded level of an RD 1367/2007 period or the acceptance region of a trend test.
A hearing protector's measured attenuation comes with its uncertainty and significance test, and an active noise reduction earmuff with its total attenuation (#866)
* A hearing protector's measured attenuation comes with its uncertainty and a test of whether two measurements differ
ISO 4869-1:2018 is where the attenuation grid of ISO 4869-2 comes from, and
none of it was implemented. hearing.real_ear_attenuation takes the individual
attenuations, or the open and occluded thresholds they are the difference of,
and returns per test signal the mean, the standard deviation, u = s/sqrt(N) and
U95 = 2u of Annex A; its grid goes into assumed_protection_value, hml_rating
and snr_rating unchanged, and .plot() draws the mean downwards on the IEC 60263
grid Clause 6 l) asks for.
hearing.assess_attenuation_difference applies the Annex B test band by band,
hearing.minimum_significant_difference gives its sqrt(2) U95 form, and the
typical budgets of Tables A.2 and B.2 are published as their three components,
with the combined and expanded values derived. hearing.check_reat_sound_field
judges the test room against 4.2.2 and Table 1.
Every derived cell of Tables A.2, A.3, B.1 and B.2 and the four minimum
differences of B.1.1 and B.2 are conformance rows. B.1.1 and B.2 compute those
differences from the rounded U95 their tables print and write that input out,
so they are a stated convention, not a misprint; the unrounded earplug values
are 3.21 dB and 9.37 dB, and the module and the guide say so.
* An active noise reduction earmuff's total attenuation, its uncertainty and where it stops being linear
ISO 4869-6:2019 was not implemented. hearing.active_insertion_loss takes the
MIRE levels at both ears with the circuit off and on, or the insertion loss
directly, keeps the ear with the lower value in each band as 5.5 b) asks, and
returns the mean, the standard deviation, u = s/4 and U95 = 2u of Annex A. The
typical budget of Table A.2 is hearing.ANR_WITHIN_LABORATORY_UNCERTAINTY, an
instance of the ISO 4869-1 budget type.
hearing.anr_total_attenuation runs the chain of 5.5: the ISO 4869-1 attenuation
interpolated into one-third octaves linearly in hertz, as the calculation
workbook ISO publishes with the standard does it, the lower-ear insertion loss
added, Formula (1) back to octave bands, and the ISO 4869-2 APV, HML and SNR at
84 %. hearing.assess_anr_linearity finds the highest external level up to which
every ear follows the 5 dB steps of 5.4.4 within 1 dB. Each result has .plot().
The mean and standard deviation of Table A.3 and every stored step of the
workbook are conformance rows; the workbook rounds each step to 0.1 dB and the
library does not, so its octave totals agree to within that rounding. Table
A.3 forms its u and U95 rows from the rounded row above each, which puts one u
cell and six of its eight U95 cells a tenth above the values A.1 and A.2 define;
the library returns the defined values, the table's own arithmetic is a
separate conformance row, and the defect is registered in the errata.
* The active insertion loss reads its three inputs through one helper each
active_insertion_loss splits into a helper for an insertion loss given
directly, one for the loss formed from the passive and active levels, and one
for the band frequencies, so each form is read in one place. The APV84 and
5 dB step labels of the hearing plots are named once. No result changes.
* The active noise reduction section states the scope of ISO 4869-6
Its methods are meant for steady noise exposures and do not apply to noise
with impulsive components (Clause 1); the guide now says so in English, in
Spanish and in the docs mirror.