66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
#!/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
|
|
"""
|
|
|
|
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.
|
|
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(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())
|