Building a budget¶
This walk-through builds a small point-to-point microwave link from scratch.
1. Create the container¶
Give it the context the figures of merit need — a noise bandwidth and a data rate — up front:
import linkbudget
budget = linkbudget.LinkContainer(
carrier_frequency=6e9,
noise_bandwidth=20e6,
data_rate=45e6,
)
2. Add the transmit side¶
A SignalSource injects power into
the chain; a Gain applies the transmit
antenna gain.
budget.add_component(linkbudget.SignalSource(
"Transmitter", "1 W (0 dBW) at the PA output", signal_power=1.0))
budget.add_component(linkbudget.Gain(
"Tx antenna", "36 dBi dish", gain=36.0, role="tx"))
3. Add the path¶
FreeSpacePathLoss is tagged as a propagation stage, so the signal power
entering it becomes the budget's EIRP.
budget.add_component(linkbudget.FreeSpacePathLoss(
"Free-space path loss", "12 km hop", distance=12e3, frequency=6e9))
4. Add the receive side¶
Mark the receive antenna with role="rx" so summary() can compute G/T.
ThermalNoise establishes the noise floor (k·T·B in watts — so every
power value in this budget is in watts); RFComponent is the LNA.
budget.add_component(linkbudget.Gain(
"Rx antenna", "36 dBi dish", gain=36.0, role="rx"))
budget.add_component(linkbudget.ThermalNoise(
"Noise floor", "290 K system temperature",
temperature_k=290.0, bandwidth=20e6))
budget.add_component(linkbudget.RFComponent(
"LNA", "low-noise amplifier", gain=30.0, noise_figure=1.5))
5. State the requirement¶
A LinkMargin stage compares the achieved
link against a demodulator threshold. It passes signal and noise through
unchanged — it only annotates the result.
budget.add_component(linkbudget.LinkMargin(
"Link margin", "64-QAM, required Eb/N0 = 15 dB",
required_ebno_db=15.0, noise_bandwidth=20e6, data_rate=45e6,
implementation_loss_db=2.0))
6. Read the result¶
summary = budget.summary()
print(summary)
if summary.closes:
print(f"link closes with {summary.margin_db:.1f} dB of margin")
summary is a BudgetSummary — every
field is also available programmatically (summary.eirp_dbw,
summary.g_over_t_db, summary.ebno_db, …) and as a dict via
summary.as_dict().
7. Publish reports¶
budget.add_publisher(linkbudget.HTMLPublisher("link.html", title="6 GHz hop"))
budget.add_publisher(linkbudget.PDFPublisher("link.pdf", title="6 GHz hop"))
budget.add_publisher(linkbudget.WaterfallPublisher("link.png"))
budget.publish()
Inspecting individual stages¶
After compute() (or publish() / summary()), budget.data_list holds
one dict per stage: