"""
Module that provides the reference profiles from :cite:t:`patzold2007`.
"""
# standard imports
import numpy as np
from importlib.resources import files as res_files
from astropy.units import Quantity, Unit
# package imports
from ...utils.interpolate import BoundedInterpolatingBasis
from ...utils.io import read_unit_csv
from ...profile import MultiProfile
# data content
DOYS = [196, 200, 202, 212, 218, 233, 234, 239]
""" Day-of-years of the electron density profiles """
TABLES = [
f"fig{t}-doy{d}"
for t, d in zip(["4a", "4b", "4b", "4b", "5a", "5b", "5c", "5d"], DOYS)
]
""" Table numbers to load """
# data format information
SZAS = Quantity([50, 56, 59, 80, 92.4, 113.0, 113.4, 113.5], "°")
""" Solar zenith angles [°] of the elctron density profiles """
UNIT_EL_DENSITY = Unit("1/m3")
""" Output unit of the electron density profile [1/m3]"""
# get local installation folder paths
_datafolder = res_files()
""" Resolved current folder location """
# load raw data files
tables = {t: read_unit_csv(_datafolder / f"table{t}.csv") for t in TABLES}
"""
Loaded tables
:meta hide-value:
"""
# get function that returns the first 6 electron density profiles as a MultiProfile
def _get_el_densities() -> MultiProfile:
# get unique altitude levels
el_altitude = np.unique(
np.concatenate([tables[t]["Altitude"].value for t in TABLES[:6]])
)
# interpolate all data onto common altitudes
all_densities = np.zeros((el_altitude.size, 6))
for i, t in enumerate(TABLES[:6]):
all_densities[:, i] = np.clip(
np.interp(
el_altitude,
tables[t]["Altitude"].value,
tables[t]["Electron density"].to(UNIT_EL_DENSITY).value,
left=0,
right=None,
),
a_min=0,
a_max=None,
)
# return as MultiProfile
return MultiProfile(
index=el_altitude,
index_unit=tables[t]["Altitude"].unit,
data=all_densities,
data_units=UNIT_EL_DENSITY,
data_names=[f"doy_{d}" for d in DOYS[:6]],
)
# create electron density MultiProfile
el_density = _get_el_densities()
""" Electron density profiles at different solar zenith angles """
# build inter- and extrapolator for first 6 angles
sza_interpolating_basis = BoundedInterpolatingBasis(
0, 180, knots=SZAS[:6].to("°").value
)
"""
Interpolating basis for the well-resolved SZA angles between 50° and 113°,
returns a 2D array when called with each column representing the different
knots
"""
[docs]
def interpolate_el_density(sza: Quantity["angle"]) -> Quantity:
"""
Interpolate the electron density profiles from solar zenith angles
between 50° and 113°.
Parameters
----------
sza
Solar zenith angle [°]
Returns
-------
Electron density profile at all altitudes for different SZA
"""
sza_coefs = sza_interpolating_basis(sza.to("°").value)
intp_density = Quantity(
np.einsum(
"ij,kj->ik",
el_density.data,
sza_coefs,
),
el_density.unit,
)
return intp_density