Source code for deshima_sensitivity.atmosphere
# standard library
from pathlib import Path
from typing import Callable, List, Union
# dependent packages
import numpy as np
import pandas as pd
from scipy.interpolate import interp2d
# type aliases
ArrayLike = Union[np.ndarray, List[float], List[int], float, int]
# main functions
[docs]def eta_atm_func(
F: ArrayLike, pwv: float, EL: float = 60.0, R: float = 0.0
) -> ArrayLike:
"""Calculate eta_atm as a function of F by interpolation.
If R~=0 then the function will average the atmospheric transmission
within each spectrometer channel.
Parameters
----------
F
Frequency of the astronomical signal.
Units: Hz (works also for GHz, will detect).
pwv
Precipitable water vapour. Units: mm.
EL
Telescope elevation angle. Units: degrees.
R
Spectral resolving power in F/W_F where W_F is the 'equivalent bandwidth'.
R is used to average the atmospheric transmission within one spectrometer
channel. If R = 0, then the function will return the transmission
at that exact frequency. Units: None.
See also: http://www.astrosurf.com/buil/us/spe2/hresol7.htm
Returns
-------
eta_atm
Atmospheric tranmsmission. Units: None.
"""
if np.average(F) > 10.0**9:
F = F / 10.0**9
# give F a length if it is an integer.
if not hasattr(F, "__len__"):
F = np.asarray([F])
eta_atm_df = pd.read_csv(
Path(__file__).parent / "data" / "atm.csv",
skiprows=4,
delim_whitespace=True,
header=0,
)
eta_atm_func_zenith = eta_atm_interp(eta_atm_df)
if R == 0:
eta_atm = np.abs(eta_atm_func_zenith(pwv, F)) ** (
1.0 / np.sin(EL * np.pi / 180.0)
)
else:
# smooth with spectrometer resolution
# 100.0, 100.1., ....., 1000 GHz as in the original data.
F_highres = eta_atm_df["F"]
eta_atm_zenith_highres = np.abs(eta_atm_func_zenith(pwv, F_highres)) ** (
1.0 / np.sin(EL * np.pi / 180.0)
)
eta_atm = np.zeros(len(F))
for i_ch in range(len(F)):
eta_atm[i_ch] = np.mean(
eta_atm_zenith_highres[
(F_highres > F[i_ch] * (1 - 0.5 / R))
& (F_highres < F[i_ch] * (1 + 0.5 / R))
]
)
eta_atm = [eta_atm]
if len(eta_atm) == 1:
return eta_atm[0]
else:
return eta_atm[:, 0]
# helper functions
[docs]def eta_atm_interp(eta_atm_dataframe: pd.DataFrame) -> Callable:
"""Used in the function eta_atm_func().
Returns a function that interpolates atmospheric transmission data
downloaded from ALMA (https://almascience.eso.org/about-alma/atmosphere-model).
The returned function has the form of eta = func(F [GHz], pwv [mm]).
Note telescope EL = 90 (zenith).
Parameters
----------
eta_atm_dataframe
Pandas DataFrame of atmospheric transmission data.
Returns
--------
func
Function that returns the atmospheric transmission.
Example
--------
Read csv file with pandas (in e.g., Jupyter)::
eta_atm_df = pd.read_csv("<desim-folder>/data/atm.csv",skiprows=4,
delim_whitespace=True,header=0)
Make function from pandas file::
etafun = desim.eta_atm_interp(eta_atm_df)
"""
x = np.array(list(eta_atm_dataframe)[1:]).astype(np.float64)
y = eta_atm_dataframe["F"].values
z = eta_atm_dataframe.iloc[:, 1:].values
return interp2d(x, y, z, kind="cubic")