Communications
RF link budget analysis for space communication systems.
Modulation Schemes
| Name | Bits per Symbol |
|---|---|
BPSK, GMSK, 2FSK |
1 |
QPSK, OQPSK, 4FSK |
2 |
8PSK, 8APSK |
3 |
16QAM, 16APSK |
4 |
32QAM, 32APSK |
5 |
64QAM, 64APSK |
6 |
128QAM |
7 |
256QAM |
8 |
Antenna Patterns
| Pattern | Description |
|---|---|
ParabolicPattern |
Airy disk model for parabolic reflector antennas |
GaussianPattern |
Gaussian roll-off approximation |
DipolePattern |
Short and general dipole radiation patterns |
Pattern gain is evaluated at two angles: theta, the polar angle from
boresight, and phi, the azimuth about boresight measured from the
antenna-frame +X axis toward +Y. All built-in patterns are axially
symmetric and ignore phi, so it can be omitted:
import lox_space as lox
pattern = lox.ParabolicPattern(diameter=0.98 * lox.m, efficiency=0.45)
gain = pattern.gain(29 * lox.GHz, theta=1.0 * lox.deg)
Antenna Frames
An AntennaFrame orients an antenna pattern in a parent frame as a
right-handed orthonormal basis: +Z is the boresight (theta = 0) and +X
is the phi = 0 reference direction. Construct it from a boresight and a
reference direction, or use AntennaFrame.identity() for a frame aligned
with the parent frame (boresight along +Z):
import lox_space as lox
frame = lox.AntennaFrame.from_boresight_and_reference(
boresight=[1.0, 0.0, 0.0], reference=[0.0, 0.0, 1.0]
)
theta, phi = frame.angles_for([0.0, 0.0, 1.0])
A PatternedAntenna combines a pattern with a frame (identity by default)
and can evaluate its gain directly toward a parent-frame direction vector
via gain_toward:
pattern = lox.ParabolicPattern(diameter=0.98 * lox.m, efficiency=0.45)
antenna = lox.PatternedAntenna(pattern=pattern, frame=frame)
gain = antenna.gain_toward(29 * lox.GHz, [1.0, 0.0, 0.0]) # on boresight
Link Terminals
A link terminal is one end of a radio link. The component tier composes an
antenna with a radio, a feed loss, and the supported frequency range: a
TxChain is an antenna fed by an AmplifierTransmitter, an RxChain is a
NoiseTempReceiver or CascadeReceiver fed by an antenna. Components are
pure physics (power, noise, gain patterns); the band lives on the terminal.
Shared hardware is expressed by reusing the same component values — a
diplexer-style transceiver is a TX and an RX chain sharing one dish:
import lox_space as lox
ka_band = lox.FrequencyRange(27.0 * lox.GHz, 31.0 * lox.GHz)
dish = lox.ConstantAntenna(gain=46.0 * lox.dB)
tx = lox.TxChain(
dish,
lox.AmplifierTransmitter(power=10 * lox.W),
band=ka_band,
feed_loss=1.0 * lox.dB,
)
rx = lox.RxChain(
dish,
lox.NoiseTempReceiver(noise_temperature=500 * lox.K),
band=ka_band,
antenna_noise_temperature=0.0 * lox.K,
feed_loss=0.5 * lox.dB,
)
Wherever a band is expected, an IEEE letter-band name is accepted as shorthand for the full band range (case-insensitive):
tx = lox.TxChain(
dish,
lox.AmplifierTransmitter(power=10 * lox.W),
band="Ka", # 27–40 GHz
feed_loss=1.0 * lox.dB,
)
Terminals expose their headline figures directly — eirp_at and gt_at
evaluate at a carrier and an optional pointing:
eirp = tx.eirp_at(29.0 * lox.GHz) # 46 + 10·log10(10) − 1 = 55 dBW
gt = rx.gt_at(29.0 * lox.GHz, angle=1.0 * lox.deg)
t_sys = rx.system_noise_temperature()
LinkBudget computes a link budget between two terminals. The carrier is
a link-level input and must lie inside both terminals' frequency ranges;
all outputs are bandwidth-free (C/N and noise power are derived views that
take an explicit bandwidth):
link = lox.LinkBudget(
tx,
rx,
carrier=29.0 * lox.GHz,
range=1000.0 * lox.km,
)
print(f"C/N0 = {float(link.c_n0):.2f} dB·Hz")
Terminals attach to assets for scenario analysis as named collections via
GroundStation(..., tx_terminals={...}, rx_terminals={...}) and
Spacecraft(..., tx_terminals={...}, rx_terminals={...}); selecting a
terminal by name is the configuration choice (e.g. high-gain vs. low-gain
antenna).
Lumped EIRP and G/T
For early-phase mission studies — where manufacturer datasheets typically
publish only aggregate figures — you can build a link budget directly from
lumped EirpModel and GtModel terminals:
import lox_space as lox
link = lox.LinkBudget(
lox.EirpModel("Ka", 55.0 * lox.dB),
lox.GtModel("Ka", 3.01 * lox.dB),
carrier=29.0 * lox.GHz,
range=1000.0 * lox.km,
)
print(f"C/N0 = {float(link.c_n0):.2f} dB·Hz")
For lumped links, link.carrier_rx_power and link.noise_power(bandwidth)
are None — the absolute carrier and noise power are not recoverable from
EIRP and G/T alone. The carrier-to-noise density ratio (c_n0) and the
carrier-to-noise ratio view (c_n(bandwidth)) remain available.
To compute modulation-aware figures (Es/N0, Eb/N0, link margin, data
rate), modulate the budget with a Channel (the waveform: symbol rate,
roll-off, optional DSSS chip rate) and a ModCod (the modulation and
coding scheme with its Eb/N0 threshold). Everything bandwidth-dependent
derives from the channel; the design margin is an input:
channel = lox.Channel(symbol_rate=5 * lox.MHz)
modcod = lox.ModCod("QPSK 1/2", lox.Modulation("QPSK"), 0.5, 10.0 * lox.dB)
modulated = link.modulate(channel, modcod, design_margin=3.0 * lox.dB)
print(f"Closes: {modulated.closes()}, margin = {float(modulated.margin):.2f} dB")
For standards-based links, use the built-in DVB-S2 table — 28 modes whose
coding chains (BBFRAME, BCH, LDPC, PLFRAME) reproduce the spectral
efficiencies and quasi-error-free thresholds of ETSI EN 302 307-1 Table 13
exactly — and ModCod.select for adaptive coding and modulation:
table = lox.ModCod.dvb_s2()
modcod = next(mc for mc in table if mc.name == "QPSK 3/4")
modulated = link.modulate(channel, modcod, design_margin=3.0 * lox.dB)
# Adaptive coding and modulation: the highest-efficiency mode that closes,
# selected and evaluated in one step (the result always closes):
best = link.modulate_best(channel, table, design_margin=3.0 * lox.dB)
print(f"{best.modcod.name}: {float(best.information_rate()) / 1e6:.1f} Mbit/s")
Budget Report
Both budget stages render as the line-item table engineers exchange —
budget_lines() returns the data as (label, value, kind) tuples and
str() renders it, with gains minus losses reproducing the C/N₀ total
exactly:
print(modulated)
# + EIRP 55.00 dB
# - Free-space path loss 181.70 dB
# - Rain attenuation 2.00 dB
# + G/T 3.01 dB
# - G/T degradation due to rain 0.99 dB
# + Boltzmann constant 228.60 dB
# = C/N0 101.93 dB
# = C/N (occupied bandwidth) 93.64 dB
# = Es/N0 34.94 dB
# = Eb/N0 34.94 dB
# - Required Eb/N0 (QPSK 1/2) 10.00 dB
# - Design margin 3.00 dB
# = Link margin 21.94 dB
For bent-pipe/relay budgets, combine per-hop C/N contributions in the
linear domain with combine_carrier_to_noise:
total = lox.combine_carrier_to_noise([uplink_c_n, downlink_c_n])
Use the component tier (configure antennas, amplifiers, receiver noise) when you need the full breakdown — for example for noise-budget allocation or detailed component trade studies.
Quick Example
An end-to-end budget for a LEO Earth-observation X-band downlink: a 500 km
satellite transmitting in the 8.025–8.4 GHz EESS band to a 3.7 m ground
station at 5° elevation. (The same scenario is available as a Rust example:
cargo run --example x_band_downlink -p lox-space.)
import lox_space as lox
eess_band = lox.FrequencyRange(8.025 * lox.GHz, 8.4 * lox.GHz)
carrier = 8.2 * lox.GHz
elevation = 5.0 * lox.deg
slant_range = lox.slant_range(elevation, 6371.0 * lox.km, 500.0 * lox.km)
# Spacecraft: 0.25 m gimballed dish, 2 W amplifier, 0.8 dB feed run
spacecraft = lox.TxChain(
lox.PatternedAntenna(pattern=lox.ParabolicPattern(0.25 * lox.m, 0.6)),
lox.AmplifierTransmitter(power=2.0 * lox.W, output_back_off=0.5 * lox.dB),
band=eess_band,
feed_loss=0.8 * lox.dB,
)
# Ground station: 3.7 m dish, Friis-cascade front end (LNA → downconverter),
# 0.3 dB feed run, 60 K clear-sky antenna noise temperature
front_end = lox.CascadeReceiver(
stages=[
lox.NoiseStage(35.0 * lox.dB, 50.0 * lox.K),
lox.NoiseStage(0.0 * lox.dB, 1540.0 * lox.K), # NF ≈ 8 dB
],
demodulator_loss=0.5 * lox.dB,
implementation_loss=0.5 * lox.dB,
)
ground_station = lox.RxChain(
lox.PatternedAntenna(pattern=lox.ParabolicPattern(3.7 * lox.m, 0.6)),
front_end,
band=eess_band,
antenna_noise_temperature=60.0 * lox.K,
feed_loss=0.3 * lox.dB,
)
# Atmospherics at X-band, 5° elevation (static values; lox-itur computes
# them from the ITU-R P-series maps)
losses = lox.PropagationLosses(
rain=1.2 * lox.dB,
gaseous=0.4 * lox.dB,
scintillation=0.3 * lox.dB,
cloud=0.1 * lox.dB,
)
# DVB-S2 QPSK 3/4 at 150 Msps; the table carries the exact Table 13
# thresholds and coding chains.
channel = lox.Channel(symbol_rate=150 * lox.MHz, roll_off=0.25)
modcod = next(mc for mc in lox.ModCod.dvb_s2() if mc.name == "QPSK 3/4")
# 2° residual pointing error on the spacecraft gimbal; the station
# autotracks on boresight. On downlinks the budget uses the rain-degraded
# G/T (ITU-R P.618 §8.2).
link = lox.LinkBudget(
spacecraft,
ground_station,
carrier=carrier,
range=slant_range,
tx_angle=2.0 * lox.deg,
losses=losses,
link_type="downlink",
)
modulated = link.modulate(channel, modcod, design_margin=3.0 * lox.dB)
print(f"EIRP: {float(link.eirp):.2f} dBW")
print(f"FSPL: {float(link.fspl):.2f} dB")
print(f"G/T: {float(link.gt):.2f} dB/K (clear sky)")
print(f"G/T: {float(link.gt_degraded):.2f} dB/K (rain)")
print(f"C/N0: {float(link.c_n0):.2f} dB·Hz")
print(f"Eb/N0: {float(modulated.eb_n0):.2f} dB")
print(f"Data rate: {float(modulated.information_rate()) / 1e6:.1f} Mbit/s")
print(f"Link margin: {float(modulated.margin):.2f} dB")
# Regulatory check: PFD on the ground vs. the RR Art. 21.16 mask
pfd = lox.power_flux_density(link.eirp, slant_range, channel.bandwidth(), 4.0 * lox.kHz)
mask = lox.PfdMask.art_21_16(-150.0 * lox.dB)
assert float(pfd) <= float(mask.value_at(elevation))
Direction-Aware Pointing
For patterned antennas the link budget can derive the pattern angles directly
from a line-of-sight vector expressed in the antenna's parent frame, using the
antenna's AntennaFrame:
import lox_space as lox
# Dish boresight along +X
frame = lox.AntennaFrame(boresight=[1.0, 0.0, 0.0], reference=[0.0, 0.0, 1.0])
antenna = lox.PatternedAntenna(
pattern=lox.ParabolicPattern(0.25 * lox.m, 0.6), frame=frame
)
spacecraft = lox.TxChain(
antenna,
lox.AmplifierTransmitter(power=2.0 * lox.W),
band=eess_band,
feed_loss=0.8 * lox.dB,
)
link = lox.LinkBudget(
spacecraft,
ground_station,
carrier=carrier,
range=slant_range,
tx_direction=[0.9, 0.1, 0.0], # line of sight in the TX parent frame
)
Working with Decibels
import lox_space as lox
# Create from dB value or linear ratio
gain = 30.0 * lox.dB
gain_linear = lox.Decibel.from_linear(1000.0)
# Arithmetic
total = gain + 3.0 * lox.dB # 33.0 dB
diff = gain - 10.0 * lox.dB # 20.0 dB
# Convert back
print(f"{float(gain)} dB = {gain.to_linear():.0f} linear")
Free-Space Path Loss
import lox_space as lox
# FSPL at 1000 km range and 29 GHz
loss = lox.fspl(distance=1000 * lox.km, frequency=29 * lox.GHz)
print(f"FSPL: {float(loss):.1f} dB")
Propagation Losses
PropagationLosses holds itemized excess-path losses as labelled lines.
total() is the carrier attenuation; absorptive() is the part that also
heats the receive antenna (rain, gaseous, cloud — used for the rain-degraded
G/T on downlinks):
import lox_space as lox
losses = lox.PropagationLosses(
rain=2.0 * lox.dB,
gaseous=0.3 * lox.dB,
other=[("Radome wetting", 0.5 * lox.dB, True)],
)
print(f"Total: {float(losses.total()):.1f} dB")
print(f"Absorptive: {float(losses.absorptive()):.1f} dB")
# Pass to LinkBudget via the losses parameter
link = lox.LinkBudget(
spacecraft,
ground_station,
carrier=carrier,
range=slant_range,
losses=losses,
)
Decibel
A value in decibels.
Parameters:
-
–valueThe value in dB.
Methods:
-
from_linear–Creates a Decibel value from a linear power ratio.
-
to_linear–Returns the linear power ratio.
Modulation
Digital modulation scheme.
Parameters:
-
–nameOne of "BPSK", "QPSK", "8PSK", "16QAM", "32QAM", "64QAM", "128QAM", "256QAM".
Methods:
-
bits_per_symbol–Returns the number of bits per symbol.
ParabolicPattern
Parabolic antenna gain pattern.
Parameters:
-
–diameterAntenna diameter as Distance.
-
–efficiencyAperture efficiency (0, 1].
Methods:
-
beamwidth–Returns the half-power beamwidth, or
Nonewhen the -
from_beamwidth–Creates a parabolic pattern from a desired beamwidth.
-
gain–Returns the gain in dBi at the given frequency and pattern angles.
-
peak_gain–Returns the peak gain in dBi.
beamwidth
Returns the half-power beamwidth, or None when the
antenna diameter is smaller than ~0.51 wavelengths at this frequency.
from_beamwidth
staticmethod
from_beamwidth(
beamwidth: Angle, frequency: Frequency, efficiency: float
) -> ParabolicPattern
gain
Returns the gain in dBi at the given frequency and pattern angles.
GaussianPattern
Gaussian antenna gain pattern.
Parameters:
-
–diameterAntenna diameter as Distance.
-
–efficiencyAperture efficiency (0, 1].
Methods:
-
beamwidth–Returns the half-power beamwidth.
-
gain–Returns the gain in dBi at the given frequency and pattern angles.
-
peak_gain–Returns the peak gain in dBi.
gain
Returns the gain in dBi at the given frequency and pattern angles.
DipolePattern
Dipole antenna gain pattern.
Parameters:
-
–lengthDipole length as Distance.
Methods:
ConstantAntenna
An antenna with constant gain.
Parameters:
-
–gainPeak gain as Decibel.
AntennaFrame
Right-handed antenna coordinate frame expressed in a parent frame.
Parameters:
-
–boresightAntenna +Z axis as [x, y, z].
-
–referenceDirection used to define the antenna +X axis after projection into the plane perpendicular to boresight.
Methods:
-
angles_for–Returns the pattern angles for a parent-frame direction vector.
-
from_boresight_and_reference–Creates an antenna frame from boresight and reference directions.
-
identity–Creates an antenna frame aligned with the parent frame.
-
x–Returns the antenna-frame +X axis in the parent frame.
-
y–Returns the antenna-frame +Y axis in the parent frame.
-
z–Returns the antenna-frame +Z axis in the parent frame.
angles_for
Returns the pattern angles for a parent-frame direction vector.
from_boresight_and_reference
staticmethod
from_boresight_and_reference(
boresight: list[float], reference: list[float]
) -> AntennaFrame
Creates an antenna frame from boresight and reference directions.
identity
staticmethod
identity() -> AntennaFrame
Creates an antenna frame aligned with the parent frame.
PatternedAntenna
An antenna with a physics-based gain pattern and antenna frame.
Parameters:
-
–patternAn antenna pattern (ParabolicPattern, GaussianPattern, or DipolePattern).
-
–frameAntenna frame defining the pattern orientation. Defaults to identity.
Methods:
-
beamwidth–Returns the half-power beamwidth, or
Nonewhen the underlying -
gain–Returns the gain in dBi at the given frequency and pattern angles.
-
gain_toward–Returns the gain in dBi toward a parent-frame direction vector.
-
peak_gain–Returns the peak gain in dBi.
beamwidth
Returns the half-power beamwidth, or None when the underlying
pattern does not define one.
gain
Returns the gain in dBi at the given frequency and pattern angles.
gain_toward
Returns the gain in dBi toward a parent-frame direction vector.
AmplifierTransmitter
A radio transmitter with an RF power amplifier.
Parameters:
-
–powerTransmit power.
-
–output_back_offOutput back-off as Decibel (default Decibel(0)).
Attributes:
-
output_back_off(Decibel) –Output back-off.
-
power(Power) –Transmit power.
NoiseTempReceiver
A receiver characterised by a single equivalent noise temperature.
The figure is referred to the receiver's input connector; the system noise temperature at the antenna flange is assembled at link-budget setup from the chain's antenna noise temperature and feed loss. For a datasheet figure that already includes antenna and feed contributions, set both chain values to zero.
Parameters:
-
–noise_temperatureEquivalent noise temperature at the input connector.
Attributes:
-
noise_temperature(Temperature) –Equivalent noise temperature referred to the receiver's input connector.
noise_temperature
property
noise_temperature: Temperature
Equivalent noise temperature referred to the receiver's input connector.
CascadeReceiver
An N-stage cascade receiver using the Friis noise formula.
Parameters:
-
–stagesNon-empty list of NoiseStage (ordered: LNA first, then downstream).
-
–demodulator_lossDemodulator loss as Decibel (default Decibel(0)).
-
–implementation_lossOther implementation losses as Decibel (default Decibel(0)).
Methods:
-
chain_gain–Returns the total RF chain gain in dB.
-
chain_noise_temperature–Returns the chain's equivalent noise temperature referred to its input connector, via the Friis formula.
-
from_lna_and_noise_figure–Creates a two-stage model: LNA followed by a receiver characterised by noise figure.
chain_noise_temperature
chain_noise_temperature() -> Temperature
Returns the chain's equivalent noise temperature referred to its input connector, via the Friis formula.
from_lna_and_noise_figure
staticmethod
from_lna_and_noise_figure(
lna_gain: Decibel,
lna_noise_temperature: Temperature,
receiver_noise_figure: Decibel,
demodulator_loss: Decibel | None = None,
implementation_loss: Decibel | None = None,
) -> CascadeReceiver
Creates a two-stage model: LNA followed by a receiver characterised by noise figure.
NoiseStage
A single stage in an RF receiver chain.
Parameters:
-
–gainStage gain as Decibel.
-
–noise_temperatureStage equivalent noise temperature.
Channel
A communication channel: the waveform's occupancy of spectrum.
Parameters:
-
–symbol_rateSymbol rate as Frequency.
-
–roll_offPulse-shaping roll-off factor (default 0.35).
-
–chip_rateChip rate for DSSS as Frequency (optional).
Methods:
-
bandwidth–Returns the occupied channel bandwidth.
-
c_n–Computes C/N from a given C/N0.
-
es_n0–Computes Es/N0 from a given C/N0.
-
processing_gain–Returns the DSSS processing gain in dB, or None for narrowband.
-
spreading_factor–Returns the DSSS spreading factor, or None for narrowband.
Attributes:
ModCod
A modulation and coding scheme with its performance threshold.
Parameters:
-
–nameName of the scheme.
-
–modulationModulation scheme.
-
–code_rateAggregate code rate in (0, 1].
-
–required_eb_n0Eb/N0 threshold as Decibel.
-
–metricError metric ("BER", "WER", "FER", or "PER"; default "BER").
-
–error_rateError rate at the threshold (default 1e-6).
Methods:
-
dvb_s2–Returns the DVB-S2 MODCOD table (normal FECFRAME, no pilots),
-
information_rate–Returns the information bit rate at the given symbol rate.
-
select–Selects the highest-efficiency MODCOD that closes at the given
Attributes:
-
code_rate(float) –Overall code rate: the product of the coding chain's rates.
-
codes(list[tuple[str, float]]) –The coding chain as (name, rate) tuples in encoding order.
-
error_rate(float) –Error rate at the threshold.
-
info_bits_per_symbol(float) –Information bits per symbol including all coding and framing overhead.
-
metric(str) –Error metric of the threshold.
-
modulation(Modulation) –Modulation scheme.
-
name(str) –Name of the scheme.
-
reference(str) –Source of the mode definition.
-
required_eb_n0(Decibel) –Required Eb/N0 threshold.
-
required_es_n0(Decibel) –Required Es/N0 threshold.
codes
property
The coding chain as (name, rate) tuples in encoding order.
info_bits_per_symbol
property
info_bits_per_symbol: float
Information bits per symbol including all coding and framing overhead.
dvb_s2
staticmethod
Returns the DVB-S2 MODCOD table (normal FECFRAME, no pilots), per ETSI EN 302 307-1 Table 13.
information_rate
Returns the information bit rate at the given symbol rate.
PropagationLosses
Itemized excess propagation losses along a link path, beyond free-space path loss.
Parameters:
-
–rainRain attenuation (optional).
-
–gaseousGaseous absorption (optional).
-
–cloudCloud attenuation (optional).
-
–scintillationScintillation loss (optional).
-
–depolarizationDepolarization loss (optional).
-
–otherCustom 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(list[tuple[str, Decibel, bool]]) –The loss lines as (label, value, absorptive) tuples, in insertion order.
lines
property
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.
LinkBudget
A modulation-agnostic link budget between two link terminals.
All outputs are bandwidth-free; use modulate to apply a waveform and
MODCOD, or the c_n/noise_power methods for ad-hoc bandwidths.
Parameters:
-
–txThe transmit terminal (TxChain or EirpModel).
-
–rxThe receive terminal (RxChain or GtModel).
-
–carrierCarrier frequency.
-
–rangeSlant range as Distance.
-
–tx_angleOff-boresight angle at transmitter as Angle (optional).
-
–rx_angleOff-boresight angle at receiver as Angle (optional).
-
–tx_directionLine-of-sight direction at transmitter as [x, y, z] (optional).
-
–rx_directionLine-of-sight direction at receiver as [x, y, z] (optional).
-
–lossesPropagationLosses (optional, defaults to none).
-
–link_type"uplink", "downlink", or "crosslink" (optional). On downlinks the budget uses the rain-degraded G/T (ITU-R P.618 §8.2).
Methods:
-
budget_lines–Returns the budget as ordered (label, value, kind) report lines,
-
c_n–Returns C/N in dB for the given noise bandwidth.
-
modulate–Applies a waveform and a MODCOD to this budget. Everything
-
modulate_best–Selects and applies the best MODCOD from a table (ACM). The
-
noise_power–Returns the noise power in dBW for the given bandwidth.
None
Attributes:
-
c_n0(Decibel) –Carrier-to-noise density ratio in dB·Hz.
-
carrier_rx_power(Decibel | None) –Received carrier power in dBW.
Nonefor lumped G/T receivers. -
eirp(Decibel) –EIRP in dBW.
-
frequency(Frequency) –Link frequency.
-
fspl(Decibel) –Free-space path loss in dB.
-
gt(Decibel) –Receiver G/T in dB/K under clear-sky conditions.
-
gt_degraded(Decibel | None) –Rain-degraded receiver G/T in dB/K.
Noneunless the link is a -
link_type(str | None) –Link direction ("uplink", "downlink", or "crosslink"), if specified.
-
slant_range(Distance) –Slant range.
carrier_rx_power
property
carrier_rx_power: Decibel | None
Received carrier power in dBW. None for lumped G/T receivers.
gt_degraded
property
gt_degraded: Decibel | None
Rain-degraded receiver G/T in dB/K. None unless the link is a
downlink with a component receive chain.
link_type
property
link_type: str | None
Link direction ("uplink", "downlink", or "crosslink"), if specified.
budget_lines
Returns the budget as ordered (label, value, kind) report lines, where kind is "gain", "loss", "subtotal", or "total".
c_n
Returns C/N in dB for the given noise bandwidth.
Raises:
-
ValueError–if the bandwidth is not finite and positive.
modulate
modulate(
channel: Channel, modcod: ModCod, design_margin: Decibel | None = None
) -> ModulatedLinkBudget
Applies a waveform and a MODCOD to this budget. Everything bandwidth-dependent derives from the channel.
modulate_best
modulate_best(
channel: Channel, table: list[ModCod], design_margin: Decibel | None = None
) -> ModulatedLinkBudget | None
Selects and applies the best MODCOD from a table (ACM). The
result always closes; None means no mode in the table closes.
noise_power
Returns the noise power in dBW for the given bandwidth. None
for lumped G/T receivers.
Raises:
-
ValueError–if the bandwidth is not finite and positive.
ModulatedLinkBudget
Link-budget output with a modulation and coding scheme applied.
Methods:
-
budget_lines–Returns the budget as ordered (label, value, kind) report lines,
-
closes–Returns whether the link closes: margin >= 0.
-
information_rate–Information bit rate: symbol rate × info bits per symbol.
-
with_interference–Computes interference statistics for a given interferer power.
Attributes:
-
budget(LinkBudget) –The underlying modulation-agnostic link budget.
-
c_n(Decibel) –C/N in dB in the channel's occupied bandwidth.
-
channel(Channel) –The waveform the link was evaluated on.
-
design_margin(Decibel) –Design margin applied on top of the MODCOD threshold.
-
eb_n0(Decibel) –Eb/N0 (energy per information bit to noise spectral density) in dB.
-
es_n0(Decibel) –Es/N0 (energy per symbol to noise spectral density) in dB.
-
margin(Decibel) –Link margin in dB.
-
modcod(ModCod) –The modulation and coding scheme the link was evaluated against.
-
symbol_rate(Frequency) –Symbol rate from the channel.
budget_lines
Returns the budget as ordered (label, value, kind) report lines, extended with C/N, Es/N0, Eb/N0, threshold, and margins.
information_rate
information_rate() -> Frequency
Information bit rate: symbol rate × info bits per symbol.
with_interference
with_interference(interference_power: Power) -> InterferenceStats
Computes interference statistics for a given interferer power.
fspl
builtin
freq_overlap
builtin
Computes the frequency overlap factor between a receiver and an interferer.
Parameters:
-
(rx_freqFrequency) –Receiver center frequency.
-
(rx_bwFrequency) –Receiver bandwidth.
-
(tx_freqFrequency) –Interferer center frequency.
-
(tx_bwFrequency) –Interferer bandwidth.
Returns:
-
float–Overlap factor in [0, 1].
power_flux_density
builtin
power_flux_density(
eirp: Decibel, distance: Distance, occupied_bw: Frequency, reference_bw: Frequency
) -> Decibel
PfdMask
A piecewise-linear PFD mask over elevation in dBW/m²/ref_bw.
The mask is linear in elevation between consecutive breakpoints and constant below the first and above the last.
Parameters:
-
–nodes(elevation, value) breakpoints with strictly ascending elevations.
Methods:
-
art_21_16–The ITU RR Article 21.16 mask shape for a given low-elevation limit.
-
nodes–Returns the mask breakpoints as (elevation, value) tuples.
-
value_at–Returns the mask value at the given elevation angle.
art_21_16
staticmethod
The ITU RR Article 21.16 mask shape for a given low-elevation limit.
Rises from start at 5° elevation by 0.5 dB per degree to start + 10 dB
at 25° and is constant outside that range.
nodes
Returns the mask breakpoints as (elevation, value) tuples.
FrequencyRange
A contiguous frequency range with inclusive bounds.
Parameters:
-
–minLower frequency bound.
-
–maxUpper frequency bound.
Methods:
-
contains–Returns whether the frequency lies within the range (bounds inclusive).
-
from_wavelengths–Creates a frequency range from wavelength bounds (e.g. optical bands).
-
max–Returns the upper frequency bound.
-
min–Returns the lower frequency bound.
contains
Returns whether the frequency lies within the range (bounds inclusive).
from_wavelengths
staticmethod
from_wavelengths(min_wavelength: Distance, max_wavelength: Distance) -> FrequencyRange
Creates a frequency range from wavelength bounds (e.g. optical bands).
TxChain
A transmit chain: an antenna fed by a transmitter.
The feed loss between transmitter output and antenna subtracts from EIRP.
Parameters:
-
–antennaConstantAntenna or PatternedAntenna.
-
–transmitterAmplifierTransmitter.
-
–bandSupported frequency range, as a FrequencyRange or an IEEE letter-band name like "Ka".
-
–feed_lossFeed loss as Decibel (default Decibel(0)).
Methods:
-
eirp_at–Returns the EIRP in dBW at the given carrier and pointing.
Attributes:
-
antenna(ConstantAntenna | PatternedAntenna) –The antenna radiating this chain.
-
band(FrequencyRange) –Supported frequency range of this chain.
-
feed_loss(Decibel) –Feed loss between transmitter output and antenna.
-
transmitter(AmplifierTransmitter) –The transmitter driving this chain.
RxChain
A receive chain: a receiver fed by an antenna.
The feed loss between antenna and receiver input is a noise contribution: it is synthesized as a passive attenuator at 290 K ahead of the receiver and referred back to the antenna flange.
Parameters:
-
–antennaConstantAntenna or PatternedAntenna.
-
–receiverNoiseTempReceiver or CascadeReceiver.
-
–bandSupported frequency range, as a FrequencyRange or an IEEE letter-band name like "Ka".
-
–antenna_noise_temperatureClear-sky antenna noise temperature at the flange.
-
–feed_lossFeed loss as Decibel (default Decibel(0)).
Methods:
-
gt_at–Returns the G/T in dB/K at the given carrier and pointing.
-
system_noise_temperature–Returns the system noise temperature referred to the antenna flange.
Attributes:
-
antenna(ConstantAntenna | PatternedAntenna) –The antenna feeding this chain.
-
antenna_noise_temperature(Temperature) –Clear-sky antenna noise temperature at the flange.
-
band(FrequencyRange) –Supported frequency range of this chain.
-
feed_loss(Decibel) –Feed loss between antenna and receiver input.
-
receiver(NoiseTempReceiver | CascadeReceiver) –The receiver terminating this chain.
antenna_noise_temperature
property
antenna_noise_temperature: Temperature
Clear-sky antenna noise temperature at the flange.
receiver
property
receiver: NoiseTempReceiver | CascadeReceiver
The receiver terminating this chain.
gt_at
gt_at(
carrier: Frequency, angle: Angle | None = None, direction: list[float] | None = None
) -> Decibel
Returns the G/T in dB/K at the given carrier and pointing.
Raises ValueError when the carrier lies outside the chain's band.
system_noise_temperature
system_noise_temperature() -> Temperature
Returns the system noise temperature referred to the antenna flange.
EirpModel
A lumped transmit terminal: an aggregate EIRP figure over a band.
Parameters:
-
–bandFrequency range over which the figure applies, as a FrequencyRange or an IEEE letter-band name like "Ka".
-
–eirpEffective isotropic radiated power as Decibel (dBW).
Methods:
-
eirp_at–Returns the EIRP in dBW at the given carrier; the pointing is ignored.
Attributes:
-
band(FrequencyRange) –Frequency range over which the figure applies.
-
eirp(Decibel) –Effective isotropic radiated power in dBW.
GtModel
A lumped receive terminal: an aggregate G/T figure over a band.
The absolute gain and noise temperature are not recoverable from a G/T figure, so links using a GtModel carry no absolute carrier or noise powers.
Parameters:
-
–bandFrequency range over which the figure applies, as a FrequencyRange or an IEEE letter-band name like "Ka".
-
–gtGain-to-noise-temperature ratio as Decibel (dB/K).
Methods:
-
gt_at–Returns the G/T in dB/K at the given carrier; the pointing is ignored.
Attributes:
-
band(FrequencyRange) –Frequency range over which the figure applies.
-
gt(Decibel) –Gain-to-noise-temperature ratio in dB/K.