Including background in a marx simulation¶
The data from all Chandra observations includes different background components: Astrophysical background (e.g. unresolved sources), instrumental background (e.g. high-energy particles from the sun), and a read-out artifact. The Proposers Observatory Guide describes all these components in detail.
The background matters most for faint or extended sources. In this example we show two different methods to include a background component into a marx simulation. Because marx ray-traces X-ray photons and does not calculate the interaction between spacecraft components and energetic particles, both methods need to make approximations:
The Chandra calibration team has released “blank sky background” files for the ACIS detector. Adding “blank-sky background” to a marx simulation shows how to add observed background events from these files to a marx simulation. This should provide the most realistic background, but there are several caveats:
As described in Current caveats for MARX, marx does not incorporate the non-uniformity maps for the ACIS detector, nor does it employ the spatially varying CTI-corrected pha redistribution matrices (RMFs). As such there always will be systematic differences between the simulated MARX source and the real background data.
The “blank sky” files contain between a 30,000 and a few million photons (depending on the chip). If this procedure is repeated for many marx simulations, it adds photons from the same pool every time, so this cannot be used for a statistical analysis if the total number of background photons approaches the number of photons in the file.
We extract fit the apparent spectrum of the “blank sky” files (“apparent” because the events look like X-ray photons on the CCD, but in reality many are electron or proton impacts) and then use marx to simulate an extended source that produces a similar spectrum (Simulating a background-like source with marx). This approach is easier and faster, but it does not capture all details of the spatial variations of the background.
Warning
Background is time variable!
The background count rate can vary within minutes in so-called flares (example for a background lightcurve), and even the quiescent background level changes over time. Thus, the simulation can only give a prediction of a typical background. The actual background might turn out to be higher or lower.
Warning
Sky background depends on Ra, Dec!
See e.g. Markevitch (2002) for a comparison of Chandra and XMM-Newton data of the same galaxy cluster, where the fitted temperature strongly depends on the background model and the Chandra “blank sky” files underpredict the background flux.
Simulating the source: A diffuse, thermal emission¶
In this example, we model a diffuse emission region with a cool, thermal plasma as they are often seen in massive star forming regions. For the purposes of this example, we do not model the stars themselves, which would show up as additional point sources. We chose a relatively simple model with one thermal emission component in collisional ionization equilibrium with parameters similar to those observed by Güdel et. al (2008) in Orion.
Similar to Creating an input spectrum from a Sherpa model we will use Sherpa to create a 2-column text file that tabulates the flux density [photons/sec/keV/cm^2] (second column) as a function of energy [keV] (first column).
# set source properties
set_source(xsphabs.abs1 * xsapec.apec1)
abs1.nH = 0.01
apec1.kT = 0.1
# get source
my_src = get_source()
# set energy grid
bin_width = 0.01
import numpy as np
energies = np.arange(0.03, 12., bin_width)
# evaluate source on energy grid
flux = my_src(energies)
# Sherpa uses the convention that an energy array holds the LOWER end of the bins;
# Marx that it holds the UPPER end of a bin.
# Thus, we need to shift energies and flux by one bin.
# Also, we need to divide the flux by the bin width to obtain the flux density.
save_arrays("source_flux.tbl", [energies[1:], flux[:-1] / bin_width], ["keV","photons/s/cm**2/keV"], ascii=True)
More details about the format of the marx input spectrum can be found at
SpectrumFile
.
The next step is to run marx in the desired configuration:
marx SourceFlux=0.02 SpectrumType="FILE" SpectrumFile="source_flux.tbl" \
ExposureTime=100000 TStart=2012.5 OutputDir=diffuse \
DetectorType="ACIS-S" DitherModel="INTERNAL" RA_Nom=30 Dec_Nom=40 \
Roll_Nom=0 SourceRA=30 SourceDEC=40 \
SourceType="GAUSS" S-GaussSigma=60
The SourceFlux
sets the observed photon flux by renormalizing the input
spectrum. For the shape of the source we choose a Gaussian that is more than one
arcmin wide and we set the aimpoint on the back-illuminated ACIS-S3 chip (chip ID 7). The results of the
simulation will be written to a subdirectory called diffuse
, as
specified by the OutputDir
parameter. After the simulation has
completed, a standard Chandra event file may be created using the
marx2fits
program:
marx2fits diffuse diffuse_evt2.fits
We also generate an aspect solution file that matches the simulation:
marxasp MarxDir="diffuse" OutputFile="diffuse_asol1.fits"
Adding “blank-sky background” to a marx simulation¶
The “blank sky background” files are part of
CalDB but because of their size
they are not installed by default. If you don’t have them yet, use the
ciao-install script or download them
by hand from http://cxc.harvard.edu/ciao/download/caldb.html . marx does not
simulate all physical effects in Chandra (see Current caveats for MARX) and thus none of
the “blank sky background” files matches the way that marx generates the data
exactly. In particular, marx does not apply the CTI correction, thus we will
use the “blank sky background” files that do not have _cti
in their
filename. The naming convention is
acis<chip><aimpoint>D<date>bkgrndN<version>.fits
.
In this simulation we care for chip-ID 7 and the ACIS-S aimpoint, so we select the most recent background file and copy it to the working directory:
cp $CALDB/data/chandra/acis/bkgrnd/acis7sD2009-09-21bkgrndN0002.fits acis7sbkg.fits
We now need to do some fiddleing with the marx simulation and the background file to make their formats compatible so that we can eventually merge them into a single event file. This involves the following steps:
Select a random subset of photons in the “blank sky file”. We need to
Find the number of rows in that file (header keyword
NAXIS2
).Estimate the number of background photons we want to simulate. Looking at the appropriate table in the Observatory Guide we see that roughly 0.3 cts/s (in the event grades we care for) is a good, conservative estiamte. For an observation of 100 ks, we thus decide to select roughly 30,000 photons.
Events in the “blank sky” files are sorted in x and y. In order to select a random subset, we use dmtcalc to assign a random number in column
randnum
and multiply it with the ratio of the number of photons in the “blank sky” file and the number of photons we want to select.We copy only those photons where the ratio is smaller than 1. Since this involves a random number, this also introduces a “random error” to the number of photons we select - it will not be exactly 30,000.
Add a time column to the “blank sky” file and fill it with random values during the observation.
Reproject the “blank sky” file to the observed position on the sky.
Select the same columns in the marx simulation and the “blank sky” file, so that they can be merged with dmmerge.
Here is the script that we use:
#! /bin/bash
# Pick how many background photons we want to add to our simulation.
n=`dmlist acis7sbkg.fits header,raw | grep NAXIS2 | awk '{ print $6 }'`
dmtcalc acis7sbkg.fits temp.fits expression="randnum=$n/3e4*#trand" clobber=yes
dmcopy "temp.fits[randnum=0:1]" temp2.fits clobber=yes
# Assign some random time during the observation to each photon.
t0=`dmkeypar diffuse_evt2.fits TSTART echo+`
t1=`dmkeypar diffuse_evt2.fits TSTOP echo+`
dmtcalc temp2.fits temp3.fits expression="time=$t0+($t1-$t0)*#trand" clobber=yes
dmsort temp3.fits temp4.fits keys=TIME clobber=yes
# Reproject the blank sky fields to the same position on the sky as the marx simulation.
punlearn reproject_events
reproject_events infile=temp4.fits outfile=acis7s_bkg_reproj.fits aspect=diffuse_asol1.fits match=diffuse_evt2.fits clobber=yes
# Merge marx simulation and blank sky fields into a single fits table.
punlearn dmmerge
dmmerge "diffuse_evt2.fits[cols ccd_id,node_id,chip,det,sky,pha,energy,pi,fltgrade,grade,status,time]","acis7s_bkg_reproj.fits[cols ccd_id,node_id,chip,det,sky,pha,energy,pi,fltgrade,grade,status,time]" merged.fits clobber=yes
If the source in the simulation covers multiple ACIS chips, then this has to be repeated chip-by-chip.
The figure Images of event files shows the marx simulation alone, with added background from the “blank sky” file and with an energy filter that we would probably use for real data to suppresses some of the background.
Looking at the background-free marx simulation, measuring the flux and the size of this source seems like an easy task. When properly including background the source can still be detected, but fitted source parameters will be more uncertain than they would be in a background-free scenario. This example shows how important it is to consider the instrumental background when simulating weak sources.
Simulating a background-like source with marx¶
An alternative approach is to extract a spectrum from the “black-sky” fields and use this spectrum as input for marx. This spectrum does not describe the real physical properties such as the energy of the background events (many of them are not even photons), it just provides an effective way to simulate “something that looks similar to real background when run through marx”.
The advantage of this approach is that we can generate more random events than the original “blank-sky” file has without repeating photons.
First, extract a spectrum from the “blank-sky” background and save this spectrum in a table that marx can read. This can be done with the following commands (a detailed explanation for this is at http://cxc.harvard.edu/ciao/threads/extended/ ):
dmextract infile="acis7s_bkg_reproj.fits[sky=rotbox(1:59:59,+39:59:20,3.2',3.5',0)][bin pi]" outfile='blank_sky.pi' wmap="[bin tdet=8]" clobber=yes
asphist infile=diffuse_asol1.fits outfile=blank_sky.asphist evtfile="diffuse_evt2.fits[ccd_id=7]" clobber=yes
sky2tdet infile="acis7s_bkg_reproj.fits[sky=rotbox(1:59:59,+39:59:20,3.2',3.5',0)][bin sky=8]" asphistfile="blank_sky.asphist" outfile="blank_sky_tdet.fits[wmap]" clobber=yes
mkwarf infile="blank_sky_tdet.fits[wmap]" outfile=blank_sky.arf weightfile=blank_sky.wfef egridspec=0.3:11.0:0.1 mskfile=NONE spectrumfile=NONE pbkfile=NONE clobber=yes
mkrmf infile=CALDB outfile=blank_sky.rmf axis1="energy=0:1" axis2="pi=1:1024:1" weights=blank_sky.wfef clobber=yes
We use Sherpa to display the spectrum on the screen (see
Extracted “blank-sky” spectrum.) and save it in a table
with columns energy and count rate density (see SpectrumFile
for details
of the input spectrum format for marx):
load_data('blank_sky.pi')
load_rmf('blank_sky.rmf')
load_arf('blank_sky.arf')
plot_data()
plt.savefig('extracted_bkgspec.png')
plt.savefig('extracted_bkgspec.eps')
pl = get_data_plot()
save_arrays('bkgspec.tbl', [pl.x, pl.y], ['Energy', pl.ylabel], ascii=True)
Again, we want a source flux of about 0.3 counts/s over the entire detector.
SourceFlux
expects the flux in counts/s/cm^2, so we would have to devide
by Chandra’s effective area. Alternatively, we can just set the
exact number of photons we want to detect with ExposureTime=0
and NumRays
set to a negative number. We set SpectrumFile
to the spectrum of
the background. Now we only need to specify the shape of the
source. Figure Binned “blank sky” file for chip 7 shows regions with higher or
lower background level in the input “blank sky” file.
dmcopy "acis7sbkg.fits[EVENTS][bin x=::32,y=::32]" chip-shape.fits option=image
To reproduce this pattern, we use marx with SourceType="IMAGE"
.
There is a trade-off here: If we bin the image too much, we smooth out the
structure, if we bin too little such that we still see the random noise in the
image, then our marx simulation will produce an event distribution that shows
the same “random noise pattern”. That fine, unless we want to run many marx
simulations, where we would see the same “random” pattern again and again. Here, the
binning is chosen such that we find a few thousand events in every pixel of the
image.
All remaining marx parameters (RA_Nom
, Dec_Nom
etc.) are the
same as in the simulation of the astrophysical source of interest above.
marx SourceFlux=3. SpectrumType="FILE" SpectrumFile="bkgspec.tbl" \
ExposureTime=0 NumRays=-30000 TStart=2012.5 OutputDir=bkg \
DetectorType="ACIS-S" DitherModel="INTERNAL" RA_Nom=30 Dec_Nom=40 \
Roll_Nom=0 SourceRA=30 SourceDEC=40 \
SourceType="IMAGE" S-ImageFile="chip-shape.fits"
Now, we can use marxcat
to merge the simulation of the diffuse
source and the background and marx2fits
to convert the merged
results into a fits file.
marxcat diffuse bkg diffuse_with_bkg
marx2fits diffuse_with_bkg diffuse_with_bkg.fits
Looking at Images of the event files with marx simulated background we again see that the background makes it much harder to discern the source. The images look very similar to Images of event files, indicating that both approaches to describe the background give similar results. The main difference is that in the marx simulation the edge of the chip is more fuzzy. That’s because pixel boundaries in Binned “blank sky” file for chip 7 do not coincide exactly with the chip boundaries and thus we simulate the “background” for a region slightly larger than the chip. However, this is not important for our purpose: Finding how well we can fit the source position, size and spectrum in the presence of background.
Notes about additional background components¶
In addition to the instrumental background, there is also an astrophyiscal background. This can be unrelated to the target of the observation, such as charge exchange emission in the solar wind or the population of weak background AGN, that is roughly homogeneous over the field-of-view and contributes to the observed “diffuse” background.
For some targets, there are additional contributions to the apparent background that are related to the source. For example, in the case of diffuse emission in a star forming region there will be stars in the cluster. While the bright stars should be detected as point sources and those regions can be excluded from the analysis, there might be a population of weak stars that contribute only a few photons each, but add up to provide significant flux in addition to a truly diffuse component from a hot gas.
Different strategies can be used to account for those backgrounds in spectral modeling, but that is beyond the scope of this marx example.