Add LUF to ionosonde data API & chart

This commit is contained in:
Ian Renton
2026-05-21 20:09:11 +01:00
parent d655354d05
commit c38be5b588
13 changed files with 67 additions and 39 deletions

View File

@@ -17,7 +17,7 @@ HISTORY_HOURS = 24
class GIROIonosonde(SolarConditionsProvider):
"""Solar conditions provider using ionosonde data from the GIRO Data Center.
Queries foF2 and MUF measurements for all stations in datafiles/didbase-stations.csv."""
Queries foF2, MUF, and LUF measurements for all stations in datafiles/didbase-stations.csv."""
def __init__(self, provider_config):
super().__init__(provider_config)
@@ -41,7 +41,7 @@ class GIROIonosonde(SolarConditionsProvider):
super().setup(solar_conditions, solar_conditions_cache)
self.update_data({"ionosonde_data": {
s["ursi"]: {"ursi": s["ursi"], "name": s["name"], "fof2": None, "muf": None}
s["ursi"]: {"ursi": s["ursi"], "name": s["name"], "fof2": None, "muf": None, "luf": None}
for s in self._stations
}})
@@ -73,9 +73,9 @@ class GIROIonosonde(SolarConditionsProvider):
ursi = station["ursi"]
name = station["name"]
try:
fof2, muf = self._fetch_station_data(ursi, from_time, now)
fof2, muf, luf = self._fetch_station_data(ursi, from_time, now)
if fof2 and muf:
ionosonde_data[ursi] = {"ursi": ursi, "name": name, "fof2": fof2, "muf": muf}
ionosonde_data[ursi] = {"ursi": ursi, "name": name, "fof2": fof2, "muf": muf, "luf": luf or None}
updated_count += 1
except Exception:
logging.warning(f"Could not fetch ionosonde data for {ursi} ({name})")
@@ -91,27 +91,28 @@ class GIROIonosonde(SolarConditionsProvider):
self._stop_event.wait(timeout=1)
def _fetch_station_data(self, ursi, from_time, to_time):
"""Fetch foF2 and MUF readings for a station. Returns (fof2_dict, muf_dict) keyed by UNIX timestamp."""
"""Fetch foF2, MUF and LUF readings for a station. Returns (fof2_dict, muf_dict, luf_dict) keyed by UNIX timestamp."""
from_str = from_time.strftime("%Y.%m.%d+%H:%M:%S")
to_str = to_time.strftime("%Y.%m.%d+%H:%M:%S")
url = f"{LGDC_URL}?ursiCode={ursi}&charName=foF2,MUFD&DMUF=3000&fromDate={from_str}&toDate={to_str}"
url = f"{LGDC_URL}?ursiCode={ursi}&charName=foF2,MUFD,fmin&DMUF=3000&fromDate={from_str}&toDate={to_str}"
response = requests.get(url, headers=HTTP_HEADERS, timeout=(5, 15))
if response.status_code != 200:
return None, None
return None, None, None
return self._parse_all(response.text)
@staticmethod
def _parse_all(text):
"""Parse web server response and return (fof2_dict, muf_dict) keyed by UNIX timestamp."""
"""Parse web server response and return (fof2_dict, muf_dict, luf_dict) keyed by UNIX timestamp."""
fof2_data = {}
muf_data = {}
luf_data = {}
for line in text.splitlines():
line = line.strip()
if not line or line.startswith('#'):
continue
# Data rows have the following format: timestamp CS foF2 QD MUFD QD
# Data rows have the following format: timestamp CS foF2 QD MUFD QD fmin QD
parts = line.split()
if len(parts) >= 5:
try:
@@ -127,4 +128,9 @@ class GIROIonosonde(SolarConditionsProvider):
muf_data[ts] = float(parts[4])
except ValueError:
pass
return fof2_data, muf_data
if len(parts) >= 7:
try:
luf_data[ts] = float(parts[6])
except ValueError:
pass
return fof2_data, muf_data, luf_data