__all__ = ["MDLF_simple", "MS_simple", "PlotD2HPBW"]
# standard library
from typing import List, Union
# dependent packages
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from jupyter_io import savetable_in_notebook
from jupyter_io.output import HTML
from .instruments import D2HPBW, eta_mb_ruze
from .simulator import spectrometer_sensitivity
# type aliases
ArrayLike = Union[np.ndarray, List[float], List[int], float, int]
# main functions
[docs]def MDLF_simple(
F: ArrayLike,
pwv: float = 0.5,
EL: float = 60.0,
snr: float = 5.0,
obs_hours: float = 8.0,
) -> HTML:
"""Plot minimum detectable line flux (MDLF) of DESHIMA 2.0 on ASTE.
Parameters
----------
F
Frequency. Units: GHz.
pwv
Precipitable water vapor. Units: mm.
EL
Elevation angle. Units: degrees.
snr
Target S/N of the detection.
obs_hours
Total hours of observation including ON-OFF and calibration overhead.
Returns
-------
html
HTML object for download link (to be used in Jupyter notebook).
"""
# Main beam efficiency of ASTE (0.9 is from EM, ruze is from ASTE)
eta_mb = eta_mb_ruze(F=F, LFlimit=0.805, sigma=37e-6) * 0.9
D2goal_input = {
"F": F,
"pwv": pwv,
"EL": EL,
"snr": snr,
"obs_hours": obs_hours,
"eta_mb": eta_mb,
"theta_maj": D2HPBW(F), # Half power beam width (major axis)
"theta_min": D2HPBW(F), # Half power beam width (minor axis)
"on_source_fraction": 0.4 * 0.9, # ON-OFF 40%, calibration overhead of 10%
}
D2goal = spectrometer_sensitivity(**D2goal_input)
D2baseline_input = {
"F": F,
"pwv": pwv,
"EL": EL,
"snr": snr,
"obs_hours": obs_hours,
"eta_mb": eta_mb,
"theta_maj": D2HPBW(F), # Half power beam width (major axis)
"theta_min": D2HPBW(F), # Half power beam width (minor axis)
"on_source_fraction": 0.3 * 0.8, # Goal 0.4*0.9
"eta_circuit": 0.32 * 0.5, # eta_inst Goal 16%, Baseline 8%
"eta_IBF": 0.4, # Goal 0.6
"KID_excess_noise_factor": 1.2, # Goal 1.1
}
D2baseline = spectrometer_sensitivity(**D2baseline_input)
# Plotting
fig, ax = plt.subplots(1, 1, figsize=(12, 6))
ax.plot(
D2baseline["F"] / 1e9,
D2baseline["MDLF"],
"--",
linewidth=1,
color="b",
alpha=1,
label="Baseline",
)
ax.plot(
D2goal["F"] / 1e9, D2goal["MDLF"], linewidth=1, color="b", alpha=1, label="Goal"
)
ax.fill_between(
D2baseline["F"] / 1e9, D2baseline["MDLF"], D2goal["MDLF"], color="b", alpha=0.2
)
ax.set_xlabel("Frequency (GHz)")
ax.set_ylabel(r"Minimum Detectable Line Flux ($\mathrm{W\, m^{-2}}$)")
ax.set_yscale("log")
ax.set_xlim(200, 460)
ax.set_ylim([10**-20, 10**-17])
ax.tick_params(direction="in", which="both")
ax.grid(True)
ax.set_title(
f"R = {int(D2goal['R'][0])}, "
f"snr = {int(D2goal['snr'][0])}, "
f"t_obs = {D2goal['obs_hours'][0]} h (incl. overhead), "
f"PWV = {D2goal['PWV'][0]} mm, "
f"EL = {int(D2goal['EL'][0])} deg",
fontsize=12,
)
ax.legend()
fig.tight_layout()
# Create download link
df_download = D2goal[["F", "MDLF"]]
df_download = df_download.rename(columns={"MDLF": "MDLF (goal)"})
df_download = df_download.join(D2baseline[["MDLF"]])
df_download = df_download.rename(columns={"MDLF": "MDLF (baseline)"})
return savetable_in_notebook(df_download, "MDLF.csv")
[docs]def MS_simple(F: ArrayLike, pwv: float = 0.5, EL: float = 60.0) -> HTML:
"""Plot mapping speed of DESHIMA 2.0 on ASTE.
Parameters
----------
F
Frequency. Units: GHz.
pwv
Precipitable water vapor. Units: mm.
EL
Elevation angle. Units: degrees.
Returns
-------
html
HTML object for download link (to be used in Jupyter notebook).
"""
# Main beam efficiency of ASTE (0.9 is from EM, ruze is from ASTE)
eta_mb = eta_mb_ruze(F=F, LFlimit=0.805, sigma=37e-6) * 0.9
D2goal_input = {
"F": F,
"pwv": pwv,
"EL": EL,
"eta_mb": eta_mb,
"on_off": False,
"theta_maj": D2HPBW(F), # Half power beam width (major axis)
"theta_min": D2HPBW(F), # Half power beam width (minor axis)
}
D2goal = spectrometer_sensitivity(**D2goal_input)
D2baseline_input = {
"F": F,
"pwv": pwv,
"EL": EL,
"eta_mb": eta_mb,
"on_off": False,
"theta_maj": D2HPBW(F), # Half power beam width (major axis)
"theta_min": D2HPBW(F), # Half power beam width (minor axis)
"eta_circuit": 0.32 * 0.5, # eta_inst Goal 16%, Baseline 8%
"eta_IBF": 0.4, # Goal 0.6
"KID_excess_noise_factor": 1.2, # Goal 1.1
}
D2baseline = spectrometer_sensitivity(**D2baseline_input)
# Plotting
fig, ax = plt.subplots(1, 1, figsize=(12, 6))
ax.plot(
D2baseline["F"] / 1e9,
D2baseline["MS"],
"--",
linewidth=1,
color="b",
alpha=1,
label="Baseline",
)
ax.plot(
D2goal["F"] / 1e9, D2goal["MS"], linewidth=1, color="b", alpha=1, label="Goal"
)
ax.fill_between(
D2baseline["F"] / 1e9, D2baseline["MS"], D2goal["MS"], color="b", alpha=0.2
)
ax.set_xlabel("Frequency (GHz)")
ax.set_ylabel(r"Mapping Speed ($\mathrm{arcmin^2\, mJy^{-2}\, h^{-1}}$)")
ax.set_yscale("log")
ax.set_xlim(200, 460)
ax.set_ylim([10**-5, 10**-2])
ax.tick_params(direction="in", which="both")
ax.grid(True)
ax.set_title(
f"R = {int(D2goal['R'][0])}, "
f"PWV = {D2goal['PWV'][0]} mm, "
f"EL = {int(D2goal['EL'][0])} deg",
fontsize=12,
)
ax.legend()
fig.tight_layout()
# Create download link
df_download = D2goal[["F", "MS"]]
df_download = df_download.rename(columns={"MS": "MS (goal)"})
df_download = df_download.join(D2baseline[["MS"]])
df_download = df_download.rename(columns={"MS": "MS (baseline)"})
return savetable_in_notebook(df_download, "MS.csv")
[docs]def PlotD2HPBW() -> HTML:
"""Plot half power beam width of DESHIMA 2.0 on ASTE.
Returns
-------
html
HTML object for download link (to be used in Jupyter notebook).
"""
F = np.logspace(np.log10(220), np.log10(440), 349) * 1e9
fig, ax = plt.subplots(1, 1, figsize=(12, 6))
ax.plot(
F / 1e9,
D2HPBW(F) * 180 * 60 * 60 / np.pi,
linewidth=1,
color="b",
alpha=1,
label="HPBW",
)
ax.set_xlabel("Frequency (GHz)")
ax.set_ylabel("HPBW (arcsec)")
ax.set_yscale("linear")
ax.set_xlim(200, 460)
ax.tick_params(direction="in", which="both")
ax.grid(True)
ax.legend()
fig.tight_layout()
# Create download link
df_download = pd.DataFrame(data=F, columns=["F"])
df_download["HPBW"] = D2HPBW(F) * 180 * 60 * 60 / np.pi
return savetable_in_notebook(df_download, "HPBW.csv")