Initial import of NavSea pbf project

This commit is contained in:
OpenAI Codex
2026-03-17 19:48:15 +08:00
commit 5f3f7409b3
84 changed files with 43889 additions and 0 deletions

View File

@@ -0,0 +1,215 @@
# 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 实现代码
```python
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()