design_values¶
design_values ¶
Regulatory design-value calculations from POSTFILE output.
This module turns raw concentration time series (parsed via
:mod:pyaermod.postfile) into the percentile / design-value figures
that NAAQS regulatory submittals quote. Each function is annotated
with its 40 CFR Part 50 citation and the EPA design-value guidance
that prescribes the math.
All functions accept a :class:pandas.DataFrame shaped like the
data attribute of :class:pyaermod.postfile.PostfileResult,
i.e. with columns x, y, concentration, date (string
in YYMMDDHH form), ave, grp.
Background concentrations (uniform or time-varying) can be added
via :func:add_background before computing design values; per-
pollutant pairing rules are in the function docstring.
DesignValue
dataclass
¶
Result of a design-value computation at one receptor.
add_background ¶
Add a background concentration to every row of df.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
df
|
DataFrame
|
POSTFILE-shaped DataFrame. |
required |
background
|
Union[float, Series, dict]
|
Either a uniform float, a pd.Series indexed by date string
(YYMMDDHH), or a dict mapping date string -> float. Index
format must match |
required |
Returns:
| Type | Description |
|---|---|
A new DataFrame with ``concentration`` += background. Rows whose
|
|
date has no background entry are left unchanged.
|
|
annual_mean ¶
Annual-mean design-value calculation.
Used for the PM2.5 annual NAAQS (40 CFR 50.18) and the NO2 annual NAAQS (40 CFR 50.11). The standard form is the multi-year average of annual means; this returns per-receptor annual means — caller averages across years if a 3-year design value is wanted.
Returns one row per (x, y, year) with column concentration.
pm25_24hr_design_value ¶
PM2.5 24-hour design value: 3-year avg of annual 98th percentiles.
Per 40 CFR 50, Appendix N. Standard: 35 µg/m³.
Input df must contain hourly (or 24-hr-averaged) concentrations;
24-hr daily values are computed by averaging within each (receptor,
day) group when the AVE column equals "1-HR", otherwise rows are
used as-is.
Returns one row per receptor with the n-year average of annual 98th percentile daily-max concentrations.
no2_1hr_design_value ¶
NO2 1-hour design value: 3-year avg of annual 98th percentile of daily max 1-hour concentrations.
Per 40 CFR 50, Appendix S. Standard: 100 ppb.
Returns one row per receptor.
so2_1hr_design_value ¶
SO2 1-hour design value: 3-year avg of annual 99th percentile of daily max 1-hour concentrations.
Per 40 CFR 50, Appendix T. Standard: 75 ppb.
pm10_24hr_design_value ¶
PM10 24-hour design value: max daily concentration not to be exceeded more than once per year on average over 5 years.
Per 40 CFR 50.6. Standard: 150 µg/m³. Functionally we return the "high, second-high" (H2H) per receptor — the 2nd-highest daily-max concentration in the multi-year record (allowing one exceedance).
Caller decides how to average the H2H across the standard's 5-year window; this function returns one H2H per receptor.
o3_8hr_design_value ¶
O3 8-hour design value: 3-year avg of annual 4th-highest daily max 8-hour average concentration.
Per 40 CFR 50.19. Standard: 70 ppb.
Note: this expects the 8-hour rolling-average concentrations as input (AERMOD AVE='8-HR' column). Each (receptor, day) max is taken to obtain the daily 8-hr max series.
naaqs_compliance_report ¶
naaqs_compliance_report(pollutant: str, df: DataFrame, *, background: Optional[Union[float, dict, Series]] = None, n_years: int = 3) -> pd.DataFrame
One-stop compliance roll-up: design value + NAAQS comparison.
Dispatches to the right design-value function for pollutant,
optionally adds background, joins the NAAQS row, and flags
receptors that exceed.
Returns a DataFrame with columns:
- x, y: receptor coords
- design_value: numeric DV
- naaqs_level, units, cfr_reference
- exceeds: bool
Supported pollutants: PM2.5 (24-hour), PM10, NO2 (1-hour), SO2,
O3, plus annual forms via pollutant="PM2.5_annual" /
"NO2_annual".