About Chandra Archive Proposer Instruments & Calibration Newsletters Data Analysis HelpDesk Calibration Database NASA Archives & Centers Chandra Science Links

Skip the navigation links
Last modified: 29 April 2009
Hardcopy (PDF): A4 | Letter

Introduction to Fitting PHA Spectra

Sherpa Threads (CIAO 4.1)

[S-Lang Syntax]



Overview

Last Update: 29 Apr 2009 - new script command is available with CIAO 4.1.2

Synopsis:

The basic steps used in fitting spectral data are illustrated in this thread. The data used herein were created by running the Step-by-Step Guide to Creating ACIS Spectra for Pointlike Sources thread (or, equivalently, the psextract script).

There are many options and variables that may affect how this process is applied to your data; for a more detailed explanation of the steps, see the following threads:

For a detailed explanation of the fitting concepts behind X-ray spectral analysis in Sherpa, see the document Spectral Fitting on the Sherpa References page.

Before fitting ACIS data sets with restricted pulse-height ranges, please read the CIAO caveat page "Spectral analyses of ACIS data with a limited pulse-height range."

Proceed to the HTML or hardcopy (PDF: A4 | letter) version of the thread.




Contents



Load the Spectrum & Instrument Responses

First, load the spectrum file:

sherpa> load_pha("3c273.pi");
statistical errors were found in file '3c273.pi'
but not used; to use them, re-read with use_errors=True
read ARF file 3c273.arf
read RMF file 3c273.rmf
statistical errors were found in file '3c273_bg.pi'
but not used; to use them, re-read with use_errors=True
read background file 3c273_bg.pi

Since the RESPFILE, ANCRFILE, and BACKFILE header keywords were updated in the spectrum file, the response files (RMF and ARF) and background file are automatically read in as well. If the default dataset id of "1" is to be used, it does not need to be explicitly included in the load function; only the data filenames are required in this case.

If Sherpa does not automatically read in the background and response files, read them manually:

sherpa> load_arf("3c273.arf");
sherpa> load_rmf("3c273.rmf");
sherpa> load_bkg("3c273_bg.pi");

Use show_all to get the status of the Sherpa session. Some additional commands are used to get the total number of counts and counts rates calculated from the data.

sherpa> show_all();
Data Set: 1
Filter: 0.1248-12.4100 Energy (keV)
Noticed Channels: 1.0-1024.0
name           = 3c273.pi
channel        = Float64[1024]
counts         = Float64[1024]
staterror      = None
syserror       = None
bin_lo         = None
bin_hi         = None
grouping       = Int16[1024]
quality        = Int16[1024]
exposure       = 38564.6089269
backscal       = 2.52643646989e-06
areascal       = 1.0
grouped        = True
subtracted     = False
units          = energy
response_ids   = [1]
background_ids = [1]

RMF Data Set: 1:1
name     = 3c273.rmf
detchans = 1024
energ_lo = Float64[1090]
energ_hi = Float64[1090]
n_grp    = Int16[1090]
f_chan   = UInt32[2002]
n_chan   = UInt32[2002]
matrix   = Float64[61834]
offset   = 1
e_min    = Float64[1024]
e_max    = Float64[1024]

ARF Data Set: 1:1
name     = 3c273.arf
energ_lo = Float64[1090]
energ_hi = Float64[1090]
specresp = Float64[1090]
bin_lo   = None
bin_hi   = None
exposure = 38564.1414549

Background Data Set: 1:1
name           = 3c273_bg.pi
channel        = Float64[1024]
counts         = Float64[1024]
staterror      = None
syserror       = None
bin_lo         = None
bin_hi         = None
grouping       = Int16[1024]
quality        = Int16[1024]
exposure       = 38564.6089269
backscal       = 1.87253514146e-05
areascal       = 1.0
grouped        = True
subtracted     = False
units          = energy
response_ids   = []
background_ids = []



sherpa> data_sum = calc_data_sum();  # total counts (or values) in the data
sherpa> print(data_sum)
736.0

 
sherpa> data_cnt_rate = calc_data_sum()/get_exposure();  # calculating count rate in cts/sec 
sherpa> print(data_cnt_rate)
0.0190848557908


sherpa> bkg_sum = calc_data_sum(;bkg_id=1);   # total counts (or values) in the background data
sherpa> print(bkg_sum)
216


sherpa> bkg_cnt_rate = calc_data_sum(;bkg_id=1)/get_exposure(;bkg_id=1);  # calculating background count rate in cts/sec
 
sherpa> print(bkg_cnt_rate);
0.00560099028644

Plot the data:

sherpa> plot_data(); 

The data are plotted in energy space - as seen in Figure 1 - since the instrument model provides the information necessary to compute the predicted counts for each bin. In general, the units of the x-axis are determined by the value in the units field of the data, which may be accessed with 'print(get_data().units)' or show_filter, and modified with set_analysis.



Filter the Data & Subtract the Background

Looking at the plot, we decide to evaluate the fit on the energy range between 0.1 and 6.0 keV. The CIAO why topic on Choosing an Energy Filter has more information on this process. To apply this filter to the dataset we use the notice_id() function, which requires explicit input of the data set id. The first argument in notice_id is the data set id, the second defines the lower energy of the range, and the third the higher energy of the range. The data between 0.1 and 6.0 keV will be noticed with this command:

At this point, we also opt to subtract the background data:

sherpa> subtract(); 

sherpa> plot_data();

Figure 2 shows the resulting plot.

The plot axis scaling may be changed to log by calling log_scale (and changed back to linear with linear_scale):

sherpa> log_scale(); #Set both axes to log scale
sherpa> log_scale(XY_AXIS); 

sherpa> log_scale(X_AXIS); #Set only x-axis to log scale

sherpa> log_scale(Y_AXIS); #Set only y-axis to log scale


Defining the Source Model

Before fitting the data, it is necessary to define a model that characterizes the source. We use a source model composed of two model components:

  • powlaw1d - a one-dimensional power law.
  • xsphabs - an XSpec photoelectric absorption model.

We define an expression that is the product of these two components. The hydrogen column density (nH) is set to the known Galactic value for the source and the parameter is frozen so that it will not be allowed to vary in the fit.

sherpa> set_source(xsphabs.abs1 * powlaw1d.p1); 
sherpa> abs1.nH = 0.07;
sherpa> freeze(abs1.nH);

The current source model definition may be displayed:

sherpa> show_model();
Model: 1
apply_rmf(apply_arf((38564.6089269 * (xsphabs.abs1 * powlaw1d.p1))))
   Param        Type          Value          Min          Max      Units
   -----        ----          -----          ---          ---      -----
   abs1.nh      frozen         0.07            0       100000 10^22 atoms / cm^2
   p1.gamma     thawed            1          -10           10
   p1.ref       frozen            1 -3.40282e+38  3.40282e+38
   p1.ampl      thawed            1            0  3.40282e+38

Note that Sherpa and XSPEC absorption models have to be multiplied by a model which has normalization and amplitude parameters, such as powlaw1d. They cannot be used as single models in the source expression. It may be necessary to modify the parameter values, since the Sherpa guess functionality does not apply to absorption models. However, we can use this command to guess the initial parameter values and ranges for the power-law model component (as model parameter values are not automatically guessed in Sherpa 4.1 as they were in previous versions of the software):

sherpa> guess(p1);

sherpa> show_model();
Model: 1
apply_rmf(apply_arf((38564.6089269 * (xsphabs.abs1 * powlaw1d.p1))))
   Param        Type          Value          Min          Max      Units
   -----        ----          -----          ---          ---      -----
   abs1.nh      frozen         0.07            0       100000 10^22 atoms / cm^2
   p1.gamma     thawed            1          -10           10           
   p1.ref       frozen            1 -3.40282e+38  3.40282e+38           
   p1.ampl      thawed  0.000148802  1.48802e-06    0.0148802           

The guess command makes an initial guess at parameter values to ensure convergence, but it is always a good idea to check that the initial range of values (soft limits) is sensible for the data being fit.



Fitting

Now we are ready to run the fit. The default statistics (chi2gehrels) and optimization method (levmar) are used:

sherpa> fit(); 
Solar Abundance Vector set to angr:  Anders E. & Grevesse N. Geochimica et Cosmochimica Acta 53, 197 (1989)
 Cross Section Table set to bcmc:  Balucinska-Church and McCammon, 1998
Dataset               = 1
Method                = levmar
Statistic             = chi2gehrels
Initial fit statistic = 6.83386e+10
Final fit statistic   = 37.9079 at function evaluation 22
Data points           = 44
Degrees of freedom    = 42
Probability [Q-value] = 0.651155
Reduced statistic     = 0.902569
Change in statistic   = 6.83386e+10
   p1.gamma       2.15852
   p1.ampl        0.00022484

The fit information includes the statistic value for chi2gehrels, goodness-of-fit and reduced chi-square along with the best-fit parameter values of the photon index and amplitude.

The best fit model with the data and residuals may be plotted in the same window:

which creates Figure 3. The errors are plotted as "sigma", the sigma residuals of the fit [(data - model)/error].



Examining Fit Results

Goodness of fit

In CIAO 3.4, the goodness command was used to get the chi-squared goodness-of-fit. This information is now reported with the best-fit values after a fit; it is no longer necessary to run a separate command. The show_fit and get_fit_results commands allow access to this information after the fit has been performed:

sherpa> show_fit();

Optimization Method: LevMar
name    = levmar
ftol    = 1.19209289551e-07
xtol    = 1.19209289551e-07
gtol    = 1.19209289551e-07
maxfev  = None
epsfcn  = 1.19209289551e-07
factor  = 100.0
verbose = 0

Statistic: Chi2Gehrels

Fit:Dataset               = 1
Method                = levmar
Statistic             = chi2gehrels
Initial fit statistic = 6.83386e+10
Final fit statistic   = 37.9079 at function evaluation 22
Data points           = 44
Degrees of freedom    = 42
Probability [Q-value] = 0.651155
Reduced statistic     = 0.902569
Change in statistic   = 6.83386e+10
   p1.gamma       2.15852
   p1.ampl        0.00022484



% retrieve a single value with get_fit_results():
sherpa> print(get_fit_results().qval);
0.651155

sherpa> print(get_fit_results().rstat);
0.902569

The number of bins in the fit (Data points), the number of degrees of freedom, i.e. the number of bins minus the number of free parameters, and the final fit statistic value are reported. If the chosen statistic is one of the chi-square statistics, as in this example, the reduced statistic (i.e. the statistic value divided by the number of degrees of freedom) and the probability (Q-value) are included as well.

The calc_chisqr command calculates the statistic contribution per bin:

sherpa-43> perbin = calc_chisqr();
sherpa-44> print(perbin);

8.18673
5.97521
1.12656
0.270996
0.152223
0.0064185
0.745753
...
0.213674
0.15101
0.434761

Confidence intervals

The covariance() command - which may be shortened to covar() - computes covariance matrices and provides an estimate of confidence intervals for the thawed parameters (see the related command projection() also):

sherpa> covar();
covariance 1-sigma bounds:
   Param            Best-Fit  Lower Bound  Upper Bound
   -----            --------  -----------  -----------
   p1.gamma          2.15852   -0.0827856    0.0827856
   p1.ampl        0.00022484 -1.48256e-05  1.48256e-05

The output is the best-fit parameter value with positive and negative error estimates.


Flux and Counts

To calculate the flux of a PHA data set, use the calc_photon_flux and calc_energy_flux commands. The flux may be calculated over the entire data set or over a specific range:

sherpa> calc_photon_flux();
0.000469951

sherpa> calc_photon_flux(2., 10.);
7.26549e-05

sherpa> calc_energy_flux();
9.61261e-13

sherpa> calc_energy_flux(2., 10.);
4.55133e-13

To calculate the counts of a PHA data set, use the calc_data_sum, calc_model_sum, or calc_source_sum commands. As with the flux calculations, these commands may be given a range:

sherpa> calc_data_sum();
706.85714092

sherpa> calc_data_sum(2., 10.);
306.230157017


sherpa> calc_model_sum();
638.45693375313488

sherpa> calc_model_sum(2., 10.);
270.73187526053857


sherpa> calc_source_sum();
0.0469964088469405

sherpa> calc_source_sum(2., 10.);
0.0072654873922453405


Scripting It

The file fit.sl is an S-Lang script which performs the primary commands used above; it can be executed by typing execfile("fit.sl") on the Sherpa command line.

The Sherpa script command may be used to save everything typed on the command line in a Sherpa session:

sherpa> script(filename="sherpa.log", clobber=False);

The CXC is committed to helping Sherpa users transition to new syntax as smoothly as possible. If you have existing Sherpa scripts or save files, submit them to us via the CXC Helpdesk and we will provide the CIAO/Sherpa 4.1 syntax to you.



History

14 Nov 2007 rewritten for CIAO 4.0 Beta 3
29 Apr 2008 show_all command is available in CIAO 4.0
09 Dec 2008 figures moved inline with text
09 Dec 2008 updated for Sherpa 4.1
16 Feb 2009 example of guess functionality added
29 Apr 2009 new script command is available with CIAO 4.1.2

Return to Threads Page: Top | All | Intro | Fitting
Hardcopy (PDF): A4 | Letter
Last modified: 29 April 2009


The Chandra X-Ray Center (CXC) is operated for NASA by the Smithsonian Astrophysical Observatory.
60 Garden Street, Cambridge, MA 02138 USA.    Email: cxcweb@head.cfa.harvard.edu
Smithsonian Institution, Copyright © 1998-2004. All rights reserved.