Skip to content

Atmospheric Propagation (ITU-R)

ITU-R P-series atmospheric propagation models for computing attenuation on Earth-to-space radio paths. Based on the ITU-Rpy library.

Prerequisites

Grid-based models read reference data from a bundled lox-itur-data.npz archive. Build it once from the upstream itur Python wheel (see the lox-itur README for the packaging workflow), then open it with lox.ItuProvider:

import lox_space as lox

provider = lox.ItuProvider("lox-itur-data.npz")

A single provider can be reused for all lookups; grids are loaded lazily and cached on first access.

Quick Start

Compute the total atmospheric attenuation for a ground station in Madrid receiving at 14.25 GHz from a satellite at 30° elevation:

losses = provider.propagation_losses(
    lat=40.4 * lox.deg,
    lon=-3.7 * lox.deg,
    frequency=14.25 * lox.GHz,
    elevation=30.0 * lox.deg,
    probability=0.01,       # exceeded 0.01% of the year
    diameter=1.2 * lox.m,   # antenna diameter
)

for label, value, absorptive in losses.lines:
    print(f"{label}: {value}")
print(f"Total:      {losses.total()}")
print(f"Absorptive: {losses.absorptive()}")

The rain, gaseous, and cloud lines carry the raw model outputs; the combination residual of the ITU-R P.618 total is booked on the scintillation line, so total() equals the combined attenuation and absorptive() is exactly the part that raises the antenna noise temperature (used for the rain-degraded G/T on downlinks).

For link budgets with known loss values, build PropagationLosses directly:

losses = lox.PropagationLosses(rain=2.0 * lox.dB, gaseous=0.5 * lox.dB)
losses = lox.PropagationLosses.none()

The result plugs directly into LinkBudget for link budget analysis.

Individual Models

Each ITU-R recommendation is also available as a standalone function.

Rain Attenuation (P.618)

a_rain = provider.rain_attenuation(
    lat=40.4 * lox.deg,
    lon=-3.7 * lox.deg,
    frequency=14.25 * lox.GHz,
    elevation=30.0 * lox.deg,
    probability=0.01,
)

Gaseous Attenuation (P.676)

a_oxygen, a_water = lox.gaseous_attenuation_slant_path(
    frequency=14.25 * lox.GHz,
    elevation=30.0 * lox.deg,
    pressure=1013.25 * lox.hPa,
    rho=7.5,                      # water vapour density (g/m³)
    temperature=288.15 * lox.K,
)

Cloud Attenuation (P.840)

a_cloud = provider.cloud_attenuation(
    lat=40.4 * lox.deg,
    lon=-3.7 * lox.deg,
    elevation=30.0 * lox.deg,
    frequency=14.25 * lox.GHz,
    probability=1.0,
)

Scintillation (P.618)

a_scint = provider.scintillation_attenuation(
    frequency=14.25 * lox.GHz,
    elevation=30.0 * lox.deg,
    probability=0.01,
    diameter=1.2 * lox.m,
    lat=40.4 * lox.deg,
    lon=-3.7 * lox.deg,
)

Specific Rain Attenuation (P.838)

gamma_r = lox.rain_specific_attenuation(
    rain_rate=25.0,               # mm/h
    frequency=14.25 * lox.GHz,
    elevation=30.0 * lox.deg,
)

Geophysical Data Lookups

Topographic Altitude (P.1511)

alt = provider.topographic_altitude(lat=27.99 * lox.deg, lon=86.93 * lox.deg)
print(f"Altitude: {alt.to_kilometers():.1f} km")

Surface Temperature (P.1510)

t = provider.surface_mean_temperature(lat=0.0 * lox.deg, lon=0.0 * lox.deg)
print(f"Temperature: {t.to_kelvin():.1f} K")

Rainfall Rate (P.837)

r = provider.rainfall_rate(lat=40.4 * lox.deg, lon=-3.7 * lox.deg, probability=0.01)
print(f"Rainfall rate: {r:.1f} mm/h")

Rain Height (P.839)

h = provider.rain_height(lat=40.4 * lox.deg, lon=-3.7 * lox.deg)
print(f"Rain height: {h.to_kilometers():.1f} km")

PropagationLosses can be passed directly to LinkBudget, where tx is a TxChain or EirpModel and rx is an RxChain or GtModel (see Communications):

losses = provider.propagation_losses(
    lat=40.4 * lox.deg,
    lon=-3.7 * lox.deg,
    frequency=29.0 * lox.GHz,
    elevation=30.0 * lox.deg,
    probability=0.01,
    diameter=0.6 * lox.m,
)

budget = lox.LinkBudget(
    tx,
    rx,
    carrier=29.0 * lox.GHz,
    range=1000.0 * lox.km,
    losses=losses,
)

Data Files

Grid-based models (P.453, P.618, P.836, P.837, P.839, P.840, P.1510, P.1511) require reference data from the ITU, distributed via the upstream itur Python package. Build a lox-itur-data.npz bundle once and open it with lox.ItuProvider. See the lox-itur README for the packaging workflow.

Implemented Recommendations

Recommendation Description
P.453-13 Radio refractive index
P.618-14 Earth-space propagation (rain, scintillation, XPD)
P.676-13 Gaseous attenuation (O₂ + H₂O)
P.835-6 Reference standard atmospheres
P.836-6 Water vapour surface density
P.837-7 Rainfall rate
P.838-3 Specific rain attenuation
P.839-4 Rain height
P.840-9 Cloud and fog attenuation
P.1510-1 Surface temperature
P.1511-2 Topographic altitude

ItuProvider

ItuProvider(path: str)

An open ITU-R data bundle (lox-itur-data.npz).

Grid-based recommendations (rain, cloud, scintillation, topography, ...) are served as methods on this object. Build a bundle once with::

cargo run -p lox-itur --bin pack -- <itur-wheel.whl> lox-itur-data.npz

Methods:

cloud_attenuation

cloud_attenuation(
    lat: Angle, lon: Angle, elevation: Angle, frequency: Frequency, probability: float
) -> Decibel

Compute cloud attenuation on a slant path (P.840-9).

propagation_losses

propagation_losses(
    lat: Angle,
    lon: Angle,
    frequency: Frequency,
    elevation: Angle,
    probability: float,
    diameter: Distance,
    polarisation_tilt: Angle | None = None,
) -> PropagationLosses

Compute excess propagation losses on a slant path.

Combines rain (P.618), gaseous (P.676), cloud (P.840), and scintillation (P.618) attenuation per ITU-R recommendations; the combination residual is booked on the scintillation line.

rain_attenuation

rain_attenuation(
    lat: Angle,
    lon: Angle,
    frequency: Frequency,
    elevation: Angle,
    probability: float,
    polarisation_tilt: Angle | None = None,
    station_altitude: Distance | None = None,
) -> Decibel

Compute rain attenuation exceeded for a given probability (P.618-13).

rain_height

rain_height(lat: Angle, lon: Angle) -> Distance

Return mean annual rain height at the given location (P.839-4).

rainfall_rate

rainfall_rate(lat: Angle, lon: Angle, probability: float) -> float

Return rainfall rate in mm/h exceeded for a given probability (P.837-7).

scintillation_attenuation

scintillation_attenuation(
    frequency: Frequency,
    elevation: Angle,
    probability: float,
    diameter: Distance,
    eta: float = 0.5,
    lat: Angle | None = None,
    lon: Angle | None = None,
) -> Decibel

Compute tropospheric scintillation fade depth (P.618-13).

surface_mean_temperature

surface_mean_temperature(lat: Angle, lon: Angle) -> Temperature

Return annual mean surface temperature at the given location (P.1510-1).

topographic_altitude

topographic_altitude(lat: Angle, lon: Angle) -> Distance

Return topographic altitude at the given location (P.1511-2).

upstream_version

upstream_version() -> str

The upstream itur package version this bundle was built from.


PropagationLosses

Itemized excess propagation losses along a link path, beyond free-space path loss.

Parameters:

  • rain

    Rain attenuation (optional).

  • gaseous

    Gaseous absorption (optional).

  • cloud

    Cloud attenuation (optional).

  • scintillation

    Scintillation loss (optional).

  • depolarization

    Depolarization loss (optional).

  • other

    Custom lines as (label, value, absorptive) tuples (optional).

Methods:

  • absorptive

    Returns the absorptive part of the loss — the attenuation that

  • none

    Returns zero propagation losses.

  • total

    Returns the total excess loss.

Attributes:

lines property

lines: list[tuple[str, Decibel, bool]]

The loss lines as (label, value, absorptive) tuples, in insertion order.

absorptive

absorptive() -> Decibel

Returns the absorptive part of the loss — the attenuation that also raises the receive antenna noise temperature.

none staticmethod

Returns zero propagation losses.

total

total() -> Decibel

Returns the total excess loss.


gaseous_attenuation_slant_path builtin

gaseous_attenuation_slant_path(
    frequency: Frequency,
    elevation: Angle,
    pressure: Pressure,
    rho: float,
    temperature: Temperature,
) -> tuple[Decibel, Decibel]

Computes gaseous attenuation on a slant path (P.676-12 approximate method).

Parameters:

  • frequency

    (Frequency) –

    Frequency.

  • elevation

    (Angle) –

    Elevation angle.

  • pressure

    (Pressure) –

    Surface pressure.

  • rho

    (float) –

    Surface water vapour density in g/m³.

  • temperature

    (Temperature) –

    Surface temperature.

Returns:


rain_specific_attenuation builtin

rain_specific_attenuation(
    rain_rate: float,
    frequency: Frequency,
    elevation: Angle,
    polarisation_tilt: Angle | None = None,
) -> float

Computes the specific attenuation from rain (P.838-3).

Parameters:

  • rain_rate

    (float) –

    Rainfall rate in mm/h.

  • frequency

    (Frequency) –

    Frequency.

  • elevation

    (Angle) –

    Elevation angle.

  • polarisation_tilt

    (Angle | None, default: None ) –

    Polarisation tilt angle (default 45° for circular).

Returns:

  • float

    Specific rain attenuation in dB/km.