3.2 KiB
3.2 KiB
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()