weather-llm-initial / scripts /preprocess_noaa.py
NagacharanVemula
Initial code-first model repo publish.
78dea75
Raw
History Blame Contribute Delete
2.81 kB
#!/usr/bin/env python3
"""Aggregate GHCN-Daily station files into weather-heavy JSONL documents."""
from __future__ import annotations
import argparse
import sys
from collections import defaultdict
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "src"))
from tqdm import tqdm
from weather_llm.config_loader import load_yaml, repo_root_from
from weather_llm.data.jsonl_utils import write_jsonl
from weather_llm.data.noaa import (
aggregate_monthly,
iter_ghcn_daily_csv,
monthly_docs_for_state,
resolve_noaa_states_and_max_per_state,
station_id_to_state_map,
state_rollup_doc,
)
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--config", type=Path, default=None)
args = ap.parse_args()
root = repo_root_from(ROOT)
cfg_path = args.config or (root / "configs/data_default.yaml")
cfg = load_yaml(cfg_path)
noaa = cfg["noaa"]
paths = cfg["paths"]
raw_dir = root / paths["raw_noaa"]
out_path = root / paths["processed"] / "weather.jsonl"
files = sorted(raw_dir.glob("US*.csv.gz")) + sorted(raw_dir.glob("US*.csv"))
if not files:
raise SystemExit(f"No station CSV(.gz) files under {raw_dir}. Run scripts/download_noaa.py first.")
states_cfg, _ = resolve_noaa_states_and_max_per_state(noaa)
fallback_state = states_cfg[0]
inv_path = raw_dir / "ghcnd-stations.txt"
if inv_path.is_file():
sid_to_state = station_id_to_state_map(inv_path.read_text(encoding="utf-8", errors="replace"))
else:
sid_to_state = {}
all_docs: list[dict] = []
seed = int(cfg["merge"]["seed"])
y0, y1 = int(noaa["year_start"]), int(noaa["year_end"])
monthly_global: dict = {}
stations_by_state: dict[str, list[str]] = defaultdict(list)
for fp in tqdm(files, desc="stations"):
sid = fp.name.split(".")[0]
st = sid_to_state.get(sid, fallback_state)
stations_by_state[st].append(sid)
daily = iter_ghcn_daily_csv(fp)
monthly = aggregate_monthly(daily, y0, y1)
for k, v in monthly.items():
monthly_global[k] = v
docs = monthly_docs_for_state(st, [sid], monthly, y0, y1, seed)
all_docs.extend(docs)
# One July rollup per state represented in the download (correct geography in text)
for st in sorted(stations_by_state.keys()):
sids = stations_by_state[st]
sub_seed = seed + sum(ord(c) for c in st) * 1_000_003
rollup = state_rollup_doc(st, sids, monthly_global, y0, y1, month=7, seed=sub_seed)
if rollup:
all_docs.append(rollup)
write_jsonl(out_path, iter(all_docs))
print("Wrote", len(all_docs), "documents to", out_path)
return 0
if __name__ == "__main__":
raise SystemExit(main())