Wrap a measured antenna pattern#

rustmatrix.spectra.beam.GaussianBeam and AiryBeam cover the two canonical analytic patterns. If you have a measured range-azimuth pattern from an antenna-range scan or a manufacturer’s datasheet, feed it in as a TabulatedBeam instead.

The contract#

TabulatedBeam(theta, gain) is a drop-in BeamPattern:

  • theta — 1-D array of off-axis angles in radians, monotonic increasing, starting at or near 0.

  • gain — 1-D array of one-way power gain (linear, not dB) at each angle. Normalise so that the peak is 1.0; the absolute level doesn’t matter (integration normalises it).

Side-lobe angles past the last table entry get extrapolated to zero.

Example — import a measured H-plane cut#

import numpy as np
from rustmatrix import spectra
from rustmatrix.spectra import beam

# Measured H-plane cut from an antenna-range scan — angle in degrees,
# gain in dB (one-way).
theta_deg, gain_dB = np.loadtxt("antenna_pattern_h.csv",
                                delimiter=",", unpack=True)

# Convert to the BeamPattern convention.
theta_rad = np.deg2rad(theta_deg)
gain_lin  = 10 ** (gain_dB / 10.0)
gain_lin /= gain_lin.max()                # peak-normalise

# Fold about θ=0 if the measurement sweeps ±θ_max: keep only θ ≥ 0.
mask = theta_rad >= 0
pattern = beam.TabulatedBeam(theta_rad[mask], gain_lin[mask])

Then pass pattern straight into BeamIntegrator:

bi = beam.BeamIntegrator(
    pattern=pattern,
    scene=beam.marshall_palmer_scene(Z_dBZ_map, N0=8000),
    v_bins=np.linspace(-2, 12, 281),
    # ... other SpectralIntegrator kwargs
)
spectrum = bi.compute(scatterer)

Gotchas#

  • Power, not voltage. TabulatedBeam expects power gain. If your CSV is in field-strength / voltage units, square it first.

  • One-way, not two-way. Many antenna-range reports give the two-way pattern (what the radar measures in transmit-receive). For the beam-integration math in rustmatrix.spectra.beam, use the one-way pattern — the two-way weight is applied internally as \(G^2\).

  • θ in radians. Degrees is a frequent source of silent bugs; assertions inside TabulatedBeam flag angles > π, but the range of valid radian values is usually [0, 0.1] for a 5° beam.

E-plane vs H-plane#

A real antenna has slightly different patterns in the E-plane and H-plane. rustmatrix.spectra.beam treats the beam as axisymmetric. If you need the full 2-D pattern, wrap a BeamPattern subclass that takes (theta, phi)TabulatedBeam is a reasonable copy-paste template.

See also#