-
Notifications
You must be signed in to change notification settings - Fork 3
Home
iris is a Python library to generate slab models of molecular emission in disks.
- Installation
-
Background
2.1 Slab Models
2.2 Keplerian Broadening -
Crash Course
3.1 Initial Settings
3.2 Fetching HITRAN Data
3.3 Making a Slab Model
3.4 Compiling the Code - Examples
- FAQ
Install the package via pip:
pip install iris-jwstiris requires the following packages be installed beforehand: jax, pandas, astropy, astroquery
and Python >= 3.8
With iris, the molecular emission lines are modeled using a slab technique, where the intensities are set by an average excitation temperature
We assume the lines are Gaussians and have an intrinsic full-width-at-half-maximum
iris generates an optical depth grid at a very high resolution (
where
Here
Setting a distance to the source of
The rightmost term above sets the final line profile, accounting for saturation effects at the line center:
The flux model is then post-processed by iris to a user-specified resolving power (R) and wavelength grid.
Optionally, we can go a step further and include the effects of Keplerian broadening on the line profiles. iris does this in 4 steps, which only add a couple milliseconds to the compute time:
- Make a standard flux model
$F_{\lambda}$ with turbulent+thermal broadening only. - Generate a flat, Keplerian disk model with inclination
$i$ , stellar mass$M_{*}$ , innermost radius$r_{in}$ , and outermost radius$r_{out}$ . - Finely sample the line-of-sight velocities
$v_{LOS} = v_{K} \sin(i) \cos(\phi)$ within the emitting region, where$v_{K} = (G M_{*}/r)^{0.5}$ is the Keplerian velocity and$\phi$ is the azimuthal angle. Make a normalized histogram ($k_{LOS}$ ) of$v_{LOS}$ . - Convolve
$F_{\lambda}$ with$k_{LOS}$ .
The effects will be most noticeable for disks at high inclinations, very small inner radii, and/or with higher stellar masses.
Whenever we work with iris, first we need to import jax in 64-bit mode. This is very important for the kind of calculations made by iris:
import jax
jax.config.update("jax_enable_x64", True)
We can then import any other useful packages and iris itself:
import jax.numpy as jnp
import numpy as np
import matplotlib.pyplot as plt
import iris as iris
from iris import setup
The very first time we model a molecule, we need to download the corresponding HITRAN spectroscopic data. iris will do this for you.
First we specify a path where we want the data to be downloaded, and then we use setup.setup_linelists to fetch and format the data:
path_to_moldata = './' # path where we want to save the HITRAN data
# Get the data for H$_2$O and $^{13}$CO
setup.setup_linelists('H2O', 'H2O', 1, path_to_moldata)
setup.setup_linelists('CO2', 'CO2', 1, path_to_moldata)
setup.setup_linelists('13CO', 'CO', 2, path_to_moldata)
Note the signature of this function: the first argument is the isotopolog name, this can be whatever you want to name this species, e.g. '13CO' for
- Define a wavelength grid (in micron) to evaluate opacities. The spacing should correspond to an
$R \sim 10^{5-6}$ or whatever is enough to sample the intrinsic line widths$\Delta V$ you want.
fine_wgrid = np.arange(11.5, 18.5, 1e-5)
Here we make a wavelength grid from 11.5 to 18.5 micron, spaced out by
- Define a wavelength to downsample the final flux model. This will usually be the wavelength grid of your data.
obs_wgrid = np.arange(12.0,18.0,0.002)
Be careful obs_wgrid is within fine_wgrid, otherwise it's impossible to downsample the model.
- Define the resolving power of the instrument
R = 3200
iris will convolve the flux density model with a Gaussian of equivalent width to the resolving power provided.
- Initialize the
slabobject. You only need to do this once, it will take a few seconds to parse the molecular data.
slab = iris.slab(molecules=['CO2', 'H2O'], wlow=11.0, whigh=19.0, path_to_moldata=path_to_moldata)
We have created a slab object to model
- iris will model the molecules in the order provided.
- The
wlowandwhighmin. and max. wavelengths should extend beyond the wavelength range spanned byfine_wgrid. Otherwise, you risk missing molecular lines. Still, the code will be faster when using a smaller wavelength range.
- Set up the wavelength grid in the
slab:
slab.setup_grid(fine_wgrid, obs_wgrid, R)
We call setup_grid any time we want to update the wavelength grid.
- Define your disk parameters.
Distance to source:
distance = 120 # pc
The temperature, column density, emitting area, and
# Excitation temperatures for each molecule in K
T_ex = np.array([np.array([800.0, 400.0, 200.0]),
np.array([800.0, 400.0, 200.0])])
# column densities in cm^-2
N_mol = np.array([np.array([1e16, 5e16, 1e16]),
np.array([5e18, 5e17, 1e17])])
# emitting areas in au^2
A_au = np.array([np.array([0.1, 1.0, 10.0]),
np.array([0.1, 1.0, 10.0])])
# intrinsic line widths in km/s (line FWHM)
dV = np.array([np.array([2.0, 2.0, 2.0]),
np.array([2.0, 2.0, 2.0])])
Here we are modeling 3 slabs for
- Set up the disk object. For now, let's ignore Keplerian broadening.
We call the slab.setup_disk module every time we wish to update a physical parameter.
slab.setup_disk(distance, T_ex=T_ex, N_mol=N_mol, A_au=A_au, dV=dV)
- Generate the slab model.
We use the slab.simulate module to calculate the slab model.
slab.simulate()
The full flux density model can then be accessed as flux.flux_model. The downsampled and convolved model is slab.downsampled_flux.
plt.figure(figsize=(17,4))
plt.plot(obs_wgrid, normal, color='orangered', lw=1)
plt.xlim(12, 18.0)
plt.tick_params(direction='in', top=True, right=True, length=5, labelsize=14)
plt.xlabel('Wavelength ($\mu$m)', fontsize=17)
plt.ylabel('Flux (Jy)', fontsize=17)
fff
...