Files
weather/tasks/WeatherServer_GridBuilder_v2.md
OpenAI Codex c957fef15b Initial import
2026-03-17 19:52:51 +08:00

3.2 KiB
Raw Permalink Blame History

NavSea Weather Server

Task: WeatherServer_GridBuilder_v2 Architecture: NavSea V11 Codex: codex6 Status: TODO


1 任务目标

升级 Grid Builder

grid_builder.py → GridBuilder v2

目标:

1 裁剪日本区域 grid
2 使用数组结构保存 grid
3 大幅减少 JSON 文件大小


2 当前问题

旧版 GridBuilder

生成全球 grid

1440 × 721
≈ 1,038,240 points

JSON 文件:

≈ 215MB

这是不可接受的。

Downloader 已经只下载:

120E 150E
20N 50N

GridBuilder 必须只输出这个区域。


3 区域范围

REGION

lon_min = 120 lon_max = 150

lat_min = 20 lat_max = 50

理论 grid

(150-120)/0.25 = 120
(50-20)/0.25 = 120

≈ 14400 grid points


4 新 Grid 数据结构

旧结构:

points list

{ "points":[ {lat,lon,...} ] }

新结构:

grid arrays

{ "time": "...", "lat": [...], "lon": [...], "wind_speed": [...], "wind_dir": [...], "rain": [...], "temp": [...], "pressure": [...] }

优点:

1 文件更小
2 读取更快
3 tile generator 更容易


5 创建文件

weather_server/grid/grid_builder_v2.py


6 实现代码

import os
import json
import numpy as np
import xarray as xr

INPUT_DIR = "data/grib"
OUTPUT_DIR = "data/grid"

os.makedirs(OUTPUT_DIR, exist_ok=True)

REGION = {
    "lon_min":120,
    "lon_max":150,
    "lat_min":20,
    "lat_max":50
}


def compute_wind(u, v):

    speed = np.sqrt(u**2 + v**2)

    direction = (np.degrees(np.arctan2(u, v)) + 360) % 360

    return speed, direction


def process_file(path):

    ds = xr.open_dataset(path, engine="cfgrib")

    u = ds["u10"].values
    v = ds["v10"].values
    rain = ds["tp"].values
    pressure = ds["msl"].values
    temp = ds["t2m"].values

    lat = ds.latitude.values
    lon = ds.longitude.values

    wind_speed, wind_dir = compute_wind(u, v)

    lat_idx = np.where(
        (lat >= REGION["lat_min"]) &
        (lat <= REGION["lat_max"])
    )[0]

    lon_idx = np.where(
        (lon >= REGION["lon_min"]) &
        (lon <= REGION["lon_max"])
    )[0]

    lat_region = lat[lat_idx]
    lon_region = lon[lon_idx]

    wind_speed = wind_speed[np.ix_(lat_idx, lon_idx)]
    wind_dir = wind_dir[np.ix_(lat_idx, lon_idx)]

    rain = rain[np.ix_(lat_idx, lon_idx)]
    temp = temp[np.ix_(lat_idx, lon_idx)]
    pressure = pressure[np.ix_(lat_idx, lon_idx)]

    return {
        "lat": lat_region.tolist(),
        "lon": lon_region.tolist(),
        "wind_speed": wind_speed.tolist(),
        "wind_dir": wind_dir.tolist(),
        "rain": rain.tolist(),
        "temp": temp.tolist(),
        "pressure": pressure.tolist()
    }


def main():

    for file in os.listdir(INPUT_DIR):

        if not file.endswith(".grib2"):
            continue

        path = os.path.join(INPUT_DIR, file)

        print("processing", file)

        grid = process_file(path)

        output = os.path.join(
            OUTPUT_DIR,
            f"grid_{file.replace('.grib2','')}.json"
        )

        data = {
            "time": file.replace(".grib2",""),
            "grid": grid
        }

        with open(output, "w") as f:

            json.dump(data, f)

        print("saved", output)


if __name__ == "__main__":

    main()