Note

The following shows the code used to run this marx test. You can inspect it and adapt it to your needs, but you cannot copy and paste it directly because it depends on local $PATH and other environment variables. For example, we use a python function to manage the directory structure for all the images generated by all the tests instead of giving the file name directly to save images.

On-axis PSF at different energies

CIAO : Set up default marx.par file

cp /nfs/melkor/d1/guenther/marx/installed/dev//share/marx/pfiles/marx.par marx.par
pset marx.par GratingType=NONE
pset marx.par DetectorType=HRC-I
pset marx.par DitherModel=INTERNAL
pset marx.par ExposureTime=10000
pset marx.par SourceFlux=0.2
pset marx.par SourceRA=0.
pset marx.par SourceDEC=0.
pset marx.par RA_Nom=0.
pset marx.par Dec_Nom=0.
pset marx.par Roll_Nom=0.

marx : run marx for different energies

marx MinEnergy=0.25 MaxEnergy=0.25 OutputDir=marx0.25
marx MinEnergy=0.5 MaxEnergy=0.5 OutputDir=marx0.5
marx MinEnergy=1 MaxEnergy=1 OutputDir=marx1
marx MinEnergy=2 MaxEnergy=2 OutputDir=marx2
marx MinEnergy=3 MaxEnergy=3 OutputDir=marx3
marx MinEnergy=4 MaxEnergy=4 OutputDir=marx4
marx MinEnergy=6 MaxEnergy=6 OutputDir=marx6
marx MinEnergy=8 MaxEnergy=8 OutputDir=marx8

marxasp : Generate asol file

Since all simulations use the same pointing and exposure time, it is enough to run marxasp once.

marxasp MarxDir=marx0.25

marx2fits : Fits files from marx runs

marx2fits --pixadj=NONE marx0.25 marx0.25.fits
marx2fits --pixadj=NONE marx0.5 marx0.5.fits
marx2fits --pixadj=NONE marx1 marx1.fits
marx2fits --pixadj=NONE marx2 marx2.fits
marx2fits --pixadj=NONE marx3 marx3.fits
marx2fits --pixadj=NONE marx4 marx4.fits
marx2fits --pixadj=NONE marx6 marx6.fits
marx2fits --pixadj=NONE marx8 marx8.fits

SAOTrace : Now use SAOTrace

trace-nest tag=sao0.25 srcpars="point{ position = { ra = 0., dec = 0., ra_aimpt=0., dec_aimpt=0. }, spectrum = { { 0.25, 0.2 } } } roll(0) dither_asol_marx{ file = 'marx_asol1.fits', ra = 0., dec = 0., roll = 0. }" tstart=362912400.01  limit=9999.98302428007 limit_type=sec
trace-nest tag=sao0.5 srcpars="point{ position = { ra = 0., dec = 0., ra_aimpt=0., dec_aimpt=0. }, spectrum = { { 0.5, 0.2 } } } roll(0) dither_asol_marx{ file = 'marx_asol1.fits', ra = 0., dec = 0., roll = 0. }" tstart=362912400.01  limit=9999.98302428007 limit_type=sec
trace-nest tag=sao1 srcpars="point{ position = { ra = 0., dec = 0., ra_aimpt=0., dec_aimpt=0. }, spectrum = { { 1, 0.2 } } } roll(0) dither_asol_marx{ file = 'marx_asol1.fits', ra = 0., dec = 0., roll = 0. }" tstart=362912400.01  limit=9999.98302428007 limit_type=sec
trace-nest tag=sao2 srcpars="point{ position = { ra = 0., dec = 0., ra_aimpt=0., dec_aimpt=0. }, spectrum = { { 2, 0.2 } } } roll(0) dither_asol_marx{ file = 'marx_asol1.fits', ra = 0., dec = 0., roll = 0. }" tstart=362912400.01  limit=9999.98302428007 limit_type=sec
trace-nest tag=sao3 srcpars="point{ position = { ra = 0., dec = 0., ra_aimpt=0., dec_aimpt=0. }, spectrum = { { 3, 0.2 } } } roll(0) dither_asol_marx{ file = 'marx_asol1.fits', ra = 0., dec = 0., roll = 0. }" tstart=362912400.01  limit=9999.98302428007 limit_type=sec
trace-nest tag=sao4 srcpars="point{ position = { ra = 0., dec = 0., ra_aimpt=0., dec_aimpt=0. }, spectrum = { { 4, 0.2 } } } roll(0) dither_asol_marx{ file = 'marx_asol1.fits', ra = 0., dec = 0., roll = 0. }" tstart=362912400.01  limit=9999.98302428007 limit_type=sec
trace-nest tag=sao6 srcpars="point{ position = { ra = 0., dec = 0., ra_aimpt=0., dec_aimpt=0. }, spectrum = { { 6, 0.2 } } } roll(0) dither_asol_marx{ file = 'marx_asol1.fits', ra = 0., dec = 0., roll = 0. }" tstart=362912400.01  limit=9999.98302428007 limit_type=sec
trace-nest tag=sao8 srcpars="point{ position = { ra = 0., dec = 0., ra_aimpt=0., dec_aimpt=0. }, spectrum = { { 8, 0.2 } } } roll(0) dither_asol_marx{ file = 'marx_asol1.fits', ra = 0., dec = 0., roll = 0. }" tstart=362912400.01  limit=9999.98302428007 limit_type=sec

marx : run marx for all SAOTrace runs

marx SourceType=SAOSAC SAOSACFile=sao0.25.fits OutputDir=saomarx0.25 DitherModel=FILE DitherFile=marx_asol1.fits
marx SourceType=SAOSAC SAOSACFile=sao0.5.fits OutputDir=saomarx0.5 DitherModel=FILE DitherFile=marx_asol1.fits
marx SourceType=SAOSAC SAOSACFile=sao1.fits OutputDir=saomarx1 DitherModel=FILE DitherFile=marx_asol1.fits
marx SourceType=SAOSAC SAOSACFile=sao2.fits OutputDir=saomarx2 DitherModel=FILE DitherFile=marx_asol1.fits
marx SourceType=SAOSAC SAOSACFile=sao3.fits OutputDir=saomarx3 DitherModel=FILE DitherFile=marx_asol1.fits
marx SourceType=SAOSAC SAOSACFile=sao4.fits OutputDir=saomarx4 DitherModel=FILE DitherFile=marx_asol1.fits
marx SourceType=SAOSAC SAOSACFile=sao6.fits OutputDir=saomarx6 DitherModel=FILE DitherFile=marx_asol1.fits
marx SourceType=SAOSAC SAOSACFile=sao8.fits OutputDir=saomarx8 DitherModel=FILE DitherFile=marx_asol1.fits

marx2fits : Fits files from marx + SAOTrace runs

marx2fits --pixadj=NONE saomarx0.25 saomarx0.25.fits
marx2fits --pixadj=NONE saomarx0.5 saomarx0.5.fits
marx2fits --pixadj=NONE saomarx1 saomarx1.fits
marx2fits --pixadj=NONE saomarx2 saomarx2.fits
marx2fits --pixadj=NONE saomarx3 saomarx3.fits
marx2fits --pixadj=NONE saomarx4 saomarx4.fits
marx2fits --pixadj=NONE saomarx6 saomarx6.fits
marx2fits --pixadj=NONE saomarx8 saomarx8.fits

Python : Plots of radial distribution

# Note that this code might not run if you directly copy and paste it:
# - Not all import statements are shown here
# - `self` is a reference to a test instance, which allows access to
#   parameters such as the directory where the test is run etc.

'''Plots of radial distribution'''
import os
import numpy as np
from matplotlib import pyplot as plt
from astropy.table import Table

fig = plt.figure()
axecf = fig.add_subplot(111)
color = plt.cm.jet_r(np.linspace(0, 1, len(self.parameter)))
for i, e in enumerate(self.parameter):

    for prog in ['marx', 'saomarx']:
        f = os.path.join(self.basepath, '{0}{1}.fits'.format(prog, e))
        with fits.open(f) as hdus:
            header = hdus[1].header

        tab = Table.read(f, hdu=1)
        # The old question: Is an index the center of a pixel of the corner?
        # Differs by 0.5...
        d_ra = (tab['X'] - header['TCRPX9'] - 0.5) * header['TCDLT9'] * 3600.
        # Count from the left or right (RA is reversed on the sky)?
        d_dec = (tab['Y'] - header['TCRPX10'] + 0.5) * header['TCDLT10'] * 3600.

        # The simulation is set up to make this simple: RA=DEC=0
        # so cos(DEC) = 1 and we can approximate with Euklidian distance
        r = np.linalg.norm(np.vstack([d_ra, d_dec]), axis=0)
        val, edges = np.histogram(r, range=[0, 5], bins=50)
        bin_mid_marx = 0.5 * (edges[:-1] + edges[1:])
        ecf_marx = 1.0 * val.cumsum() / val.sum()
        if prog == 'marx':
            line, = axecf.plot(bin_mid_marx, ecf_marx, color=color[i],
                               label='{0} keV'.format(e))
        else:
            axecf.plot(bin_mid_marx, ecf_marx, color=line.get_color(), ls=':')
axecf.set_xscale('power', power=0.5)
axecf.legend(loc='lower right')
axecf.set_ylabel('encircled count fraction')
axecf.set_xlabel('radius [arcsec]')
axecf.set_xticks([0, .1, .2, .4, .6, .8, 1, 2, 3, 4, 5])
fig.savefig(self.figpath('ECF'), bbox_inches='tight')