ehs-risk-sem
Back to ehs-risk-sem

rare_events

ExposureModel

ExposureModel(trir: 'float' = 2.3, shift_hours: 'float' = 8.0, base_hours: 'float' = 200000.0) -> None

Translate an establishment-level incidence rate into unit-level risk.

Parameters ---------- trir Total recordable incidence rate per ``base_hours`` hours. shift_hours Length of the exposure window that a score would be attached to. base_hours Denominator of the incidence rate; 200,000 for OSHA-style rates.

The class exists to make one point explicit: a risk score has no meaning until the unit of analysis and the exposure window are named. "This crew is at elevated risk" is not a claim until it says elevated over what period, relative to what denominator.

Used by: study_02_rare_events.py

alerts_per_true_event

alerts_per_true_event(sensitivity: 'float', specificity: 'float', prevalence: 'float') -> 'float'

Number of alerts raised per true event detected, ``1 / PPV``.

This is the quantity that determines whether an operational alerting system will be believed. It is reported instead of, not alongside, a bare PPV in most of this repository's output because the reciprocal is the form people can act on.

Used by: study_02_rare_events.py

events_for_relative_precision

events_for_relative_precision(rel_precision: 'float' = 0.1, z: 'float' = 1.959963985) -> 'float'

Number of events (not observations) needed for a given relative precision.

``events = z^2 / rel^2``, approximately, since ``n * p`` at small ``p``. At 10% relative precision this is about 384 events, whatever the base rate.

n_for_relative_precision

n_for_relative_precision(p: 'float', rel_precision: 'float' = 0.1, z: 'float' = 1.959963985) -> 'float'

Sample size needed to estimate a proportion to a relative precision.

``n = z^2 (1 - p) / (rel^2 * p)``

At ``p = 9.2e-5`` (one recordable per 8-hour shift at TRIR 2.3) and 10% relative precision this is roughly 4.2 million worker-shifts. Below that sample size, calibration-in-the-large cannot be estimated, let alone a calibration curve.

ppv_from_sens_spec

ppv_from_sens_spec(sensitivity: 'float', specificity: 'float', prevalence: 'float') -> 'float'

Positive predictive value from sensitivity, specificity and prevalence.

``PPV = sens * prev / (sens * prev + (1 - spec) * (1 - prev))``

probability_per_shift

probability_per_shift(trir: 'float', shift_hours: 'float' = 8.0, base_hours: 'float' = 200000.0) -> 'float'

Probability that a given worker-shift contains a recordable case.

Uses the rate directly rather than a Poisson exceedance probability, since at these rates the two agree to seven decimal places and the linear form is the one a reader can check by hand.

rate_per_hour

rate_per_hour(trir: 'float', base_hours: 'float' = 200000.0) -> 'float'

Convert an OSHA-style incidence rate to a rate per worker-hour.

``TRIR`` is cases per ``base_hours`` hours worked. At TRIR 2.3 this is 1.15e-5 per worker-hour.

rate_ratio_ci

rate_ratio_ci(events_a: 'int', exposure_a: 'float', events_b: 'int', exposure_b: 'float', z: 'float' = 1.959963985) -> 'dict'

Confidence interval for a ratio of two Poisson rates.

Included because comparing an establishment or a shift against a benchmark is the operational use of these rates, and the interval is usually wide enough at realistic event counts to make the comparison uninformative -- which is worth showing rather than asserting.

shifts_per_event

shifts_per_event(trir: 'float', shift_hours: 'float' = 8.0, base_hours: 'float' = 200000.0) -> 'float'

Expected number of worker-shifts between recordable cases.

Used by: study_02_rare_events.py

worker_shifts_for_calibration

worker_shifts_for_calibration(trir: 'float' = 2.3, shift_hours: 'float' = 8.0, rel_precision: 'float' = 0.1) -> 'dict'

Sample size needed to calibrate a shift-level risk model.

Returns both the required number of worker-shifts and the number of events those shifts are expected to contain.

Used by: study_02_rare_events.py