Quickstart#
This is a concise introduction to pyathena, aimed mainly at new users.
Start by importing the necessary modules.
To use pyathena, add its directory to the PYTHONPATH
environment variable in .bashrc
or .bash_profile
export PYTHONPATH=/path/to/directory:$PYTHONPATH
Alternatively, you can dynamically add the path in your script or notebook.
import sys
sys.path.insert(0, '..')
import pyathena as pa
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import xarray as xr
LoadSim class#
The LoadSim
class is the primary interface for handling Athena/Athena++ simulation data.
Use the help()
function to access documentation for the class:
help(pa.LoadSim)
Pro Tip: Use class_or_func_name?
, class_or_func_name??
, help(class_or_func_name)
, or Shift+Tab in an interactive Python environment to view documentation, summaries, or source code.
Initialization#
Simulation Directory:
LoadSim
uses thebasedir
parameter to locate all output files (hst
,hdf5
,vtk
, etc.).Save Directory: The
savdir
parameter defines the directory for saving pickles and figures. If unspecified, it defaults tobasedir
.Logger: A logger is attached to the
LoadSim
instance print out log messages. The verbosity can be adjusted by settingverbose
toTrue
(equivalent"INFO"
) orFalse
(equivalent"WARNING"
) or different levels of logging"DEBUG"
,"INFO"
,"WARNING"
,"ERROR"
(case insensitive). The default is set toFalse
.Metadata : During the initialization,
FindFiles
class is initialized withinLoadSim
and it tries to find the athinput file and (e.g.,athinput.runtime
) or a file (e.g.,out.txt
) where standard output is redirected to. It then reads in simulations parameters and code configuration and saves results to a dictionary of dictionaries,par
, containing all information. Other important metadata include information about the computational domain (domain
), the date and time when code was configured (config_time
).Finding files : Find output files based on the information available from par. The
find_files()
method can be called to find file names (files
) and lists of snapshot numbers (nums*
) again. File formats includeAthena-TIGRESS :
hst
,sn
,zprof
,vtk
,starpar_vtk
,rst
,timeit
TIGRIS :
hst
,sn
,zprof
,hdf5
,rst
,loop_time/task_time
import sys
sys.path.insert(0, '..')
import pyathena as pa
basedir = '/tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/'
s = pa.LoadSim(basedir, verbose=True)
[LoadSim-INFO] basedir: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0
[LoadSim-INFO] savdir: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0
[LoadSim-INFO] load_method: pyathena
[FindFiles-INFO] athinput: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/out.txt
[FindFiles-INFO] athena_pp: False
[FindFiles-INFO] problem_id: R8_8pc_NCR
[FindFiles-INFO] vtk in tar: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/vtk nums: 200-668
[FindFiles-INFO] hst: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/hst/R8_8pc_NCR.hst
[FindFiles-INFO] sn: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/hst/R8_8pc_NCR.sn
[FindFiles-INFO] zprof: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/zprof nums: 200-668
[FindFiles-INFO] starpar_vtk: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/starpar nums: 200-668
[FindFiles-INFO] rst: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/rst/0010 nums: 10-34
[FindFiles-INFO] timeit: /tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/timeit.txt
Attributes#
Print some (read-only) attributes of a LoadSim
instance.
s.basedir
'/tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0'
s.basename
'R8_8pc_NCR.full.xy2048.eps0.0'
s.problem_id
'R8_8pc_NCR'
domain
contains information about simulation domain
Nx: Number of cells
le/re: left/right edge
Lx: box size
dx: cell size
s.domain
{'Nx': array([128, 128, 768]),
'ndim': 3,
'le': array([ -512, -512, -3072]),
're': array([ 512, 512, 3072]),
'Lx': array([1024, 1024, 6144]),
'dx': array([8., 8., 8.]),
'center': array([0., 0., 0.]),
'time': None}
Date and time when the code is compiled
s.config_time
Timestamp('2022-05-18 14:19:25-0700', tz='US/Pacific')
par
contains all input parameters and meta information
s.par.keys()
dict_keys(['job', 'log', 'output1', 'output2', 'output3', 'output4', 'output5', 'time', 'domain1', 'problem', 'feedback', 'cooling', 'opacity', 'radps', 'configure'])
s.par['configure'].keys()
dict_keys(['config_date', 'config_server', 'git_commit_ID', 'problem', 'gas', 'eq_state', 'nscalars', 'self-gravity', 'resistivity', 'viscosity', 'thermal_conduction', 'cooling', 'new_cooling', 'particles', 'sixray', 'radps', 'ionrad', 'lwrad', 'species_HI', 'species_H2', 'species_EL', 'species_CI', 'test_newcool', 'scalar_CL', 'star_particles', 'coord', 'special_relativity', 'order', 'flux', 'integrator', 'precision', 'write_ghost', 'mpi', 'H-correction', 'FFT', 'ShearingBox', 'RaytPlaneParallel', 'FARGO', 'FOFC', 'SMR'])
s.par['output2']
{'out_fmt': 'vtk',
'out': 'prim',
'dt': 1.0,
'time': 201.0,
'num': 200,
'level': -1,
'domain': -1,
'id': 'out2',
'new_output_directory': 1}
s.par['time']
{'selfg_no': 1,
'cour_no': 0.3,
'nlim': -1,
'tlim': 700.0,
'time': 200.0007,
'nstep': 0}
s.par['problem']
{'gamma': 1.66666667,
'surf': 12.0,
'sz0': 10,
'vturb': 10,
'beta': 1,
'qshear': 1.0,
'Omega': 0.028,
'SurfS': 42.0,
'zstar': 245.0,
'rhodm': 0.0064,
'R0': 8000,
'Sigma_SFR': 0.005,
'Z_gas': 1.0,
'Z_dust': 1.0,
'xi_CR_amp': 1.0,
'rho_crit': 1.0,
'starpar_iacc': 0,
'muH': 1.4,
'Sigma_gas0': 10.0,
'Sigma_SFR0': 0.0025,
'tdecay_CR': -1.0}
Other attributes.
s.verbose # can be changed at any time
True
s.savdir
'/tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0'
s.load_method
'pyathena'
s.out_fmt
['hst', 'vtk', 'starpar_vtk', 'rst', 'zprof']
Finding files#
NOTE: If find_files()
did not succeed in finding output files under basedir
, check if the glob patterns s.ff.patterns
are set appropriately. Update it and try again. For example, the history dump is found using the glob patterns /path_to_basedir/id0/*.hst
first. If it fails, it searches again with /path_to_basedir/hst/*.hst
, and then with /path_to_basedir/*.hst
s.files.keys()
dict_keys(['athinput', 'vtk_tar', 'hst', 'sn', 'zprof', 'starpar_vtk', 'rst', 'timeit'])
s.files['vtk_tar'][0], s.files['vtk_tar'][-1]
('/tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/vtk/R8_8pc_NCR.0200.tar',
'/tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/vtk/R8_8pc_NCR.0668.tar')
s.nums[0], s.nums[-1], s.nums_starpar[0], s.nums_starpar[-1]
(200, 668, 200, 668)
type(s.ff)
pyathena.find_files.FindFiles
s.ff.patterns.keys()
dict_keys(['athinput', 'hst', 'sphst', 'sn', 'vtk', 'vtk_id0', 'vtk_tar', 'vtk_athenapp', 'hdf5', 'starpar_vtk', 'partab', 'parhst', 'zprof', 'timeit', 'looptime', 'tasktime', 'rst'])
s.ff.patterns['hst']
[('id0', '*.hst'), ('hst', '*.hst'), ('*.hst',)]
s.ff.patterns['vtk']
[('vtk', '*.????.vtk'), ('*.????.vtk',)]
s.ff.patterns['hdf5']
[('hdf5', '*.out?.?????.athdf'), ('*.out?.?????.athdf',)]
Units#
Simulations run with Athena-TIGRESS/TIGRIS use the following code units
TIGRESS-classic:
Mean particle mass per H: \(\mu_{\rm H} = 1.4271\)
\(1\;{code\_density} \leftrightarrow n_{\rm H} = 1 {\rm cm}^{-3}\)
Length : 1 pc
Velocity : 1 km/s
TIGRESS-NCR:
Mean particle mass per H: \(\mu_{\rm H} = 1.4\)
\(1\;{code\_density} \leftrightarrow n_{\rm H} = 1 {\rm cm}^{-3}\)
Length : 1 pc
Velocity : 1 km/s
TIGRIS with
"ism"
units:Mean particle mass per H: \(\mu_{\rm H} = 1.4\)
\(1.4\;{code\_density} \leftrightarrow \rho = 1.4 m_{\rm H}\;{\rm cm}^{-3} \leftrightarrow n_{\rm H} = 1 {\rm cm}^{-3}\)
Length : 1 pc
Velocity : 1 km/s
u = s.u
# or
# u = pa.Units(kind='LV', muH=1.4)
Print code units (astropy Quantity)
type(s.u.time)
astropy.units.quantity.Quantity
s.u.time, s.u.mass, s.u.density, s.u.length, s.u.velocity, s.u.muH,
(<Quantity 3.08567758e+13 s>,
<Quantity 0.03462449 solMass>,
<Quantity 2.34335273e-24 g / cm3>,
<Quantity 1. pc>,
<Quantity 1. km / s>,
1.4)
s.u.energy, s.u.energy_density, s.u.momentum, s.u.momentum_flux
(<Quantity 6.88476785e+41 erg>,
<Quantity 2.34335273e-14 erg / cm3>,
<Quantity 0.03462449 km solMass / s>,
<Quantity 0.03541089 km solMass / (s yr kpc2)>)
Commonly used astronomical constants and units (plain numbers). Multiply them to convert quantities in code units to one in physical units. For example,
(code mass)*u.Msun = mass in Msun
(code time)*u.Myr = time in Myr
(code luminosity)*u.Lsun = luminosity in Lsun
(code pressure)*u.pok = P/k_B in cm^-3 K
s.u.Msun, s.u.Myr, s.u.Lsun, s.u.pc, s.u.kms, s.u.pok
(0.034624490427439196,
0.9777922216807893,
5.82863455377993e-06,
1.0,
1.0,
169.7283473776405)
VTK dump#
print(s.nums[0], s.nums[-1], len(s.nums)) # vtk file numbers in the directory
200 668 469
ds = s.load_vtk(num=s.nums[0])
[LoadSim-INFO] [load_vtk_tar]: R8_8pc_NCR.0200.tar. Time: 200.000700
ds.domain
{'all_grid_equal': True,
'ngrid': 384,
'le': array([ -512., -512., -3072.], dtype=float32),
're': array([ 512., 512., 3072.], dtype=float32),
'dx': array([8., 8., 8.], dtype=float32),
'Lx': array([1024., 1024., 6144.], dtype=float32),
'center': array([0., 0., 0.], dtype=float32),
'Nx': array([128, 128, 768]),
'ndim': 3,
'time': 200.0007}
ds.domain == s.domain
True
Note that domain['time']
is updated after reading loading a vtk file.
Field names#
The field_list
contains all available variable names in vtk file, representing the raw data. The derived_field_list
includes variables that are calculated based on those in the field_list
, often expressed in more convenient units. Usually, fields in derived_field_list
are in more convenient units. When in doubt, it is recommended to use variables from the field_list
and calculate derived quantities yourself.
print(ds.field_list)
['density', 'velocity', 'pressure', 'cell_centered_B', 'gravitational_potential', 'temperature', 'heat_rate', 'cool_rate', 'net_cool_rate', 'CR_ionization_rate', 'rad_energy_density_PH', 'rad_energy_density_LW', 'rad_energy_density_PE', 'rad_energy_density_LW_diss', 'specific_scalar[0]', 'specific_scalar[1]', 'xHI', 'xH2', 'xe']
print(ds.derived_field_list)
['rho', 'nH', 'pok', 'r', 'vmag', 'vr', 'vx', 'vy', 'vz', 'cs', 'csound', 'Mr', 'Mr_abs', 'rhovr2ok', 'T', 'Td', 'cool_rate', 'heat_rate', 'net_cool_rate', 'Lambda_cool', 'nHLambda_cool', 'nHLambda_cool_net', 'Gamma_heat', 't_cool', 'vAmag', 'vAx', 'vAy', 'vAz', 'Bx', 'By', 'Bz', 'Bmag', 'nH2', '2nH2', 'xH2', '2xH2', 'nHI', 'xHI', 'nHII', 'xHII', 'nHn', 'xn', 'ne', 'nesq', 'xe', 'xCI', 'nCI', 'xOII', 'xCII', 'xCII_alt', 'xi_CR', 'T_alt', 'chi_PE', 'chi_LW', 'chi_FUV', 'Erad_LyC', 'Jphot_LyC', 'Uion', 'j_Halpha', 'Erad_FUV', 'heat_ratio', 'NHeff', 'heat_rate_HI_phot', 'heat_rate_H2_phot', 'heat_rate_dust_LyC', 'heat_rate_dust_FUV', 'heat_rate_dust_UV', 'psi_gr', 'eps_pe', 'Gamma_pe', 'chi_H2', 'chi_CI', 'fshld_H2', 'j_X']
ds.dirname, ds.ext
('/tigress/changgoo/TIGRESS-NCR/R8_8pc_NCR.full.xy2048.eps0.0/vtk', 'tar')
Read 3d data cubes#
With xarray=True
option (default is True), read dataset as a xarray DataSet.
See http://xarray.pydata.org/en/stable/quick-overview.html for a quick overview of xarray.
help(ds.get_field) # Note: setting (le, re) manually may not work as intended
Help on method get_field in module pyathena.io.read_vtk:
get_field(field='density', le=None, re=None, as_xarray=True) method of pyathena.io.read_vtk_tar.AthenaDataSetTar instance
Read 3d fields data.
Parameters
----------
field : (list of) string
The name of the field(s) to be read.
le : sequence of floats
Left edge. Default value is the domain left edge.
re : sequence of floats
Right edge. Default value is the domain right edge.
as_xarray : bool
If True, returns results as an xarray Dataset. If False, returns a
dictionary containing numpy arrays. Default value is True.
Returns
-------
dat : xarray dataset
An xarray dataset containing fields.
dat = ds.get_field(['nH', 'pok', 'T'])
Indexing follows the convention of the Athena code (k,j,i): for scalar fields, the innermost (fastest running) index is the x-direction, while the outermost index is the z-direction
dat['nH'].shape
(768, 128, 128)
dat
<xarray.Dataset> Dimensions: (x: 128, y: 128, z: 768) Coordinates: * x (x) float64 -508.0 -500.0 -492.0 -484.0 ... 484.0 492.0 500.0 508.0 * y (y) float64 -508.0 -500.0 -492.0 -484.0 ... 484.0 492.0 500.0 508.0 * z (z) float64 -3.068e+03 -3.06e+03 -3.052e+03 ... 3.06e+03 3.068e+03 Data variables: nH (z, y, x) float32 0.0001338 0.0001325 ... 0.0003592 0.0003528 T (z, y, x) float32 2.277e+06 2.316e+06 ... 2.397e+06 2.451e+06 pok (z, y, x) float32 700.5 705.4 707.3 ... 1.98e+03 1.988e+03 Attributes: all_grid_equal: True num: 200 ngrid: 384 le: [ -512. -512. -3072.] re: [ 512. 512. 3072.] dx: [8. 8. 8.] Lx: [1024. 1024. 6144.] center: [0. 0. 0.] Nx: [128 128 768] ndim: 3 time: 200.0007 dfi: {'rho': {'field_dep': ['density'], 'func': <function set...
dat.x
<xarray.DataArray 'x' (x: 128)> array([-508., -500., -492., -484., -476., -468., -460., -452., -444., -436., -428., -420., -412., -404., -396., -388., -380., -372., -364., -356., -348., -340., -332., -324., -316., -308., -300., -292., -284., -276., -268., -260., -252., -244., -236., -228., -220., -212., -204., -196., -188., -180., -172., -164., -156., -148., -140., -132., -124., -116., -108., -100., -92., -84., -76., -68., -60., -52., -44., -36., -28., -20., -12., -4., 4., 12., 20., 28., 36., 44., 52., 60., 68., 76., 84., 92., 100., 108., 116., 124., 132., 140., 148., 156., 164., 172., 180., 188., 196., 204., 212., 220., 228., 236., 244., 252., 260., 268., 276., 284., 292., 300., 308., 316., 324., 332., 340., 348., 356., 364., 372., 380., 388., 396., 404., 412., 420., 428., 436., 444., 452., 460., 468., 476., 484., 492., 500., 508.]) Coordinates: * x (x) float64 -508.0 -500.0 -492.0 -484.0 ... 484.0 492.0 500.0 508.0
Mean value of nH, pressure/kB at the midplane
dat.sel(z=0, method='nearest').mean()
<xarray.Dataset> Dimensions: () Coordinates: z float64 4.0 Data variables: nH float32 0.8858 T float32 6.296e+05 pok float32 9.153e+03
Slice plots#
Use
dat.dfi
ors.dfi
(derived field info) to set plot argumentsSee also https://docs.xarray.dev/en/latest/generated/xarray.plot.imshow.html
dat.dfi['nH']
{'field_dep': ['density'],
'func': <function pyathena.fields.fields.set_derived_fields_def.<locals>._nH(d, u)>,
'label': '$n_{\\rm H}\\;[{\\rm cm^{-3}}]$',
'norm': <matplotlib.colors.LogNorm at 0x14a046191780>,
'vminmax': (0.001, 10000.0),
'cmap': 'Spectral_r',
'scale': 'log',
'take_log': True,
'imshow_args': {'norm': <matplotlib.colors.LogNorm at 0x14a046191780>,
'cmap': 'Spectral_r',
'cbar_kwargs': {'label': '$n_{\\rm H}\\;[{\\rm cm^{-3}}]$'}}}
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
dat['nH'].sel(z=0, method='nearest').plot.imshow(ax=axes[0], **dat.dfi['nH']['imshow_args'])
dat['pok'].sel(z=0, method='nearest').plot.imshow(ax=axes[1], **dat.dfi['pok']['imshow_args'])
plt.setp(axes, aspect='equal')
plt.suptitle(f'time={dat.time}')
Text(0.5, 0.98, 'time=200.0007')

Another example: plot slice of density and temperature at z=0
d = ds.get_field(['nH', 'T'])
from pyathena.plt_tools.cmap_shift import cmap_shift
iz = ds.domain['Nx'][2] // 2
fig, axes = plt.subplots(1, 2, figsize=(10,5))
cmap_temp = cmap_shift(mpl.cm.RdYlBu_r, midpoint=3.0/7.0)
axes[0].imshow(d['nH'][iz,:,:], norm=LogNorm(), origin='lower')
axes[1].imshow(d['T'][iz,:,:], norm=LogNorm(), origin='lower',
cmap=cmap_temp)
<matplotlib.image.AxesImage at 0x14a041c689d0>

get_slice()
method#
help(ds.get_slice)
Help on method get_slice in module pyathena.io.read_vtk:
get_slice(axis, field='density', pos='c', method='nearest') method of pyathena.io.read_vtk_tar.AthenaDataSetTar instance
Read slice of fields.
Parameters
----------
axis : str
Axis to slice along. 'x' or 'y' or 'z'
field : (list of) str
The name of the field(s) to be read.
pos : float or str
Slice through If 'c' or 'center', get a slice through the domain
center. Default value is 'c'.
method : str
Returns
-------
slc : xarray dataset
An xarray dataset containing slices.
slc = ds.get_slice('y', ['nH', 'T', 'pressure']) # x-z slices
slc
<xarray.Dataset> Dimensions: (z: 768, x: 128) Coordinates: * x (x) float64 -508.0 -500.0 -492.0 -484.0 ... 492.0 500.0 508.0 y float64 4.0 * z (z) float64 -3.068e+03 -3.06e+03 -3.052e+03 ... 3.06e+03 3.068e+03 Data variables: pressure (z, x) float32 2.693 2.68 2.657 2.631 ... 11.88 11.52 11.16 10.87 nH (z, x) float32 0.0001072 0.0001052 ... 0.0004483 0.0004352 T (z, x) float32 1.855e+06 1.881e+06 ... 1.839e+06 1.844e+06 Attributes: all_grid_equal: True num: 200 ngrid: 384 le: [ -512. -512. -3072.] re: [ 512. 512. 3072.] dx: [8. 8. 8.] Lx: [1024. 1024. 6144.] center: [0. 0. 0.] Nx: [128 128 768] ndim: 3 time: 200.0007 dfi: {'rho': {'field_dep': ['density'], 'func': <function set...
type(slc), type(slc.nH), type(slc.nH.data)
(xarray.core.dataset.Dataset, xarray.core.dataarray.DataArray, numpy.ndarray)
fig, axes = plt.subplots(1, 2, figsize=(8, 12), constrained_layout=True)
im1 = slc['nH'].plot(ax=axes[0], norm=LogNorm())
im2 = slc['T'].plot(ax=axes[1], norm=LogNorm(), cmap=cmap_temp)
for im in (im1, im2):
im.axes.set_aspect('equal')

2d histogram#
lognH = np.log10(dat['nH'].data.flatten())
logT = np.log10(dat['T'].data.flatten())
# mass-weighted histograms
wgt = dat['nH'].data.flatten()
plt.hexbin(lognH, logT, wgt, mincnt=1, norm=mpl.colors.LogNorm())
plt.xlabel(r'$\log_{10}\,n_{\rm H}$')
plt.ylabel(r'$\log_{10}\,T$')
Text(0, 0.5, '$\\log_{10}\\,T$')

Plot projection and star particles#
sp = s.load_starpar_vtk(num=s.nums_starpar[0])
sp.columns
[LoadSim-INFO] [load_starpar_vtk]: R8_8pc_NCR.0200.starpar.vtk. Time: 200.000700
Index(['id', 'flag', 'n_ostar', 'mass', 'age', 'mage', 'metal_mass[0]',
'metal_mass[1]', 'metal_mass[2]', 'metal_mass[3]', 'metal_mass[4]',
'x1', 'x2', 'x3', 'v1', 'v2', 'v3'],
dtype='object')
sp
id | flag | n_ostar | mass | age | mage | metal_mass[0] | metal_mass[1] | metal_mass[2] | metal_mass[3] | metal_mass[4] | x1 | x2 | x3 | v1 | v2 | v3 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | -2 | 0 | 1.517063e+05 | 231.347687 | 231.347687 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | -128.291458 | -450.330017 | 34.969208 | -3.673561 | -0.497162 | 2.552266 |
1 | 1 | -2 | 0 | 1.142920e+05 | 200.281982 | 200.281982 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | -451.638062 | 448.136475 | 1.251051 | -1.985113 | 13.861067 | -0.561060 |
2 | 2 | -2 | 0 | 1.029942e+06 | 219.190628 | 219.190628 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | -352.151489 | -204.598938 | 3.780031 | 5.817396 | 9.692892 | -1.035785 |
3 | 3 | -2 | 0 | 2.885881e+05 | 236.061691 | 236.061691 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | -46.320374 | 399.499939 | -45.633480 | 1.270643 | 1.333141 | 7.092731 |
4 | 4 | -2 | 0 | 8.737053e+04 | 224.225128 | 224.225128 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | -169.073090 | -75.030182 | -7.814175 | 9.002285 | 5.097887 | -2.412747 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
264 | 3619 | -1 | 0 | 0.000000e+00 | -9.412859 | 12.259128 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | -17.949648 | -436.911743 | 68.887535 | 14.285395 | 42.216995 | 70.368149 |
265 | 3620 | -1 | 0 | 0.000000e+00 | -0.123773 | 4.554963 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 250.112442 | 487.829712 | -12.737943 | -6.930785 | -8.410844 | 22.714880 |
266 | 3621 | -1 | 0 | 0.000000e+00 | -24.058840 | 4.369840 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | -214.895584 | -250.390366 | -6.121937 | -21.697975 | 38.959778 | -75.154793 |
267 | 3622 | -1 | 0 | 0.000000e+00 | -15.175461 | 12.259128 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | -19.128952 | -454.030334 | 57.308399 | 13.182298 | -40.273441 | 46.820534 |
268 | 3623 | -1 | 0 | 0.000000e+00 | -1.964489 | 25.226053 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 72.532875 | -66.833473 | 8.098772 | 2.340160 | -29.183071 | 6.838042 |
269 rows × 17 columns
from pyathena.plt_tools.plt_starpar import scatter_sp
fig, ax = plt.subplots(1, 1, figsize=(6.5, 5))
d = ds.get_field('rho')
conv_Sigma = (1.0*au.g/au.cm**2).to('Msun pc-2').value
dz_cgs = ds.domain['dx'][2]*u.length.cgs.value
(d['rho'].sum(dim='z')*dz_cgs*conv_Sigma).plot.imshow(ax=ax,
cmap='pink_r', norm=mpl.colors.LogNorm(0.1, 2e2),
cbar_kwargs=dict(label=r'$\Sigma_{\rm gas}\;[M_{\odot}\,{\rm pc}^{-2}]$'))
ax.set_aspect('equal')
# Plot projected positions of star particles
# age < agemax : colored circles
# agemax < age_Myr < agemax_sn : grey circles
# with agemax = 20 Myr ; agemax_sn = 40Myr
scatter_sp(sp, ax, dim='z')

LoadSimTIGRESSNCR class#
For TIGRESS-classic and TIGRESS-NCR simulations, many derived information (such as total luminosity, number of sources) are calculated in pyathena/tigress_ncr/starpar.py
from pyathena.tigress_ncr.load_sim_tigress_ncr import LoadSimTIGRESSNCR
s = LoadSimTIGRESSNCR(basedir)
# s.print_all_properties()
Suppress warning
s.verbose = 'ERROR'
If you do not have permission to basedir
, save pickles to a different directory, e.g., /home/USERNAME/basename/
s.savdir = os.path.join(os.path.expanduser('~'), s.basename)
star = s.read_starpar_all(force_override=True, savdir=s.savdir)
star.keys()
Index(['time', 'nstars', 'isrc', 'nsrc', 'sp_src', 'z_max', 'z_min',
'z_mean_mass', 'z_mean_Qi', 'z_mean_LFUV', 'stdz_mass', 'stdz_Qi',
'stdz_LFUV', 'Qi_tot', 'L_LW_tot', 'L_PE_tot', 'L_FUV_tot', 'Phi_i',
'Sigma_FUV', 'sp'],
dtype='object')
plt.plot(star['time']*s.u.Myr, star['Qi_tot']) # Total ionizing photon rate [1/s]
plt.setp(plt.gca(), xlabel='time [Myr]', ylabel='Qi_tot')
[Text(0.5, 0, 'time [Myr]'), Text(0, 0.5, 'Qi_tot')]

History dump#
# Read raw hst dump
h = pa.read_hst(s.files['hst']) # returns a pandas DataFrame object
h.columns
Index(['time', 'dt', 'mass', 'totalE', 'x1Mom', 'x2Mom', 'x3Mom', 'x1KE',
'x2KE', 'x3KE', 'x1ME', 'x2ME', 'x3ME', 'gravPE', 'scalar0', 'scalar1',
'scalar2', 'scalar3', 'scalar4', 'dmasssink', 'dM1sink', 'dM2sink',
'dM3sink', 'dEsink', 'heat_ratio', 'heat_ratio_mid',
'heat_ratio_mid_2p', 'ftau', 'x2dke', 'nmid', 'Pth_mid', 'Pturb_mid',
'Vmid_2p', 'nmid_2p', 'Pth_mid_2p', 'Pturb_mid_2p', 'sfr10', 'sfr40',
'sfr100', 'msp', 'metal_sp', 'total_ecool', 'total_eheat', 'total_enet',
'V_Erad_PH', 'Lmasked_HI_PH', 'Lmasked_H2_PH', 'Lmasked_dust_PH',
'Lmasked_dust_LW', 'Lmasked_dust_PE', 'phot_rate_HI', 'phot_rate_H2',
'rec_rate_rad_HII', 'rec_rate_gr_HII', 'xi_CR0', 'Ltot0', 'Ltot1',
'Ltot2', 'Ltot3', 'Lesc0', 'Lesc1', 'Lesc2', 'Lesc3', 'Ldust0',
'Ldust1', 'Ldust2', 'Ldust3', 'Lxymax0', 'Lxymax1', 'Lxymax2',
'Lxymax3', 'Lpp0', 'Lpp1', 'Lpp2', 'Lpp3'],
dtype='object')
h.head()
time | dt | mass | totalE | x1Mom | x2Mom | x3Mom | x1KE | x2KE | x3KE | ... | Ldust2 | Ldust3 | Lxymax0 | Lxymax1 | Lxymax2 | Lxymax3 | Lpp0 | Lpp1 | Lpp2 | Lpp3 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 200.000700 | 0.002155 | 0.052018 | 24.523072 | -0.010668 | -0.114090 | 0.149412 | 2.067014 | 3.001098 | 3.706466 | ... | 2.404333e+12 | 653.116688 | 4.696874e+09 | 1.815048e+09 | 2.867097e+10 | 5.840392e+11 | 0.0 | 2.298291e+11 | 1.069728e+12 | 2.893340e+12 |
1 | 200.011568 | 0.002198 | 0.052018 | 24.417614 | -0.010663 | -0.114099 | 0.149376 | 2.056071 | 2.992799 | 3.695838 | ... | 2.404154e+12 | 653.411037 | 4.695982e+09 | 1.814261e+09 | 2.866940e+10 | 5.840334e+11 | 0.0 | 2.299529e+11 | 1.069950e+12 | 2.893498e+12 |
2 | 200.020375 | 0.002232 | 0.052018 | 24.338644 | -0.010658 | -0.114106 | 0.149347 | 2.047250 | 2.986004 | 3.686907 | ... | 2.398275e+12 | 650.927607 | 4.816156e+09 | 1.817778e+09 | 2.867580e+10 | 5.828847e+11 | 0.0 | 2.297048e+11 | 1.068698e+12 | 2.887522e+12 |
3 | 200.031582 | 0.002255 | 0.052018 | 24.242892 | -0.010653 | -0.114116 | 0.149309 | 2.036098 | 2.977272 | 3.675242 | ... | 2.391494e+12 | 648.406112 | 4.969366e+09 | 1.817014e+09 | 2.865399e+10 | 5.816466e+11 | 0.0 | 2.297736e+11 | 1.068160e+12 | 2.881460e+12 |
4 | 200.040671 | 0.002297 | 0.052018 | 24.166606 | -0.010648 | -0.114124 | 0.149279 | 2.027186 | 2.970138 | 3.665638 | ... | 2.391494e+12 | 648.406112 | 4.969366e+09 | 1.817014e+09 | 2.865399e+10 | 5.816466e+11 | 0.0 | 2.297736e+11 | 1.068160e+12 | 2.881460e+12 |
5 rows × 75 columns
Plot
timestep size
dt_mhd
(code unit)(total gas mass)/(volume of box) (code units)
\(\Sigma_{\rm SFR,40 Myr}\) (Msun/yr/kpc^2)
ax = h.plot('time', y=['dt','mass', 'sfr40'])
ax.set_yscale('log')

Read history dump post-processed (and saved to a pickle) using the script pyathena/tigress_ncr/hst.py
h = s.read_hst()
h.columns
Index(['time_code', 'time', 'time_orb', 'dt_code', 'dt', 'mass', 'mass_sp',
'mass0', 'mass1', 'mass2', 'mass3', 'mass4', 'M_HI', 'Sigma_HI', 'M_H2',
'Sigma_H2', 'M_HII', 'Sigma_HII', 'massflux_lbd_d', 'massflux_ubd_d',
'mass_out', 'Sigma_gas', 'Sigma_sp', 'Sigma_out', 'mass_snej',
'Sigma_snej', 'H', 'mf_c', 'vf_c', 'H_c', 'mf_u', 'vf_u', 'H_u',
'mf_w1', 'vf_w1', 'H_w1', 'mf_w2', 'vf_w2', 'H_w2', 'mf_h1', 'vf_h1',
'H_h1', 'mf_h2', 'vf_h2', 'H_h2', 'mf_w', 'vf_w', 'H_w', 'mf_2p',
'vf_2p', 'H_2p', 'KE', 'ME', 'v1', 'vA1', 'v1_2p', 'v2', 'vA2', 'v2_2p',
'v3', 'vA3', 'v3_2p', 'cs', 'Pth_mid', 'Pth_mid_2p', 'Pturb_mid',
'Pturb_mid_2p', 'nmid', 'nmid_2p', 'sfr10', 'sfr40', 'sfr100',
'Ltot_PH', 'Lesc_PH', 'Ldust_PH', 'Qtot_PH', 'Qesc_PH', 'Qtot_cum_PH',
'Qesc_cum_PH', 'fesc_PH', 'fesc_cum_PH', 'Ltot_LW', 'Lesc_LW',
'Ldust_LW', 'Qtot_LW', 'Qesc_LW', 'Qtot_cum_LW', 'Qesc_cum_LW',
'fesc_LW', 'fesc_cum_LW', 'Ltot_PE', 'Lesc_PE', 'Ldust_PE', 'Qtot_PE',
'Qesc_PE', 'Qtot_cum_PE', 'Qesc_cum_PE', 'fesc_PE', 'fesc_cum_PE',
'xi_CR0'],
dtype='object')