Skip to content

met_ingest

met_ingest

PyAERMOD Meteorological Data Ingest

Helpers to fetch and preprocess upstream met data before AERMET:

  • ASOS1Min: parse 1-minute ASOS DSI-6405 files and aggregate to hourly (skeleton of the AERMINUTE algorithm) for use in AERMET Stage 1.
  • ISDFetcher: fetch NOAA ISD / ISD-Lite hourly surface observations.
  • IGRAFetcher: fetch IGRA v2 upper-air radiosonde soundings.
  • MMIFConfig: plug an MMIF-produced .SFC/.PFL pair directly into AERMODProject's meteorology pathway (bypassing AERMET).

All network helpers accept either a local path or a URL; they are designed to be mockable in tests.

ASOS1MinRecord dataclass

One parsed 1-minute ASOS observation.

ISDStationId dataclass

USAF + WBAN identifier for an ISD station.

ISDFetcher

Fetch NOAA ISD / ISD-Lite surface observations.

ISD-Lite is the simpler hourly product (8 elements). Use use_lite=True unless you need the full ISD record for AERMET's ISHD reader.

fetch

fetch(station: ISDStationId, year: int) -> bytes

Download the ISD file for one station-year; returns raw gzipped bytes.

If cache_dir was set and the file is already cached, returns the cached bytes without hitting the network.

read_hourly

read_hourly(station: ISDStationId, year: int) -> List[Dict[str, Any]]

Fetch ISD-Lite and parse into list of hourly dicts.

ISD-Lite columns (whitespace-delimited, -9999 = missing): YEAR MONTH DAY HOUR T DEWPT SLP WDIR WSPD SKY_COND 1HR_PRCP 6HR_PRCP T/DEWPT in tenths of C; WSPD in tenths of m/s; SLP in tenths of hPa.

IGRASounding dataclass

One radiosonde ascent.

IGRAFetcher

Fetch IGRA v2 upper-air soundings for a station.

fetch_text

fetch_text(station_id: str) -> str

Return the raw IGRA v2 text (year-to-date) for a station id.

station_id is the 11-character IGRA id (e.g. 'USM00072469').

MMIFConfig dataclass

Describes an MMIF-produced meteorology pair.

MMIF (EPA's prognostic-to-AERMOD bridge) emits AERMOD-compatible .SFC and .PFL files from WRF/MM5/RAMS output. Since AERMOD reads these directly, the MMIFConfig just provides a sanity-checked plug into MeteorologyPathway.

to_meteorology

to_meteorology() -> Dict[str, str]

Return kwargs suitable for MeteorologyPathway(...).

Use as: MeteorologyPathway(**mmif_config.to_meteorology(), ...).

parse_asos_1min_line

parse_asos_1min_line(line: str) -> Optional[ASOS1MinRecord]

Parse a single 1-minute ASOS DSI-6405 page-1 line.

Returns None if the line is not parseable. Real DSI-6405 has a complex fixed-width format; this covers the common subset used by AERMINUTE (wind speed + direction with QC flag). Knots are converted to m/s.

aggregate_1min_to_hourly

aggregate_1min_to_hourly(records: List[ASOS1MinRecord]) -> List[Dict[str, Any]]

Aggregate 1-minute observations to hourly vector averages.

This is the core AERMINUTE algorithm (simplified): - Group by (year, month, day, hour) - Compute vector-mean wind (u, v) for non-calm, non-variable records - Calm hour if all records in that hour are calm - Variable hour if valid records < threshold (AERMINUTE uses 2)

Returns a list of dicts with keys year/month/day/hour/ws/wd/n_obs/flag.

parse_asos_1min_file

parse_asos_1min_file(path: Union[str, Path]) -> List[ASOS1MinRecord]

Parse a DSI-6405 1-minute ASOS file into records.

Handles .gz compression transparently.

parse_igra_v2

parse_igra_v2(text: str) -> List[IGRASounding]

Parse IGRA v2 data-format text into a list of soundings.

Header line format: "#USM00072469 2020 01 01 00 2359 ..." etc. Level lines follow; count is given in the header. We extract just enough to be useful for AERMET Stage 1 input (pressure, height, temp, wind).