Instruments
[1]:
import os
import sys
import numpy as np
import pandas as pd
sys.path.insert(0, os.path.join(".."))
Meudon PDR code predictions
[2]:
from infobs.model import MeudonPDR
meudonpdr = MeudonPDR()
df_params = pd.DataFrame(
{
"Av": [1, 5, 10, 15, 20],
"G0": [1e2, 1e2, 1e2, 1e2, 1e2],
"Pth": [1e5, 1e5, 1e5, 1e5, 1e5],
"angle": [0, 0, 0, 0, 0],
}
)
df_params
[2]:
| Av | G0 | Pth | angle | |
|---|---|---|---|---|
| 0 | 1 | 100.0 | 100000.0 | 0 |
| 1 | 5 | 100.0 | 100000.0 | 0 |
| 2 | 10 | 100.0 | 100000.0 | 0 |
| 3 | 15 | 100.0 | 100000.0 | 0 |
| 4 | 20 | 100.0 | 100000.0 | 0 |
[3]:
meudonpdr.predict(df_params)
[3]:
| Av | G0 | Pth | angle | kappa | h2_v0_j2__v0_j0 | h2_v0_j3__v0_j1 | h2_v0_j4__v0_j2 | h2_v0_j5__v0_j3 | h2_v0_j6__v0_j4 | ... | shp_n10_j11_f11d5__n9_j10_f10d5 | shp_n10_j10_f10d5__n9_j9_f9d5 | shp_n10_j9_f9d5__n9_j8_f8d5 | shp_n10_j9_f9d5__n9_j10_f10d5 | shp_n10_j10_f10d5__n9_j10_f10d5 | shp_n5_j4_f4d5__n2_j3_f3d5 | shp_n6_j5_f5d5__n3_j4_f4d5 | shp_n7_j6_f6d5__n4_j5_f5d5 | shp_n8_j7_f7d5__n5_j6_f6d5 | shp_n9_j8_f8d5__n6_j7_f7d5 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 0.010243 | 0.002992 | 0.000057 | 0.000010 | 0.000002 | ... | 2.991196e-12 | 2.645448e-12 | 2.420507e-12 | 3.334513e-17 | 2.685572e-14 | 7.130854e-14 | 1.255194e-14 | 2.563640e-15 | 5.562906e-16 | 1.247624e-16 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 0.009836 | 0.003158 | 0.000060 | 0.000010 | 0.000002 | ... | 2.927281e-12 | 2.588342e-12 | 2.376320e-12 | 3.258995e-17 | 2.626043e-14 | 7.143769e-14 | 1.253789e-14 | 2.521841e-15 | 5.556850e-16 | 1.238246e-16 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 0.010026 | 0.003207 | 0.000059 | 0.000010 | 0.000002 | ... | 2.915170e-12 | 2.580306e-12 | 2.359131e-12 | 3.258680e-17 | 2.623749e-14 | 7.176126e-14 | 1.255073e-14 | 2.530706e-15 | 5.523370e-16 | 1.229295e-16 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 0.010062 | 0.003317 | 0.000059 | 0.000010 | 0.000002 | ... | 2.913692e-12 | 2.583992e-12 | 2.372837e-12 | 3.241424e-17 | 2.622504e-14 | 7.204642e-14 | 1.255310e-14 | 2.542738e-15 | 5.539160e-16 | 1.230413e-16 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 0.010102 | 0.003278 | 0.000058 | 0.000011 | 0.000002 | ... | 2.893779e-12 | 2.571290e-12 | 2.359847e-12 | 3.224938e-17 | 2.617005e-14 | 7.181391e-14 | 1.253679e-14 | 2.545107e-15 | 5.531721e-16 | 1.225758e-16 |
5 rows × 5025 columns
[4]:
df = meudonpdr.predict(
df_params,
lines=[
"13c_o_j1__j0",
"13c_o_j2__j1",
"13c_o_j3__j2",
"c_el3p_j1__el3p_j0",
"c_el3p_j2__el3p_j1",
"cp_el2p_j3_2__el2p_j1_2",
],
)
df
[4]:
| Av | G0 | Pth | angle | kappa | 13c_o_j1__j0 | 13c_o_j2__j1 | 13c_o_j3__j2 | c_el3p_j1__el3p_j0 | c_el3p_j2__el3p_j1 | cp_el2p_j3_2__el2p_j1_2 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 0.000276 | 0.000318 | 0.000128 | 0.237290 | 0.168541 | 7.993103 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 10.176692 | 11.708745 | 3.919423 | 22.388675 | 11.729995 | 10.794163 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 22.873276 | 21.915024 | 8.102161 | 21.884921 | 11.508051 | 10.750909 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 29.498773 | 25.964494 | 10.321277 | 22.693579 | 11.846299 | 10.839103 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 34.912525 | 29.605632 | 12.635616 | 23.212814 | 12.121948 | 10.800269 |
Instruments
[5]:
obstime = 1 # Minutes
linewidth = 10 # km/s
Ideal instrument
Note: By definition, the integration time obstime has no effect when using the ideal instrument.
[6]:
from infobs.instruments import IdealInstrument
ideal = IdealInstrument()
ideal.measure(df, obstime)
[6]:
| Av | G0 | Pth | angle | kappa | 13c_o_j1__j0 | 13c_o_j2__j1 | 13c_o_j3__j2 | c_el3p_j1__el3p_j0 | c_el3p_j2__el3p_j1 | cp_el2p_j3_2__el2p_j1_2 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 0.000276 | 0.000318 | 0.000128 | 0.237290 | 0.168541 | 7.993103 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 10.176692 | 11.708745 | 3.919423 | 22.388675 | 11.729995 | 10.794163 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 22.873276 | 21.915024 | 8.102161 | 21.884921 | 11.508051 | 10.750909 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 29.498773 | 25.964494 | 10.321277 | 22.693579 | 11.846299 | 10.839103 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 34.912525 | 29.605632 | 12.635616 | 23.212814 | 12.121948 | 10.800269 |
IRAM 30m EMIR
[7]:
from infobs.instruments import IRAM30mEMIR
emir = IRAM30mEMIR(linewidth)
emir.measure(emir.filter_lines(df), obstime)
[7]:
| Av | G0 | Pth | angle | kappa | 13c_o_j1__j0 | 13c_o_j2__j1 | 13c_o_j3__j2 | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 2.304100 | 1.186082 | 2.559229 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 11.045154 | 12.614035 | 7.962028 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 21.275261 | 20.809291 | 12.215755 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 30.982845 | 27.994013 | 21.121263 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 34.579477 | 24.472355 | 8.870162 |
Changing integration time
[8]:
emir.measure(emir.filter_lines(df), 10 * obstime)
[8]:
| Av | G0 | Pth | angle | kappa | 13c_o_j1__j0 | 13c_o_j2__j1 | 13c_o_j3__j2 | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 1.007058 | -0.061244 | -0.406238 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 10.733919 | 11.054353 | 1.201543 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 22.532765 | 20.564771 | 9.082299 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 27.842653 | 29.493280 | 8.562712 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 31.244859 | 32.500944 | 11.883908 |
Changing line width
linewidth mandatory argument.
[9]:
emir = IRAM30mEMIR(linewidth=2 * linewidth)
emir.measure(emir.filter_lines(df), obstime)
[9]:
| Av | G0 | Pth | angle | kappa | 13c_o_j1__j0 | 13c_o_j2__j1 | 13c_o_j3__j2 | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | -5.599257 | 0.029949 | 6.860503 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 8.376963 | 15.003082 | 9.801187 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 17.128225 | 18.203982 | 3.208072 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 29.142781 | 33.710153 | 14.633763 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 35.617939 | 34.560992 | -0.637018 |
Integrated precipitable water vapor
ipwv optional argument. * Available values: 0 (excellent conditions), 1 (good conditions), 2 (normal conditions) * Default: 2
[10]:
emir = IRAM30mEMIR(linewidth, ipwv=0)
emir.measure(emir.filter_lines(df), obstime)
[10]:
| Av | G0 | Pth | angle | kappa | 13c_o_j1__j0 | 13c_o_j2__j1 | 13c_o_j3__j2 | |
|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 3.637652 | -0.302471 | 1.208588 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 13.113089 | 11.641636 | -1.319127 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 23.734262 | 27.891698 | 8.298691 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 27.723701 | 27.294525 | 13.622968 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 31.520066 | 29.115825 | 14.508134 |
Implementing other instruments
[11]:
from infobs.instruments import StandardInstrument
Mount Fuji submillimeter-wave telescope for [CI] lines
[12]:
class Fuji(StandardInstrument):
"""
Obstime must be interpreted as a relative integration time compared with the one achieved in T. Oka et al, 2004 (ApJ).
For simplicity sake, we assume the noise RMS to be identical for both lines.
"""
def __init__(self, linewidth: float, kelvin: bool = True):
super().__init__(
["c_el3p_j1__el3p_j0", "c_el3p_j2__el3p_j1"], linewidth, kelvin
)
@property
def dv(self):
return 1.0 # km/s
@property
def ref_obstime(self):
return {"c_el3p_j1__el3p_j0": 1, "c_el3p_j2__el3p_j1": 1}
@property
def rms(self):
return {"c_el3p_j1__el3p_j0": 0.5, "c_el3p_j2__el3p_j1": 0.5}
@property
def percent(self):
return {"c_el3p_j1__el3p_j0": 20, "c_el3p_j2__el3p_j1": 20}
def __str__(self):
return "Mount Fuji telescope"
[13]:
fuji = Fuji(linewidth)
fuji_obstime = 0.5
fuji.measure(fuji.filter_lines(df), fuji_obstime)
[13]:
| Av | G0 | Pth | angle | kappa | c_el3p_j1__el3p_j0 | c_el3p_j2__el3p_j1 | |
|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | -0.353822 | -0.180102 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 26.541506 | 10.524991 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 18.180540 | 7.015612 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 16.307703 | 11.164658 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 27.354132 | 10.895989 |
SOFIA (Stratospheric Observatory for Infrared Astronomy) for [CII] line
[14]:
class SOFIA(StandardInstrument):
"""
Obstime must be interpreted as a relative integration time compared with the one achieved in Pabst et al, 2017 (A&A).
Calibration error is discussed in Risacher et al, 2016.
"""
def __init__(self, linewidth: float, kelvin: bool = True):
super().__init__(["cp_el2p_j3_2__el2p_j1_2"], linewidth, kelvin)
@property
def dv(self):
return 0.193 # km/s
@property
def ref_obstime(self):
return {"cp_el2p_j3_2__el2p_j1_2": 1}
@property
def rms(self):
return {"cp_el2p_j3_2__el2p_j1_2": 2.25}
@property
def percent(self):
return {"cp_el2p_j3_2__el2p_j1_2": 5}
def __str__(self):
return "SOFIA"
[15]:
sofia = SOFIA(linewidth)
sofia_obstime = 0.25
sofia.measure(sofia.filter_lines(df), fuji_obstime)
[15]:
| Av | G0 | Pth | angle | kappa | cp_el2p_j3_2__el2p_j1_2 | |
|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 7.173556 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 10.857059 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 8.986045 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 12.189415 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 11.791652 |
Mixing instruments
[16]:
from infobs.instruments import MergedInstrument
merged = MergedInstrument([emir, fuji, sofia])
[17]:
merged.measure(merged.filter_lines(df), [obstime, fuji_obstime, sofia_obstime])
[17]:
| Av | G0 | Pth | angle | kappa | 13c_o_j1__j0 | 13c_o_j2__j1 | 13c_o_j3__j2 | c_el3p_j1__el3p_j0 | c_el3p_j2__el3p_j1 | cp_el2p_j3_2__el2p_j1_2 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | -1.394607 | 1.790921 | 1.990865 | 1.067935 | 0.169435 | 8.098664 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 10.271918 | 8.804715 | 5.461707 | 20.382862 | 12.709262 | 10.241453 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 21.093096 | 20.478475 | 8.369292 | 17.634216 | 9.516761 | 8.793674 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 29.499523 | 24.465393 | 9.611141 | 22.491916 | 9.317297 | 10.023532 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 33.713076 | 35.565098 | 13.903594 | 19.555128 | 12.418816 | 6.144656 |
You can use the same instrument with two different integration times with two instances of the same instrument using the restrict_lines method.
In the following example, the second transition of [CI] is integrated 10 times longer.
[18]:
fuji1 = Fuji(linewidth)
fuji1.restrict_lines(["c_el3p_j1__el3p_j0"])
fuji2 = Fuji(linewidth)
fuji2.restrict_lines(["c_el3p_j2__el3p_j1"])
merged = MergedInstrument([emir, fuji1, fuji2, sofia])
merged.measure(
merged.filter_lines(df), [obstime, fuji_obstime, 10 * fuji_obstime, sofia_obstime]
)
[18]:
| Av | G0 | Pth | angle | kappa | 13c_o_j1__j0 | 13c_o_j2__j1 | 13c_o_j3__j2 | c_el3p_j1__el3p_j0 | c_el3p_j2__el3p_j1 | cp_el2p_j3_2__el2p_j1_2 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 0.429596 | 1.290377 | 3.208243 | -0.546726 | -0.145097 | 9.386241 |
| 1 | 5.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 11.208933 | 11.345129 | -2.303984 | 25.432893 | 14.693545 | 13.910911 |
| 2 | 10.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 22.865378 | 19.874641 | 9.037263 | 24.292709 | 12.537440 | 11.606017 |
| 3 | 15.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 25.463512 | 24.593912 | 12.059598 | 23.657297 | 18.576150 | 11.382027 |
| 4 | 20.0 | 100.0 | 100000.0 | 0.0 | 1.0 | 35.870254 | 32.683043 | 19.930144 | 29.086794 | 17.062069 | 11.930846 |
All these instruments can then be used to simulate observations (see simulator.ipynb example notebook).