X-ray Fields for yt

The simplest use of a SourceModel in pyXSIM is to create fields of X-ray emission that can be used in yt to compute emissivities, luminosities, or intensities. These can be computed for geometric objects such as spheres or boxes or can be projected along a sight line. There are two methods to do this which are described below.

Source Fields

One may want to compute fields for the emissivity or the luminosity of a particular source in its rest frame. This can be done using the make_source_fields() method. This method takes a Dataset object from yt, and the minimum and maximum energies of the band you want to create fields for. The example below shows creating source fields for thermal emission from a simulation of a galaxy cluster:

import yt
import pyxsim

ds = yt.load("GasSloshing/sloshing_nomag2_hdf5_plt_cnt_0100",
             default_species_fields="ionized")

emin = 0.1
emax = 10.0
nbins = 1000
Zmet = 0.3 # this dataset does not have a metallicity field, so assume 0.3 Zsolar
source_model = pyxsim.CIESourceModel("apec", emin, emax, nbins, Zmet)

# arguments are the Dataset, and the emin and emax of the
# band
xray_fields = source_model.make_source_fields(ds, 0.5, 7.0)

The fields are created for the Dataset ds, and their names are returned in the xray_fields list:

print(xray_fields)
[('gas', 'xray_emissivity_0.5_7.0_keV'),
 ('gas', 'xray_luminosity_0.5_7.0_keV'),
 ('gas', 'xray_photon_emissivity_0.5_7.0_keV'),
 ('gas', 'xray_count_rate_0.5_7.0_keV')]

Four fields have been created–one for the X-ray emissivity in the chosen band in \(\rm{erg}~\rm{cm}^{-3}~\rm{s}^{-1}\), another for the X-ray luminosity in the chosen band in \(\rm{erg}~\rm{s}^{-1}\), another for the X-ray photon emissivity in \(\rm{photon}~\rm{cm}^{-3}~\rm{s}^{-1}\), and another for the X-ray photon count rate in \(\rm{photon}~\rm{s}^{-1}\). These fields exist in the same way as any other field in yt, and can be used in the same ways.

Querying emissivity values in a sphere:

sp = ds.sphere("c", (500.0, "kpc"))
print(sp['gas', 'xray_emissivity_0.5_7.0_keV'])
[6.75018212e-30 6.63582106e-30 6.45686636e-30 ... 2.59468150e-30
 2.55886161e-30 2.65063999e-30] erg/(cm**3*s)

Summing luminosity in a sphere:

print(sp.sum(("gas", "xray_luminosity_0.5_7.0_keV")))
unyt_quantity(7.73753352e+44, 'erg/s')

Projecting the photon emissivity along a sight line:

prj = yt.ProjectionPlot(ds, "z", xray_fields[-2], width=(0.5, "Mpc"))
prj.save()
_images/projected_emiss.png

It is possible if one desires to adjust the names for the fields that are created using the band_name keyword argument. If specified, this argument will replace the "{emin}_{emax}_keV part of the field name with the string given in band_name:

xray_fields = source_model.make_source_fields(ds, 0.5, 7.0, band_name="broad")
print(xray_fields)
[('gas', 'xray_emissivity_broad'),
 ('gas', 'xray_luminosity_broad'),
 ('gas', 'xray_photon_emissivity_broad'),
 ('gas', 'xray_count_rate_broad')]

Intensity Fields

If one wants to compute the fields that are observed locally from the source that is at a given distance or redshift, this can be done using the make_intensity_fields() method. This method takes a Dataset object from yt, the minimum and maximum energies of the band you want to create fields for, and either the cosmological redshift of the source (which gives the distance) or the local distance for a nearby source. These fields are designed specifically for making projections.

The example below shows creating source fields for thermal emission from a simulation of the circumgalactic medium of a disk galaxy:

import yt
import pyxsim

def hot_gas(pfilter, data):
    pfilter1 = data[pfilter.filtered_type, "temperature"] > 3.0e5
    pfilter2 = data["PartType0", "StarFormationRate"] == 0.0
    pfilter3 = data[pfilter.filtered_type, "density"] < 5.0e-25
    return pfilter1 & pfilter2 & pfilter3

yt.add_particle_filter(
    "hot_gas",
    function=hot_gas,
    filtered_type="gas",
    requires=["temperature", "density"],
)

ds = yt.load("cutout_37.hdf5",
             bounding_box=[[-1000.0, 1000], [-1000.0, 1000], [-1000.0, 1000]])
ds.add_particle_filter("hot_gas")

source_model = pyxsim.IGMSourceModel(
    0.2,
    3.0,
    1000,
    ("hot_gas", "metallicity"),
    binscale="log",
    resonant_scattering=False,
    cxb_factor=0.5,
    kT_max=30.0,
    nh_field=("hot_gas","H_nuclei_density"),
    temperature_field=("hot_gas", "temperature"),
    emission_measure_field=("hot_gas", "emission_measure"),
)

# arguments are the Dataset, the emin and emax of the band, and the redshift
xray_fields = source_model.make_intensity_fields(ds, 0.55, 0.65, redshift=0.01)

The fields are created for the Dataset ds, and their names are returned in the xray_fields list:

print(xray_fields)
[('hot_gas', 'xray_intensity_0.55_0.65_keV'),
 ('hot_gas', 'xray_photon_intensity_0.55_0.65_keV')]

These can be used to make projections:

prj = yt.OffAxisProjectionPlot(ds, [0.0, -1.0, 1.0], xray_fields[-1],
                           width=(0.5,"Mpc"), north_vector=[0.0, 1.0, 1.0])
prj.save()
_images/projected_intensity.png

As with the source fields, it is possible to adjust the names for the fields that are produced by passing in the band_name keyword argument.

Note

At this time, Doppler-shifting of photon energies by motions of the emitting material is not available for the creation of intensity fields in this mode, but it will be available in a future release.

Line Fields

At times it may be more convenient to specify a source or intensity field based on a very narrow bandpass around a line centroid. For this, pyXSIM provides the make_line_source_fields() and make_line_intensity_fields() methods. These are essentially just wrappers around make_source_fields() and make_intensity_fields() which allow one to specify a narrow bandpass around a line centroid and give it a specific name:

src_fields = source_model.make_line_source_fields(
    ds, (0.561, "keV"), (2, "eV"), "O_VII"
)
I_fields = source_model.make_line_intensity_fields(
    ds, (0.64752, "keV"), (3.0, "eV"), "O_VIII", redshift=0.01
)

Otherwise, the properties of the fields are the same as their broader counterparts.