Refine climate metrics and data pipeline
This commit is contained in:
@@ -25,7 +25,6 @@ import numpy as np
|
||||
import pandas as pd
|
||||
import xarray as xr
|
||||
|
||||
|
||||
STATE_FIPS_TO_ABBR = {
|
||||
"01": "AL",
|
||||
"04": "AZ",
|
||||
@@ -80,6 +79,7 @@ STATE_FIPS_TO_ABBR = {
|
||||
CONUS_STATE_FIPS = set(STATE_FIPS_TO_ABBR)
|
||||
REQUIRED_VARIABLES = ("sph", "rmax", "rmin")
|
||||
SUMMER_MONTHS = {6, 7, 8}
|
||||
DEFAULT_HEAT_INDEX_THRESHOLD_F = 90.0
|
||||
NOAA_REGION_CODE_TO_FIPS_OVERRIDES = {
|
||||
"18511": "11001",
|
||||
}
|
||||
@@ -436,8 +436,12 @@ def _county_means_chunk(
|
||||
|
||||
|
||||
def _heat_index_f(t_f: np.ndarray, rh_pct: np.ndarray) -> np.ndarray:
|
||||
"""Return the NWS Heat Index for Fahrenheit temperature and percent RH."""
|
||||
rh = np.clip(rh_pct, 0, 100)
|
||||
heat_index = (
|
||||
simple_heat_index = 0.5 * (t_f + 61.0 + ((t_f - 68.0) * 1.2) + (rh * 0.094))
|
||||
simple_heat_index = (simple_heat_index + t_f) / 2
|
||||
|
||||
regression_heat_index = (
|
||||
-42.379
|
||||
+ 2.04901523 * t_f
|
||||
+ 10.14333127 * rh
|
||||
@@ -451,9 +455,17 @@ def _heat_index_f(t_f: np.ndarray, rh_pct: np.ndarray) -> np.ndarray:
|
||||
|
||||
low_rh_adjustment = ((13 - rh) / 4) * np.sqrt(np.maximum((17 - np.abs(t_f - 95)) / 17, 0))
|
||||
high_rh_adjustment = ((rh - 85) / 10) * ((87 - t_f) / 5)
|
||||
heat_index = np.where((rh < 13) & (80 <= t_f) & (t_f <= 112), heat_index - low_rh_adjustment, heat_index)
|
||||
heat_index = np.where((rh > 85) & (80 <= t_f) & (t_f <= 87), heat_index + high_rh_adjustment, heat_index)
|
||||
return np.where(t_f >= 80, heat_index, t_f)
|
||||
regression_heat_index = np.where(
|
||||
(rh < 13) & (80 <= t_f) & (t_f <= 112),
|
||||
regression_heat_index - low_rh_adjustment,
|
||||
regression_heat_index,
|
||||
)
|
||||
regression_heat_index = np.where(
|
||||
(rh > 85) & (80 <= t_f) & (t_f <= 87),
|
||||
regression_heat_index + high_rh_adjustment,
|
||||
regression_heat_index,
|
||||
)
|
||||
return np.where(simple_heat_index >= 80, regression_heat_index, simple_heat_index)
|
||||
|
||||
|
||||
def _time_dimension(data_array: xr.DataArray, lat_dim: str, lon_dim: str) -> str:
|
||||
@@ -646,7 +658,8 @@ def summarize(args: argparse.Namespace) -> None:
|
||||
"gridmetSource": (
|
||||
f"gridmet-{source_period} county-cell-weighted; "
|
||||
"relative-humidity=(rmax+rmin)/2; "
|
||||
"humidHeatDays=noaa-nclimgrid-tmax+gridmet-rmin heat-index-gte-90f"
|
||||
"humidHeatDays=noaa-nclimgrid-tmax+gridmet-rmin "
|
||||
f"heat-index-gte-{args.heat_index_threshold_f:g}f"
|
||||
),
|
||||
}
|
||||
)
|
||||
@@ -680,7 +693,15 @@ def main() -> int:
|
||||
parser.add_argument("--years", type=_parse_years, default=None, help="Optional comma/range years, e.g. 1991-2020.")
|
||||
parser.add_argument("--start-year", type=int, default=None)
|
||||
parser.add_argument("--end-year", type=int, default=None)
|
||||
parser.add_argument("--heat-index-threshold-f", type=float, default=90.0)
|
||||
parser.add_argument(
|
||||
"--heat-index-threshold-f",
|
||||
type=float,
|
||||
default=DEFAULT_HEAT_INDEX_THRESHOLD_F,
|
||||
help=(
|
||||
"Daily Heat Index threshold in F. The default 90 F is the lower "
|
||||
"bound of the NWS Extreme Caution category."
|
||||
),
|
||||
)
|
||||
parser.add_argument("--chunk-days", type=int, default=31)
|
||||
summarize(parser.parse_args())
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user