apsis-rs/validation/tools/generate_p839_table.py

88 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Generate the Rust source for the ITU-R P.839-4 rain height table.
The recommendation gives the height of the zero degree isotherm as a
tabulated global grid at 1.5 degree resolution. This script reads the grid
from the ``itur`` reference package and emits a Rust module that embeds it as
integer tenths of a kilometre, which is the resolution the recommendation
publishes.
Usage:
python validation/tools/generate_p839_table.py > /tmp/p839_table.rs
生成 ITU-R P.839-4 雨顶高度表的 Rust 源码。
该建议书把零度等温线高度给出为 1.5 度分辨率的全球列表网格。本脚本从
``itur`` 参考包读取该网格,并输出一个 Rust 模块,把它以十分之一千米的整数
嵌入,这正是该建议书发布的分辨率。
用法:
python validation/tools/generate_p839_table.py > /tmp/p839_table.rs
"""
from __future__ import annotations
import sys
import numpy as np
BASE = (
"validation/.pixi/envs/default/lib/python3.12/site-packages/itur/data/839/"
)
# The grid resolution, in degrees.
# 网格分辨率,单位为度。
STEP_DEGREES = 1.5
def main() -> int:
heights = np.load(BASE + "v4_esa0height.npz")["arr_0"]
latitudes = np.load(BASE + "v4_esalat.npz")["arr_0"]
longitudes = np.load(BASE + "v4_esalon.npz")["arr_0"]
rows = heights.shape[0]
columns = heights.shape[1]
# The grid is regular: latitude runs from 90 down to -90 and longitude
# from 0 to 360, both in steps of 1.5 degrees.
# 该网格是规则的:纬度自 90 降到 -90,经度自 0 到 360,步长均为 1.5 度。
assert np.allclose(latitudes[:, 0], np.linspace(90.0, -90.0, rows)), "latitude grid"
assert np.allclose(longitudes[0, :], np.linspace(0.0, 360.0, columns)), "longitude grid"
# The recommendation publishes the height to the nearest metre, so the
# table is stored in metres to avoid losing precision.
# 该建议书把高度发布到最近一米,故该表以米存储以避免损失精度。
metres = np.round(heights * 1000.0).astype(np.uint16)
print("/// The height of the zero degree isotherm, in metres.")
print("///")
print("/// The grid runs from 90 degrees north to 90 degrees south in the row")
print("/// direction and from 0 to 360 degrees east in the column direction,")
print("/// both in steps of 1.5 degrees, so there are 121 rows and 241 columns.")
print("/// The value at a fractional latitude or longitude is found by bilinear")
print("/// interpolation between the four surrounding points.")
print("///")
print("/// Source: ITU-R Recommendation P.839-4, *Rain height model for prediction")
print("/// methods*, which tabulates the isotherm height on this grid.")
print("///")
print("/// 零度等温线的高度,单位为米。")
print("///")
print("/// 网格在行方向上自北纬 90 度到南纬 90 度,在列方向上自东经 0 度到")
print("/// 360 度,步长均为 1.5 度,故有 121 行 241 列。分数纬度或经度处的值")
print("/// 由周围四点之间的双线性插值求得。")
print("///")
print("/// 出处:ITU-R 建议书 P.839-4,*Rain height model for prediction methods*,")
print("/// 它在该网格上列出等温线高度。")
print(f"pub static ZERO_ISOTHERM_HEIGHT_METRES: [[u16; {columns}]; {rows}] = [")
for row in range(rows):
values = ", ".join(str(int(value)) for value in metres[row])
print(f" [{values}],")
print("];")
return 0
if __name__ == "__main__":
raise SystemExit(main())