mirror of
https://git.ianrenton.com/ian/spothole.git
synced 2026-04-29 18:25:58 +00:00
Add descriptions for solar conditions #92
This commit is contained in:
@@ -1,6 +1,87 @@
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
|
||||
# Lookup tables for derived text descriptions.
|
||||
# Each threshold-based table is a list of (min_value, description) pairs in descending order;
|
||||
# the first entry whose threshold the value meets or exceeds is used.
|
||||
|
||||
BLACKOUT_DESCRIPTIONS = {
|
||||
"X": "Extreme HF radio blackout on entire sunlit side",
|
||||
"M": "Wide area HF radio blackout on sunlit side",
|
||||
"C": "Occasional loss of HF communications on sunlit side",
|
||||
"B": "No significant radio blackout",
|
||||
"A": "No impact",
|
||||
}
|
||||
|
||||
PROTON_FLUX_DESCRIPTIONS = [
|
||||
(1000000, "Complete HF blackout in polar regions"),
|
||||
(100000, "Partial HF blackout in polar regions"),
|
||||
(10000, "Degraded HF propagation in polar regions"),
|
||||
(1000, "Small effect on HF propagation in polar regions"),
|
||||
(100, "Minor effect on HF propagation in polar regions"),
|
||||
(10, "Very minor effect on HF propagation in polar regions"),
|
||||
(0, "No impact"),
|
||||
]
|
||||
|
||||
SOLAR_STORM_SCALES = [
|
||||
(100000, 5),
|
||||
(10000, 4),
|
||||
(1000, 3),
|
||||
(100, 2),
|
||||
(10, 1),
|
||||
(0, 0),
|
||||
]
|
||||
|
||||
GEOMAG_STORM_DESCRIPTIONS = [
|
||||
(9, "Solar storm. Complete HF blackout, S30+ noise"),
|
||||
(8, "Solar storm. HF sporadic only, S20-30 noise"),
|
||||
(7, "Solar storm. HF intermittent, S9-20 noise"),
|
||||
(6, "Solar storm. HF fading at higher latitudes, S6-9 noise"),
|
||||
(5, "Solar storm. HF fading at higher latitudes, S4-6 noise"),
|
||||
(4, "Active. Minor HF fading at higher latitudes, S2-3 noise"),
|
||||
(3, "Unsettled. Minor HF fading at higher latitudes, S2-3 noise"),
|
||||
(2, "Inactive. No impact, S0-2 noise"),
|
||||
(1, "Quiet. No impact, S0-2 noise"),
|
||||
(0, "Quiet. No impact, S0-2 noise"),
|
||||
]
|
||||
|
||||
GEOMAG_STORM_SCALES = [
|
||||
(9, 5),
|
||||
(8, 4),
|
||||
(7, 3),
|
||||
(6, 2),
|
||||
(5, 1),
|
||||
(0, 0),
|
||||
]
|
||||
|
||||
BAND_CONDITIONS_DESCRIPTIONS = [
|
||||
(200, "Reliable conditions on all bands including 6m"),
|
||||
(150, "Excellent conditions on all bands up to 10m, occasional 6m openings"),
|
||||
(120, "Fair to good conditions on all bands up to 10m"),
|
||||
(90, "Fair conditions on bands up to 15m"),
|
||||
(70, "Poor to fair conditions on bands up to 20m"),
|
||||
(0, "Bands above 40m unusable"),
|
||||
]
|
||||
|
||||
ELECTRON_FLUX_DESCRIPTIONS = [
|
||||
(1000, "Partial to complete HF blackout in polar regions"),
|
||||
(100, "Degraded HF propagation in polar regions"),
|
||||
(10, "Minor impact on HF in polar regions"),
|
||||
(0, "No impact"),
|
||||
]
|
||||
|
||||
|
||||
def _lookup_by_threshold(value, table, default=None):
|
||||
"""Return the description from a threshold table for the given numeric value.
|
||||
The table is a list of (min_value, description) pairs in descending order."""
|
||||
|
||||
if value is None:
|
||||
return default
|
||||
for threshold, description in table:
|
||||
if value >= threshold:
|
||||
return description
|
||||
return default
|
||||
|
||||
|
||||
@dataclass
|
||||
class HFBandCondition:
|
||||
@@ -63,6 +144,36 @@ class SolarConditions:
|
||||
# VHF propagation phenomena
|
||||
vhf_conditions: list = None # list[VHFCondition]
|
||||
|
||||
# Derived values (populated by infer_descriptions())
|
||||
# HF radio blackout risk, derived from x_ray
|
||||
blackout_desc: str = None
|
||||
# Solar radiation storm level description, derived from proton_flux
|
||||
proton_flux_desc: str = None
|
||||
# Solar radiation storm scale number (S0–S5), derived from proton_flux
|
||||
solar_storm_scale: int = None
|
||||
# Geomagnetic storm level description, derived from k_index
|
||||
geomag_storm_desc: str = None
|
||||
# Geomagnetic storm scale number (G0–G5), derived from k_index
|
||||
geomag_storm_scale: int = None
|
||||
# Overall HF band conditions summary, derived from sfi
|
||||
band_conditions_desc: str = None
|
||||
# Electron flux level, derived from electron_flux
|
||||
electron_flux_desc: str = None
|
||||
|
||||
def infer_descriptions(self):
|
||||
"""Populate derived text description fields from the current numeric/raw field values."""
|
||||
|
||||
# blackout_desc: use the X-ray flux class letter (first character of x_ray)
|
||||
if self.x_ray and len(self.x_ray) > 0:
|
||||
self.blackout_desc = BLACKOUT_DESCRIPTIONS.get(self.x_ray[0].upper())
|
||||
|
||||
self.proton_flux_desc = _lookup_by_threshold(self.proton_flux, PROTON_FLUX_DESCRIPTIONS)
|
||||
self.solar_storm_scale = _lookup_by_threshold(self.proton_flux, SOLAR_STORM_SCALES)
|
||||
self.geomag_storm_desc = _lookup_by_threshold(self.k_index, GEOMAG_STORM_DESCRIPTIONS)
|
||||
self.geomag_storm_scale = _lookup_by_threshold(self.k_index, GEOMAG_STORM_SCALES)
|
||||
self.band_conditions_desc = _lookup_by_threshold(self.sfi, BAND_CONDITIONS_DESCRIPTIONS)
|
||||
self.electron_flux_desc = _lookup_by_threshold(self.electron_flux, ELECTRON_FLUX_DESCRIPTIONS)
|
||||
|
||||
def to_json(self):
|
||||
"""JSON serialise"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user