feat: add interactive exploration of Shannon's capacity formula with Plotly graphs
All checks were successful
Build & Deploy Shannon / 🏗️ Build & Deploy Shannon (push) Successful in 3m1s
All checks were successful
Build & Deploy Shannon / 🏗️ Build & Deploy Shannon (push) Successful in 3m1s
- Implemented bandwidth sensitivity and power sensitivity plots. - Created a contour map for bit rate multiplying factors. - Added input parameters for C/N and bandwidth with validation. - Displayed computed results and sensitivity analysis metrics. - Integrated interactive graphs for user exploration. - Included background information section for user guidance.
This commit is contained in:
0
core/__init__.py
Normal file
0
core/__init__.py
Normal file
BIN
core/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
core/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/calculations.cpython-313.pyc
Normal file
BIN
core/__pycache__/calculations.cpython-313.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/database.cpython-313.pyc
Normal file
BIN
core/__pycache__/database.cpython-313.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/help_texts.cpython-313.pyc
Normal file
BIN
core/__pycache__/help_texts.cpython-313.pyc
Normal file
Binary file not shown.
280
core/calculations.py
Normal file
280
core/calculations.py
Normal file
@@ -0,0 +1,280 @@
|
||||
"""
|
||||
Shannon Equation - Core Calculations Module
|
||||
|
||||
All scientific computation functions extracted from the original Shannon.py.
|
||||
These are pure functions with no UI dependency.
|
||||
"""
|
||||
|
||||
from math import log, pi, sqrt, cos, acos, atan
|
||||
import numpy as np
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Fundamental Shannon Functions
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
def combine_cnr(*cnr_values: float) -> float:
|
||||
"""Combine multiple Carrier-to-Noise Ratios (in dB) into one equivalent C/N.
|
||||
|
||||
Uses the summation of normalized noise variances:
|
||||
1/CNR_total = sum(1/CNR_i)
|
||||
"""
|
||||
ncr_linear = 0.0
|
||||
for cnr_db in cnr_values:
|
||||
ncr_linear += 10 ** (-cnr_db / 10)
|
||||
return -10 * log(ncr_linear, 10)
|
||||
|
||||
|
||||
def shannon_capacity(bw: float = 36.0, cnr: float = 10.0, penalty: float = 0.0) -> float:
|
||||
"""Shannon channel capacity (bit rate in Mbps).
|
||||
|
||||
Args:
|
||||
bw: Bandwidth in MHz.
|
||||
cnr: Carrier-to-Noise Ratio in dB.
|
||||
penalty: Implementation penalty in dB.
|
||||
"""
|
||||
cnr_linear = 10 ** ((cnr - penalty) / 10)
|
||||
return bw * log(1 + cnr_linear, 2)
|
||||
|
||||
|
||||
def br_multiplier(bw_mul: float = 1.0, p_mul: float = 2.0, cnr: float = 10.0) -> float:
|
||||
"""Bit Rate multiplying factor when BW and Power are scaled."""
|
||||
cnr_linear = 10 ** (cnr / 10)
|
||||
return bw_mul * log(1 + cnr_linear * p_mul / bw_mul, 2) / log(1 + cnr_linear, 2)
|
||||
|
||||
|
||||
def shannon_points(bw: float = 36.0, cnr: float = 10.0):
|
||||
"""Compute key Shannon operating points.
|
||||
|
||||
Returns:
|
||||
(cnr_linear, br_infinity, c_n0, br_constrained)
|
||||
"""
|
||||
cnr_linear = 10 ** (cnr / 10)
|
||||
c_n0 = cnr_linear * bw
|
||||
br_infinity = c_n0 / log(2)
|
||||
br_constrained = shannon_capacity(bw, cnr)
|
||||
return cnr_linear, br_infinity, c_n0, br_constrained
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Satellite Link Budget Calculations
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
def compute_satellite_link(
|
||||
freq_ghz: float,
|
||||
hpa_power_w: float,
|
||||
sat_loss_db: float,
|
||||
sat_cir_list: list[float],
|
||||
sat_beam_deg: float,
|
||||
gain_offset_db: float,
|
||||
sat_alt_km: float,
|
||||
sat_lat: float,
|
||||
sat_lon: float,
|
||||
gs_lat: float,
|
||||
gs_lon: float,
|
||||
availability_pct: float,
|
||||
) -> dict:
|
||||
"""Compute all satellite link parameters.
|
||||
|
||||
Returns a dict with all computed values.
|
||||
"""
|
||||
import itur
|
||||
|
||||
R_EARTH = 6378 # km
|
||||
SAT_ANT_EFF = 0.65
|
||||
|
||||
# Signal power after losses
|
||||
sig_power = hpa_power_w * 10 ** (-sat_loss_db / 10)
|
||||
|
||||
# Satellite antenna
|
||||
wavelength = 300e6 / freq_ghz / 1e9 # meters
|
||||
sat_gain_linear = SAT_ANT_EFF * (pi * 70 / sat_beam_deg) ** 2
|
||||
sat_gain_linear *= 10 ** (-gain_offset_db / 10)
|
||||
|
||||
# EIRP
|
||||
eirp_linear = sig_power * sat_gain_linear
|
||||
|
||||
# Satellite C/I
|
||||
sat_cir = combine_cnr(*sat_cir_list)
|
||||
|
||||
# Path geometry
|
||||
path_length = sqrt(
|
||||
sat_alt_km ** 2
|
||||
+ 2 * R_EARTH * (R_EARTH + sat_alt_km)
|
||||
* (1 - cos(np.radians(sat_lat - gs_lat)) * cos(np.radians(sat_lon - gs_lon)))
|
||||
)
|
||||
|
||||
phi = acos(cos(np.radians(sat_lat - gs_lat)) * cos(np.radians(sat_lon - gs_lon)))
|
||||
if phi > 0:
|
||||
elevation = float(np.degrees(
|
||||
atan((cos(phi) - R_EARTH / (R_EARTH + sat_alt_km)) / sqrt(1 - cos(phi) ** 2))
|
||||
))
|
||||
else:
|
||||
elevation = 90.0
|
||||
|
||||
# Atmospheric attenuation
|
||||
if elevation <= 0:
|
||||
atm_loss_db = 999.0
|
||||
else:
|
||||
atm_loss_db = float(
|
||||
itur.atmospheric_attenuation_slant_path(
|
||||
gs_lat, gs_lon, freq_ghz, elevation, 100 - availability_pct, 1
|
||||
).value
|
||||
)
|
||||
|
||||
# Path dispersion
|
||||
path_loss_linear = 4 * pi * (path_length * 1000) ** 2
|
||||
free_space_loss_linear = (4 * pi * path_length * 1000 / wavelength) ** 2
|
||||
|
||||
# PFD
|
||||
pfd_linear = eirp_linear / path_loss_linear * 10 ** (-atm_loss_db / 10)
|
||||
|
||||
return {
|
||||
"sig_power": sig_power,
|
||||
"wavelength": wavelength,
|
||||
"sat_gain_linear": sat_gain_linear,
|
||||
"eirp_linear": eirp_linear,
|
||||
"sat_cir": sat_cir,
|
||||
"path_length": path_length,
|
||||
"elevation": elevation,
|
||||
"atm_loss_db": atm_loss_db,
|
||||
"path_loss_linear": path_loss_linear,
|
||||
"free_space_loss_linear": free_space_loss_linear,
|
||||
"pfd_linear": pfd_linear,
|
||||
}
|
||||
|
||||
|
||||
def compute_receiver(
|
||||
pfd_linear: float,
|
||||
atm_loss_db: float,
|
||||
wavelength: float,
|
||||
cpe_ant_d: float,
|
||||
cpe_t_clear: float,
|
||||
) -> dict:
|
||||
"""Compute receiver-side parameters."""
|
||||
CPE_ANT_EFF = 0.6
|
||||
K_BOLTZ = 1.38e-23 # J/K
|
||||
|
||||
cpe_t_att = (cpe_t_clear - 40) + 40 * 10 ** (-atm_loss_db / 10) + 290 * (1 - 10 ** (-atm_loss_db / 10))
|
||||
|
||||
cpe_ae = pi * cpe_ant_d ** 2 / 4 * CPE_ANT_EFF
|
||||
cpe_gain_linear = (pi * cpe_ant_d / wavelength) ** 2 * CPE_ANT_EFF
|
||||
cpe_g_t = 10 * log(cpe_gain_linear / cpe_t_att, 10)
|
||||
|
||||
rx_power = pfd_linear * cpe_ae
|
||||
n0 = K_BOLTZ * cpe_t_att
|
||||
c_n0_hz = rx_power / n0
|
||||
c_n0_mhz = c_n0_hz / 1e6
|
||||
|
||||
br_infinity = c_n0_mhz / log(2)
|
||||
|
||||
# Spectral efficiency points
|
||||
bw_spe_1 = c_n0_mhz
|
||||
bw_spe_double = c_n0_mhz / (2 ** 2 - 1)
|
||||
|
||||
br_spe_1 = bw_spe_1
|
||||
br_spe_double = bw_spe_double * 2
|
||||
|
||||
return {
|
||||
"cpe_ae": cpe_ae,
|
||||
"cpe_gain_linear": cpe_gain_linear,
|
||||
"cpe_g_t": cpe_g_t,
|
||||
"cpe_t_att": cpe_t_att,
|
||||
"rx_power": rx_power,
|
||||
"n0": n0,
|
||||
"c_n0_hz": c_n0_hz,
|
||||
"c_n0_mhz": c_n0_mhz,
|
||||
"br_infinity": br_infinity,
|
||||
"bw_spe_1": bw_spe_1,
|
||||
"br_spe_1": br_spe_1,
|
||||
"br_spe_double": br_spe_double,
|
||||
}
|
||||
|
||||
|
||||
def compute_baseband(
|
||||
c_n0_mhz: float,
|
||||
br_infinity: float,
|
||||
bw_spe_1: float,
|
||||
sat_cir: float,
|
||||
bandwidth: float,
|
||||
rolloff: float,
|
||||
overheads: float,
|
||||
cnr_imp_list: list[float],
|
||||
penalties: float,
|
||||
) -> dict:
|
||||
"""Compute baseband processing results."""
|
||||
cnr_imp = combine_cnr(*cnr_imp_list)
|
||||
|
||||
cnr_spe_1 = 0.0 # dB
|
||||
cnr_bw = cnr_spe_1 + 10 * log(bw_spe_1 / bandwidth, 10)
|
||||
bw_nyq = bandwidth / (1 + rolloff / 100)
|
||||
cnr_nyq = cnr_spe_1 + 10 * log(bw_spe_1 / bw_nyq, 10)
|
||||
cnr_rcv = combine_cnr(cnr_nyq, cnr_imp, sat_cir)
|
||||
|
||||
br_nyq = shannon_capacity(bw_nyq, cnr_nyq)
|
||||
br_rcv = shannon_capacity(bw_nyq, cnr_rcv, penalties)
|
||||
br_rcv_higher = br_rcv / (1 + overheads / 100)
|
||||
|
||||
spe_nyq = br_nyq / bandwidth
|
||||
bits_per_symbol = br_nyq / bw_nyq
|
||||
spe_rcv = br_rcv / bandwidth
|
||||
spe_higher = br_rcv_higher / bandwidth
|
||||
|
||||
return {
|
||||
"cnr_bw": cnr_bw,
|
||||
"cnr_nyq": cnr_nyq,
|
||||
"cnr_rcv": cnr_rcv,
|
||||
"cnr_imp": cnr_imp,
|
||||
"bw_nyq": bw_nyq,
|
||||
"br_nyq": br_nyq,
|
||||
"br_rcv": br_rcv,
|
||||
"br_rcv_higher": br_rcv_higher,
|
||||
"br_nyq_norm": br_nyq / br_infinity,
|
||||
"br_rcv_norm": br_rcv / br_infinity,
|
||||
"br_rcv_h_norm": br_rcv_higher / br_infinity,
|
||||
"spe_nyq": spe_nyq,
|
||||
"bits_per_symbol": bits_per_symbol,
|
||||
"spe_rcv": spe_rcv,
|
||||
"spe_higher": spe_higher,
|
||||
"bandwidth": bandwidth,
|
||||
"rolloff": rolloff,
|
||||
"overheads": overheads,
|
||||
"penalties": penalties,
|
||||
}
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Formatting Helpers
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
def fmt_br(br: float) -> str:
|
||||
return f"{br:.1f} Mbps"
|
||||
|
||||
|
||||
def fmt_power(p: float) -> str:
|
||||
p_db = 10 * log(p, 10)
|
||||
if 1 < p < 1e4:
|
||||
return f"{p:.1f} W · {p_db:.1f} dBW"
|
||||
elif 1e-3 < p <= 1:
|
||||
return f"{p:.4f} W · {p_db:.1f} dBW"
|
||||
else:
|
||||
return f"{p:.1e} W · {p_db:.1f} dBW"
|
||||
|
||||
|
||||
def fmt_pfd(p: float) -> str:
|
||||
p_db = 10 * log(p, 10)
|
||||
return f"{p:.1e} W/m² · {p_db:.1f} dBW/m²"
|
||||
|
||||
|
||||
def fmt_psd(p: float) -> str:
|
||||
p_db = 10 * log(p, 10)
|
||||
return f"{p:.1e} W/MHz · {p_db:.1f} dBW/MHz"
|
||||
|
||||
|
||||
def fmt_gain(g: float) -> str:
|
||||
g_db = 10 * log(g, 10)
|
||||
return f"{g:.1f} · {g_db:.1f} dBi"
|
||||
|
||||
|
||||
def fmt_ploss(loss: float) -> str:
|
||||
loss_db = 10 * log(loss, 10)
|
||||
return f"{loss:.2e} m² · {loss_db:.1f} dBm²"
|
||||
107
core/database.py
Normal file
107
core/database.py
Normal file
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
Database module for managing user contributions.
|
||||
|
||||
Uses parameterized queries (no SQL injection) and context managers.
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
DB_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data")
|
||||
|
||||
|
||||
def _get_db_path(db_name: str) -> str:
|
||||
os.makedirs(DB_DIR, exist_ok=True)
|
||||
return os.path.join(DB_DIR, db_name)
|
||||
|
||||
|
||||
def _init_db(db_path: str):
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
conn.execute(
|
||||
"""CREATE TABLE IF NOT EXISTS contributions (
|
||||
num INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
keywords TEXT,
|
||||
text TEXT NOT NULL,
|
||||
date TEXT NOT NULL,
|
||||
password TEXT DEFAULT ''
|
||||
)"""
|
||||
)
|
||||
|
||||
|
||||
def write_contribution(
|
||||
db_name: str, name: str, title: str, keywords: str, text: str, password: str = ""
|
||||
) -> int:
|
||||
"""Write a new contribution. Returns the new contribution ID."""
|
||||
db_path = _get_db_path(db_name)
|
||||
_init_db(db_path)
|
||||
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("SELECT COALESCE(MAX(num), 0) FROM contributions")
|
||||
next_id = cursor.fetchone()[0] + 1
|
||||
|
||||
cursor.execute(
|
||||
"INSERT INTO contributions (num, name, title, keywords, text, date, password) "
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
(next_id, name, title, keywords, text, datetime.now().strftime("%Y-%m-%d"), password),
|
||||
)
|
||||
return next_id
|
||||
|
||||
|
||||
def search_contributions(
|
||||
db_name: str,
|
||||
name_filter: str = "",
|
||||
title_filter: str = "",
|
||||
keywords_filter: str = "",
|
||||
content_filter: str = "",
|
||||
limit: int = 50,
|
||||
) -> list[dict]:
|
||||
"""Search contributions with optional filters. Returns list of dicts."""
|
||||
db_path = _get_db_path(db_name)
|
||||
if not os.path.isfile(db_path):
|
||||
return []
|
||||
|
||||
_init_db(db_path)
|
||||
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"""SELECT num, name, title, keywords, text, date, password
|
||||
FROM contributions
|
||||
WHERE name LIKE ? AND title LIKE ? AND keywords LIKE ? AND text LIKE ?
|
||||
ORDER BY num DESC
|
||||
LIMIT ?""",
|
||||
(
|
||||
f"%{name_filter}%",
|
||||
f"%{title_filter}%",
|
||||
f"%{keywords_filter}%",
|
||||
f"%{content_filter}%",
|
||||
limit,
|
||||
),
|
||||
)
|
||||
return [dict(row) for row in cursor.fetchall()]
|
||||
|
||||
|
||||
def delete_contribution(db_name: str, num: int, password: str) -> bool:
|
||||
"""Delete a contribution if the password matches. Returns True on success."""
|
||||
db_path = _get_db_path(db_name)
|
||||
if not os.path.isfile(db_path):
|
||||
return False
|
||||
|
||||
with sqlite3.connect(db_path) as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"SELECT password FROM contributions WHERE num = ?", (num,)
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
if row is None:
|
||||
return False
|
||||
if row[0] != password:
|
||||
return False
|
||||
cursor.execute("DELETE FROM contributions WHERE num = ?", (num,))
|
||||
return True
|
||||
297
core/help_texts.py
Normal file
297
core/help_texts.py
Normal file
@@ -0,0 +1,297 @@
|
||||
"""
|
||||
Help texts for Shannon application.
|
||||
|
||||
Cleaned-up version of Shannon_Dict.py, organized by section.
|
||||
Unicode subscripts/superscripts replaced by readable equivalents for web display.
|
||||
"""
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Panel 1: Theoretical Exploration
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
THEORY_HELP = {
|
||||
"cnr": (
|
||||
"**Reference C/N [dB]**\n\n"
|
||||
"Reference Carrier to Noise Ratio in decibels: 10·log(C/N), where C is the "
|
||||
"Carrier's power and N is the Noise's Power, both measured in the reference "
|
||||
"Channel Bandwidth.\n\n"
|
||||
"The Carrier's power is often named Signal's Power and the Carrier to Noise Ratio "
|
||||
"is often named Signal to Noise Ratio."
|
||||
),
|
||||
"bw": (
|
||||
"**Reference BW [MHz]**\n\n"
|
||||
"Reference Channel Bandwidth — a key parameter of the communication channel.\n\n"
|
||||
"This bandwidth is usually a degree of freedom of the system design, eventually "
|
||||
"constrained by technological constraints and various kinds of frequency usage regulations."
|
||||
),
|
||||
"c_n0": (
|
||||
"**Carrier Power to Noise Power Density Ratio: C/N₀**\n\n"
|
||||
"Carrier's power (in Watts) divided by the Noise Spectral Power Density "
|
||||
"(in Watts per MHz). The result's units are MHz."
|
||||
),
|
||||
"br_inf": (
|
||||
"**Theoretical BR at infinite BW: 1.44·C/N₀**\n\n"
|
||||
"Bit Rate theoretically achievable when the signal occupies an infinite Bandwidth. "
|
||||
"This value is a useful asymptotic limit."
|
||||
),
|
||||
"br_unit": (
|
||||
"**Theoretical BR at Spectral Efficiency = 1: C/N₀**\n\n"
|
||||
"Bit Rate theoretically achievable at a Spectral Efficiency = 1: "
|
||||
"Bit Rate in Mbps = Bandwidth in MHz.\n\n"
|
||||
"The corresponding value, deduced from Shannon's formula, is given by C/N₀."
|
||||
),
|
||||
"br_bw": (
|
||||
"**Theoretical BR at Reference (BW, C/N)**\n\n"
|
||||
"Bit Rate theoretically achievable when the Bandwidth is constrained "
|
||||
"to the given reference value."
|
||||
),
|
||||
"cnr_lin": (
|
||||
"**C/N = C / (N₀·B)**\n\n"
|
||||
"Reference Carrier to Noise Ratio (or Signal to Noise Ratio). "
|
||||
"The C/N Ratio is usually given in dB: 10·log(C/N).\n\n"
|
||||
"Although the logarithm is convenient for many evaluations (multiplications become additions), "
|
||||
"it's also good to consider the ratio itself (Linear Format) to get some physical sense "
|
||||
"of the power ratio.\n\n"
|
||||
"The Carrier to Noise Ratio in linear format is the value used in Shannon's formula."
|
||||
),
|
||||
"br_mul": (
|
||||
"**Bit Rate Increase Factor**\n\n"
|
||||
"Bit Rate multiplying factor achieved when the Bandwidth and the Power "
|
||||
"are multiplied by a given set of values."
|
||||
),
|
||||
"bw_mul": (
|
||||
"**BW Increase Factor**\n\n"
|
||||
"Arbitrary multiplying factor applied to the Carrier's Bandwidth, for sensitivity analysis."
|
||||
),
|
||||
"p_mul": (
|
||||
"**Power Increase Factor**\n\n"
|
||||
"Arbitrary multiplying factor applied to the Carrier's Power, for sensitivity analysis."
|
||||
),
|
||||
"shannon": (
|
||||
"**The Shannon Limit** allows to evaluate the theoretical capacity achievable over "
|
||||
"a communication channel.\n\n"
|
||||
"As a true genius, Claude Shannon founded communication theory, information theory "
|
||||
"and more (click the Wikipedia button for more info).\n\n"
|
||||
"This equation is fundamental for the evaluation of communication systems. "
|
||||
"It is an apparently simple but extremely powerful tool to guide communication systems' designs.\n\n"
|
||||
"This equation tells us what is achievable, not how to achieve it. It took almost 50 years "
|
||||
"to approach this limit with the invention of Turbo codes.\n\n"
|
||||
"In the satellite domain, DVB-S2x, using LDPC codes iteratively decoded (Turbo-Like), "
|
||||
"is only 1 dB away from this limit."
|
||||
),
|
||||
"advanced": (
|
||||
"**AWGN Channel Model**\n\n"
|
||||
"The model assumes that the communication channel is **AWGN** (Additive White Gaussian Noise). "
|
||||
"This noise is supposed to be random and white, meaning noise at a given time is independent "
|
||||
"of noise at any other time — implying a flat and infinite spectrum. "
|
||||
"This noise is also supposed to be Gaussian.\n\n"
|
||||
"Although these assumptions seem very strong, they accurately match the cases of interest. "
|
||||
"Many impairments are actually non-linear and/or non-additive, but combining equivalent C/N "
|
||||
"of all impairments as if they were fully AWGN is in most cases very accurate. "
|
||||
"The reason is that the sum of random variables of unknown laws always tends to Gaussian, "
|
||||
"and thermal noise is dominating, actually white and gaussian, and whitening the rest.\n\n"
|
||||
"The tool accepts lists of comma-separated CNRs which will be combined in that way.\n\n"
|
||||
"Overall, the Shannon Limit is a pretty convenient tool to predict the real performances "
|
||||
"of communication systems."
|
||||
),
|
||||
"help": (
|
||||
"**Recommendations for using the tool**\n\n"
|
||||
"The first purpose of the tool is educational, allowing people to better understand "
|
||||
"the physics of communications and the role of key parameters.\n\n"
|
||||
"- Try multiple values in all the fields one by one\n"
|
||||
"- Explore the graphs and try to understand the underlying physics\n"
|
||||
"- The units are as explicit as possible to facilitate the exploration\n"
|
||||
"- Click on the ℹ️ icons to get information about each parameter"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
# Panel 2: Real World (Satellite Link Budget)
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
REAL_WORLD_HELP = {
|
||||
"freq": (
|
||||
"**Frequency [GHz]**\n\n"
|
||||
"Frequency of the electromagnetic wave supporting the communication.\n\n"
|
||||
"For satellite downlink, typical bands: L: 1.5 GHz, S: 2.2 GHz, C: 4 GHz, "
|
||||
"Ku: 12 GHz, Ka: 19 GHz, Q: 40 GHz"
|
||||
),
|
||||
"sat_alt": (
|
||||
"**Satellite Altitude [km]**\n\n"
|
||||
"The position of the satellite is expressed in latitude, longitude, altitude. "
|
||||
"A GEO satellite has a latitude of 0° and an altitude of 35786 km. "
|
||||
"LEO satellites have altitudes lower than 2000 km. "
|
||||
"MEO altitudes are between LEO and GEO (O3B constellation: 8063 km)."
|
||||
),
|
||||
"sat_latlon": (
|
||||
"**Satellite Latitude and Longitude [°]**\n\n"
|
||||
"The program doesn't simulate the orbit — any satellite coordinates can be used. "
|
||||
"A GEO satellite has a latitude of 0°."
|
||||
),
|
||||
"gs_latlon": (
|
||||
"**Ground Station Lat, Lon [°]**\n\n"
|
||||
"The position of the ground station affects link availability due to weather statistics "
|
||||
"(tropical regions have very heavy rains attenuating signals at high frequencies). "
|
||||
"It also impacts the elevation angle and overall path length.\n\n"
|
||||
"🔗 [Find coordinates](https://www.gps-coordinates.net)"
|
||||
),
|
||||
"availability": (
|
||||
"**Link Availability [%]**\n\n"
|
||||
"A high desired link availability corresponds to high signal attenuation: "
|
||||
"only rare and severe weather events exceeding this attenuation can interrupt the link.\n\n"
|
||||
"For example, at 99.9% availability, the attenuation considered is only exceeded 0.1% of the time."
|
||||
),
|
||||
"path_length": (
|
||||
"**Path Length [km] @ Elevation [°]**\n\n"
|
||||
"Distance from the satellite to the ground station and elevation angle. "
|
||||
"Minimum path length = satellite altitude (elevation = 90°). "
|
||||
"A negative elevation means the satellite is not visible."
|
||||
),
|
||||
"atm_loss": (
|
||||
"**Atmospheric Attenuation [dB]**\n\n"
|
||||
"The atmosphere affects radio wave propagation with attenuation from rain, clouds, "
|
||||
"scintillation, multi-path, sand/dust storms, and atmospheric gases.\n\n"
|
||||
"Typical attenuation exceeded 0.1% of the time in Europe from GEO:\n"
|
||||
"- Ku: 2.5 dB\n- Ka: 6.9 dB\n- Q: 22 dB\n\n"
|
||||
"Uses [ITU-Rpy](https://itu-rpy.readthedocs.io/en/latest/index.html)."
|
||||
),
|
||||
"hpa": (
|
||||
"**HPA Output Power [W]**\n\n"
|
||||
"Power of the High Power Amplifier at the satellite's last amplification stage. "
|
||||
"Some satellites operate at saturation (DTH), others in multicarrier mode with "
|
||||
"reduced power (3 dB Output Back Off is typical for VSAT)."
|
||||
),
|
||||
"sat_beam": (
|
||||
"**Satellite Beam Diameter [°]**\n\n"
|
||||
"Half-power beam width. Typical values: 0.4–1.4° for GEO HTS, 3–6° for GEO DTH."
|
||||
),
|
||||
"gain_offset": (
|
||||
"**Gain Offset from Peak [dB]**\n\n"
|
||||
"Simulates terminals not at beam peak. 3 dB = worst case in 3 dB beam (DTH). "
|
||||
"1 dB = typical median performance for single feed per beam HTS."
|
||||
),
|
||||
"losses": (
|
||||
"**Output Section Losses [dB]**\n\n"
|
||||
"Signal loss between HPA and antenna (filters, waveguides, switches). "
|
||||
"Typical: 2.5 dB for classical satellites, 1 dB for active antennas."
|
||||
),
|
||||
"sat_cir": (
|
||||
"**Satellite C/I [dB]**\n\n"
|
||||
"Signal impairments from satellite implementation: intermodulation, filtering, phase noise. "
|
||||
"Supports comma-separated lists to include uplink C/N, interferences, etc."
|
||||
),
|
||||
"output_power": "**Output Power [W]** — Signal power at antenna output carrying user information.",
|
||||
"sat_gain": (
|
||||
"**Satellite Antenna Gain**\n\n"
|
||||
"Ratio between signal radiated on-axis vs. isotropic antenna. "
|
||||
"Expressed in dBi (dB relative to isotropic antenna)."
|
||||
),
|
||||
"eirp": (
|
||||
"**Equivalent Isotropic Radiated Power (EIRP)**\n\n"
|
||||
"Product Power × Gain in Watts. Represents the power required for an isotropic antenna "
|
||||
"to match the directive antenna's radiation in that direction."
|
||||
),
|
||||
"path_loss": (
|
||||
"**Path Dispersion Loss**\n\n"
|
||||
"Free-space propagation loss — simply the surface of a sphere with radius = path length. "
|
||||
"Not actual absorption, just geometric spreading."
|
||||
),
|
||||
"pfd": (
|
||||
"**Power Flux Density**\n\n"
|
||||
"Signal power per square meter at the terminal side. "
|
||||
"Actual captured power = PFD × antenna effective area."
|
||||
),
|
||||
"cpe_ant": (
|
||||
"**Customer Antenna Size [m]**\n\n"
|
||||
"Parabolic antenna with state-of-the-art efficiency (~60%)."
|
||||
),
|
||||
"cpe_temp": (
|
||||
"**Noise Temperature [K]**\n\n"
|
||||
"Total receiver's clear-sky noise temperature. Includes all contributors: "
|
||||
"receiver, sky, ground seen by antenna. Default of 120 K is a reasonable typical value."
|
||||
),
|
||||
"cpe_gain": (
|
||||
"**Antenna Effective Area and G/T**\n\n"
|
||||
"G/T is the figure of merit of a receive antenna: Gain / Noise Temperature. "
|
||||
"In case of rain, the signal is punished twice: attenuation weakens it and "
|
||||
"the rain attenuator generates additional noise."
|
||||
),
|
||||
"rx_power": "**RX Power** — Extremely small power before amplification. This is 'C' in Shannon's equation.",
|
||||
"n0": "**Noise Power Density N₀** — Noise Spectral Power Density of the radio front end.",
|
||||
"br_inf": (
|
||||
"**Bit Rate at infinite BW** — Asymptotic limit: 1.443·C/N₀. Never achieved in practice."
|
||||
),
|
||||
"br_unit": "**Bit Rate at Spectral Efficiency=1** — Bandwidth = Bit Rate and C/N = 0 dB.",
|
||||
"br_double": (
|
||||
"**Bit Rate at Spectral Efficiency=2** — Bandwidth-efficient operating point "
|
||||
"(BW = 0.5 × BR), often considered typical."
|
||||
),
|
||||
"bandwidth": (
|
||||
"**Occupied Bandwidth [MHz]**\n\n"
|
||||
"Bandwidth occupied by the communication channel — a key degree of freedom in system design."
|
||||
),
|
||||
"rolloff": (
|
||||
"**Nyquist Filter Rolloff [%]**\n\n"
|
||||
"Excess bandwidth required beyond the theoretical Nyquist minimum. "
|
||||
"The Nyquist filter avoids inter-symbol interference."
|
||||
),
|
||||
"cir": (
|
||||
"**Receiver C/I [dB]**\n\n"
|
||||
"Signal impairments from terminal: phase noise, quantization, synchronization errors. "
|
||||
"Supports comma-separated lists."
|
||||
),
|
||||
"penalty": (
|
||||
"**Implementation Penalty [dB]**\n\n"
|
||||
"DVB-S2x with LDPC codes is typically 1 dB from Shannon Limit. "
|
||||
"With 0.5 dB margin, a total of 1.5 dB is typical."
|
||||
),
|
||||
"overhead": (
|
||||
"**Higher Layers Overhead [%]**\n\n"
|
||||
"Encapsulation cost (IP over DVB-S2x via GSE). Typically ~5% for modern systems."
|
||||
),
|
||||
"cnr_bw": "**SNR in Available BW** — Signal-to-Noise Ratio in the available bandwidth.",
|
||||
"cnr_nyq": "**SNR in Nyquist BW** — SNR in Nyquist BW = Available BW / (1 + Roll-Off).",
|
||||
"cnr_rcv": (
|
||||
"**SNR at Receiver Output** — Combining link noise, satellite C/I, and receiver C/I. "
|
||||
"This is the relevant ratio for real-life performance."
|
||||
),
|
||||
"br_nyq": (
|
||||
"**Theoretical Bit Rate** — Direct application of Shannon Limit in Nyquist BW. "
|
||||
"Efficiency in bits/symbol also shown."
|
||||
),
|
||||
"br_rcv": (
|
||||
"**Practical Physical Layer Bit Rate** — Using all-degradations-included SNR "
|
||||
"in Shannon's formula."
|
||||
),
|
||||
"br_high": (
|
||||
"**Practical Higher Layers Bit Rate** — Corresponds to user bits of IP datagrams."
|
||||
),
|
||||
"satellite": (
|
||||
"The evaluation is decomposed in 3 sections:\n\n"
|
||||
"1. **Satellite Link** — transmitter and path to receiver with key characteristics\n"
|
||||
"2. **Radio Front End** — antenna and amplification capturing signal with minimal noise\n"
|
||||
"3. **Baseband Unit** — digital signal processing: filtering, synchronization, "
|
||||
"demodulation, error correction, decapsulation\n\n"
|
||||
"All fields are initially filled with meaningful values. Start by changing the "
|
||||
"straightforward parameters. All parameters have help tooltips."
|
||||
),
|
||||
"advanced": (
|
||||
"**Advanced Analysis Notes**\n\n"
|
||||
"All capacity evaluations use direct application of the Shannon formula with real-world "
|
||||
"impairments via C/N combinations. Useful links:\n\n"
|
||||
"- [Nyquist ISI Criterion](https://en.wikipedia.org/wiki/Nyquist_ISI_criterion)\n"
|
||||
"- [Error Correction Codes](https://en.wikipedia.org/wiki/Error_correction_code)\n"
|
||||
"- [Viterbi Decoder](https://en.wikipedia.org/wiki/Viterbi_decoder)\n"
|
||||
"- [Turbo Codes](https://en.wikipedia.org/wiki/Turbo_code)\n"
|
||||
"- [DVB-S2](https://en.wikipedia.org/wiki/DVB-S2)\n"
|
||||
"- [OSI Model](https://en.wikipedia.org/wiki/OSI_model)"
|
||||
),
|
||||
"help": (
|
||||
"**Recommendations**\n\n"
|
||||
"- Try multiple values one by one, starting from the least intimidating\n"
|
||||
"- Explore the graphs to understand the physics\n"
|
||||
"- Units are as explicit as possible\n"
|
||||
"- The tool can also be used for a quick first-order link analysis"
|
||||
),
|
||||
}
|
||||
Reference in New Issue
Block a user