Initial import of NavSea pbf project
This commit is contained in:
229
tasks/WeatherServer_GridBuilder
Normal file
229
tasks/WeatherServer_GridBuilder
Normal file
@@ -0,0 +1,229 @@
|
||||
# NavSea Weather Server
|
||||
Task: WeatherServer_GridBuilder
|
||||
Architecture: NavSea V11
|
||||
Codex: codex6
|
||||
Status: TODO
|
||||
|
||||
---
|
||||
|
||||
# 1 任务目标
|
||||
|
||||
实现 Weather Grid Builder 模块。
|
||||
|
||||
功能:
|
||||
|
||||
将 GRIB 数据解析为统一的 Weather Grid 数据结构。
|
||||
|
||||
输入:
|
||||
|
||||
data/grib/*.grib2
|
||||
|
||||
输出:
|
||||
|
||||
data/grid/*.json
|
||||
|
||||
Weather Grid 将作为:
|
||||
|
||||
Vector Tile Generator
|
||||
Routing Engine
|
||||
Weather Analysis
|
||||
|
||||
的基础数据源。
|
||||
|
||||
---
|
||||
|
||||
# 2 输入数据
|
||||
|
||||
GRIB 文件来自 Downloader。
|
||||
|
||||
示例:
|
||||
|
||||
data/grib/
|
||||
|
||||
20260312_00_f000.grib2
|
||||
20260312_00_f003.grib2
|
||||
20260312_00_f006.grib2
|
||||
|
||||
变量:
|
||||
|
||||
UGRD
|
||||
VGRD
|
||||
APCP
|
||||
PRMSL
|
||||
TMP
|
||||
|
||||
---
|
||||
|
||||
# 3 Weather Grid 数据结构
|
||||
|
||||
每个 grid 点结构:
|
||||
|
||||
{
|
||||
"lat": float,
|
||||
"lon": float,
|
||||
"wind_speed": float,
|
||||
"wind_dir": float,
|
||||
"rain": float,
|
||||
"temp": float,
|
||||
"pressure": float
|
||||
}
|
||||
|
||||
说明:
|
||||
|
||||
lat 纬度
|
||||
lon 经度
|
||||
|
||||
wind_speed m/s
|
||||
wind_dir 度
|
||||
|
||||
rain mm
|
||||
|
||||
temp 摄氏度
|
||||
|
||||
pressure hPa
|
||||
|
||||
---
|
||||
|
||||
# 4 风速计算
|
||||
|
||||
使用 U/V 分量计算:
|
||||
|
||||
wind_speed = sqrt(u² + v²)
|
||||
|
||||
---
|
||||
|
||||
# 5 风向计算
|
||||
|
||||
公式:
|
||||
|
||||
wind_dir = (atan2(u, v) * 180 / π + 360) % 360
|
||||
|
||||
结果:
|
||||
|
||||
0–360°
|
||||
|
||||
---
|
||||
|
||||
# 6 Grid Builder 输出
|
||||
|
||||
文件:
|
||||
|
||||
data/grid/
|
||||
|
||||
示例:
|
||||
|
||||
grid_20260312_00_f000.json
|
||||
|
||||
结构:
|
||||
|
||||
{
|
||||
"time": "20260312_00_f000",
|
||||
"points": [...]
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
# 7 创建文件
|
||||
|
||||
weather_server/grid/grid_builder.py
|
||||
|
||||
---
|
||||
|
||||
# 8 实现代码
|
||||
|
||||
```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)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
points = []
|
||||
|
||||
for i in range(len(lat)):
|
||||
|
||||
for j in range(len(lon)):
|
||||
|
||||
point = {
|
||||
|
||||
"lat": float(lat[i]),
|
||||
"lon": float(lon[j]),
|
||||
|
||||
"wind_speed": float(wind_speed[i][j]),
|
||||
"wind_dir": float(wind_dir[i][j]),
|
||||
|
||||
"rain": float(rain[i][j]),
|
||||
|
||||
"temp": float(temp[i][j]),
|
||||
|
||||
"pressure": float(pressure[i][j])
|
||||
}
|
||||
|
||||
points.append(point)
|
||||
|
||||
return points
|
||||
|
||||
|
||||
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)
|
||||
|
||||
points = process_file(path)
|
||||
|
||||
output = os.path.join(
|
||||
OUTPUT_DIR,
|
||||
f"grid_{file.replace('.grib2','')}.json"
|
||||
)
|
||||
|
||||
data = {
|
||||
|
||||
"time": file.replace(".grib2",""),
|
||||
"points": points
|
||||
}
|
||||
|
||||
with open(output, "w") as f:
|
||||
|
||||
json.dump(data, f)
|
||||
|
||||
print("saved", output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user