Skip to content

linkbudget.fom

fom

fom.py

Standard link-budget figures of merit, as pure functions working in the conventional decibel-domain units used in link budgets (dBW, dBi, dB/K, dB-Hz). These are the building blocks used by LinkContainer.summary() but are handy on their own.

eirp_dbw

eirp_dbw(tx_power_dbw: float, tx_antenna_gain_dbi: float, tx_loss_db: float = 0.0) -> float

Effective isotropic radiated power (dBW).

Source code in linkbudget/fom.py
def eirp_dbw(tx_power_dbw: float, tx_antenna_gain_dbi: float,
             tx_loss_db: float = 0.0) -> float:
    """Effective isotropic radiated power (dBW)."""
    return tx_power_dbw + tx_antenna_gain_dbi - tx_loss_db

g_over_t_db

g_over_t_db(rx_antenna_gain_dbi: float, system_noise_temp_k: float) -> float

Receiver figure of merit G/T (dB/K).

Source code in linkbudget/fom.py
def g_over_t_db(rx_antenna_gain_dbi: float, system_noise_temp_k: float) -> float:
    """Receiver figure of merit G/T (dB/K)."""
    return rx_antenna_gain_dbi - convert.linear_to_db(system_noise_temp_k)

noise_figure_to_temp_k

noise_figure_to_temp_k(noise_figure_db: float, reference_temp_k: float = convert.REFERENCE_NOISE_TEMP_K) -> float

Equivalent noise temperature (K) of a stage with the given noise figure: T_e = (F - 1) * T0.

Source code in linkbudget/fom.py
def noise_figure_to_temp_k(noise_figure_db: float,
                           reference_temp_k: float = convert.REFERENCE_NOISE_TEMP_K) -> float:
    """Equivalent noise temperature (K) of a stage with the given noise figure:
    ``T_e = (F - 1) * T0``."""
    return (convert.db_to_linear(noise_figure_db) - 1.0) * reference_temp_k

noise_temp_to_figure_db

noise_temp_to_figure_db(noise_temp_k: float, reference_temp_k: float = convert.REFERENCE_NOISE_TEMP_K) -> float

Noise figure (dB) equivalent to an excess noise temperature T_e: F = 1 + T_e / T0.

Source code in linkbudget/fom.py
def noise_temp_to_figure_db(noise_temp_k: float,
                            reference_temp_k: float = convert.REFERENCE_NOISE_TEMP_K) -> float:
    """Noise figure (dB) equivalent to an excess noise temperature ``T_e``:
    ``F = 1 + T_e / T0``."""
    return convert.linear_to_db(1.0 + noise_temp_k / reference_temp_k)

friis_total_noise_temp_k

friis_total_noise_temp_k(stage_noise_temps_k: Sequence[float], stage_gains_db: Sequence[float]) -> float

Total noise temperature (K) of a cascade, referred to its input, from Friis: T = T1 + T2/G1 + T3/(G1 G2) + ....

stage_gains_db[i] is the available power gain (dB) of stage i; the last stage's gain is not used. Both sequences must be the same length.

Source code in linkbudget/fom.py
def friis_total_noise_temp_k(stage_noise_temps_k: Sequence[float],
                             stage_gains_db: Sequence[float]) -> float:
    """Total noise temperature (K) of a cascade, referred to its input, from
    Friis: ``T = T1 + T2/G1 + T3/(G1 G2) + ...``.

    ``stage_gains_db[i]`` is the available power gain (dB) of stage ``i``; the
    last stage's gain is not used.  Both sequences must be the same length.
    """
    if len(stage_noise_temps_k) != len(stage_gains_db):
        raise ValueError("stage_noise_temps_k and stage_gains_db must match in length")
    total = 0.0
    gain_before = 1.0
    for temp_k, gain_db in zip(stage_noise_temps_k, stage_gains_db):
        total += temp_k / gain_before
        gain_before *= convert.db_to_linear(gain_db)
    return total

friis_total_noise_figure_db

friis_total_noise_figure_db(stage_noise_figures_db: Sequence[float], stage_gains_db: Sequence[float]) -> float

Total noise figure (dB) of a cascade from Friis: F = F1 + (F2-1)/G1 + (F3-1)/(G1 G2) + ....

Source code in linkbudget/fom.py
def friis_total_noise_figure_db(stage_noise_figures_db: Sequence[float],
                                stage_gains_db: Sequence[float]) -> float:
    """Total noise figure (dB) of a cascade from Friis:
    ``F = F1 + (F2-1)/G1 + (F3-1)/(G1 G2) + ...``."""
    temps = [noise_figure_to_temp_k(nf) for nf in stage_noise_figures_db]
    return noise_temp_to_figure_db(friis_total_noise_temp_k(temps, stage_gains_db))

free_space_path_loss_db

free_space_path_loss_db(distance_m: float, frequency_hz: float) -> float

Free-space path loss (dB) as a positive number.

Source code in linkbudget/fom.py
def free_space_path_loss_db(distance_m: float, frequency_hz: float) -> float:
    """Free-space path loss (dB) as a positive number."""
    wavelength = convert.SPEED_OF_LIGHT / frequency_hz
    return convert.linear_to_db((4.0 * math.pi * distance_m / wavelength) ** 2)

cn0_dbhz

cn0_dbhz(eirp: float, g_over_t: float, path_loss_db: float, extra_loss_db: float = 0.0) -> float

Carrier-to-noise-density ratio C/N0 (dB-Hz) from the classic link equation C/N0 = EIRP + G/T - L_path - L_extra - k (with k Boltzmann's constant in dBW/K/Hz).

Source code in linkbudget/fom.py
def cn0_dbhz(eirp: float, g_over_t: float, path_loss_db: float,
             extra_loss_db: float = 0.0) -> float:
    """Carrier-to-noise-density ratio C/N0 (dB-Hz) from the classic link
    equation ``C/N0 = EIRP + G/T - L_path - L_extra - k`` (with k Boltzmann's
    constant in dBW/K/Hz)."""
    boltzmann_db = convert.linear_to_db(convert.BOLTZMANN_CONSTANT)
    return eirp + g_over_t - path_loss_db - extra_loss_db - boltzmann_db

cn0_from_snr

cn0_from_snr(snr_db: float, noise_bandwidth_hz: float) -> float

C/N0 (dB-Hz) from a carrier-to-noise ratio measured in a given noise bandwidth.

Source code in linkbudget/fom.py
def cn0_from_snr(snr_db: float, noise_bandwidth_hz: float) -> float:
    """C/N0 (dB-Hz) from a carrier-to-noise ratio measured in a given noise
    bandwidth."""
    return snr_db + convert.linear_to_db(noise_bandwidth_hz)

cn_db

cn_db(cn0: float, noise_bandwidth_hz: float) -> float

Carrier-to-noise ratio C/N (dB) in a given noise bandwidth.

Source code in linkbudget/fom.py
def cn_db(cn0: float, noise_bandwidth_hz: float) -> float:
    """Carrier-to-noise ratio C/N (dB) in a given noise bandwidth."""
    return cn0 - convert.linear_to_db(noise_bandwidth_hz)

ebno_db

ebno_db(cn0: float, data_rate_bps: float) -> float

Energy-per-bit to noise-density ratio Eb/N0 (dB).

Source code in linkbudget/fom.py
def ebno_db(cn0: float, data_rate_bps: float) -> float:
    """Energy-per-bit to noise-density ratio Eb/N0 (dB)."""
    return cn0 - convert.linear_to_db(data_rate_bps)

esno_db

esno_db(cn0: float, symbol_rate_bd: float) -> float

Energy-per-symbol to noise-density ratio Es/N0 (dB).

Source code in linkbudget/fom.py
def esno_db(cn0: float, symbol_rate_bd: float) -> float:
    """Energy-per-symbol to noise-density ratio Es/N0 (dB)."""
    return cn0 - convert.linear_to_db(symbol_rate_bd)

shannon_capacity_bps

shannon_capacity_bps(bandwidth_hz: float, snr_linear: float) -> float

Shannon-Hartley channel capacity (bits/s).

Source code in linkbudget/fom.py
def shannon_capacity_bps(bandwidth_hz: float, snr_linear: float) -> float:
    """Shannon-Hartley channel capacity (bits/s)."""
    return bandwidth_hz * math.log2(1.0 + snr_linear)

spectral_efficiency

spectral_efficiency(data_rate_bps: float, bandwidth_hz: float) -> float

Spectral efficiency (bits/s/Hz).

Source code in linkbudget/fom.py
def spectral_efficiency(data_rate_bps: float, bandwidth_hz: float) -> float:
    """Spectral efficiency (bits/s/Hz)."""
    return data_rate_bps / bandwidth_hz