Analyzing GRB 080916C with Fermi-GBM

Alt text (NASA/Swift/Cruz deWilde)

To demonstrate the capabilities and features of 3ML in, we will go through a time-integrated and time-resolved analysis. This example serves as a standard way to analyze Fermi-GBM data with 3ML as well as a template for how you can design your instrument’s analysis pipeline with 3ML if you have similar data.

3ML provides utilities to reduce time series data to plugins in a correct and statistically justified way (e.g., background fitting of Poisson data is done with a Poisson likelihood). The approach is generic and can be extended. For more details, see the time series documentation.

[1]:
import warnings

warnings.simplefilter("ignore")
[2]:
%%capture
import matplotlib.pyplot as plt
import numpy as np

np.seterr(all="ignore")


from threeML import *
from threeML.io.package_data import get_path_of_data_file
[3]:

silence_warnings() %matplotlib inline from jupyterthemes import jtplot jtplot.style(context="talk", fscale=1, ticks=True, grid=False) set_threeML_style()

Examining the catalog

As with Swift and Fermi-LAT, 3ML provides a simple interface to the on-line Fermi-GBM catalog. Let’s get the information for GRB 080916C.

[4]:
gbm_catalog = FermiGBMBurstCatalog()
gbm_catalog.query_sources("GRB080916009")
05:51:27 INFO      The cache for fermigbrst does not yet exist. We will try to    get_heasarc_table_as_pandas.py:63
                  build it                                                                                         
                                                                                                                   
         INFO      Building cache for fermigbrst                                 get_heasarc_table_as_pandas.py:103
[4]:
Table length=1
name ra dec trigger_time t90
object float64 float64 float64 float64
GRB080916009 119.800 -56.600 54725.0088613 62.977

To aid in quickly replicating the catalog analysis, and thanks to the tireless efforts of the Fermi-GBM team, we have added the ability to extract the analysis parameters from the catalog as well as build an astromodels model with the best fit parameters baked in. Using this information, one can quickly run through the catalog an replicate the entire analysis with a script. Let’s give it a try.

[5]:
grb_info = gbm_catalog.get_detector_information()["GRB080916009"]

gbm_detectors = grb_info["detectors"]
source_interval = grb_info["source"]["fluence"]
background_interval = grb_info["background"]["full"]
best_fit_model = grb_info["best fit model"]["fluence"]
model = gbm_catalog.get_model(best_fit_model, "fluence")["GRB080916009"]
[6]:
model
[6]:
Model summary:

N
Point sources 1
Extended sources 0
Particle sources 0


Free parameters (5):

value min_value max_value unit
GRB080916009.spectrum.main.SmoothlyBrokenPowerLaw.K 0.012255 0.0 None keV-1 s-1 cm-2
GRB080916009.spectrum.main.SmoothlyBrokenPowerLaw.alpha -1.130424 -1.5 2.0
GRB080916009.spectrum.main.SmoothlyBrokenPowerLaw.break_energy 309.2031 10.0 None keV
GRB080916009.spectrum.main.SmoothlyBrokenPowerLaw.break_scale 0.3 0.0 10.0
GRB080916009.spectrum.main.SmoothlyBrokenPowerLaw.beta -2.096931 -5.0 -1.6


Fixed parameters (3):
(abridged. Use complete=True to see all fixed parameters)


Properties (0):

(none)


Linked parameters (0):

(none)

Independent variables:

(none)

Linked functions (0):

(none)

Downloading the data

We provide a simple interface to download the Fermi-GBM data. Using the information from the catalog that we have extracted, we can download just the data from the detectors that were used for the catalog analysis. This will download the CSPEC, TTE and instrument response files from the on-line database.

[7]:
dload = download_GBM_trigger_data("bn080916009", detectors=gbm_detectors)

Let’s first examine the catalog fluence fit. Using the TimeSeriesBuilder, we can fit the background, set the source interval, and create a 3ML plugin for the analysis. We will loop through the detectors, set their appropriate channel selections, and ensure there are enough counts in each bin to make the PGStat profile likelihood valid.

  • First we use the CSPEC data to fit the background using the background selections. We use CSPEC because it has a longer duration for fitting the background.

  • The background is saved to an HDF5 file that stores the polynomial coefficients and selections which we can read in to the TTE file later.

  • The light curve is plotted.

  • The source selection from the catalog is set and DispersionSpectrumLike plugin is created.

  • The plugin has the standard GBM channel selections for spectral analysis set.

[8]:
fluence_plugins = []
time_series = {}
for det in gbm_detectors:

    ts_cspec = TimeSeriesBuilder.from_gbm_cspec_or_ctime(
        det, cspec_or_ctime_file=dload[det]["cspec"], rsp_file=dload[det]["rsp"]
    )

    ts_cspec.set_background_interval(*background_interval.split(","))
    ts_cspec.save_background(f"{det}_bkg.h5", overwrite=True)

    ts_tte = TimeSeriesBuilder.from_gbm_tte(
        det,
        tte_file=dload[det]["tte"],
        rsp_file=dload[det]["rsp"],
        restore_background=f"{det}_bkg.h5",
    )

    time_series[det] = ts_tte

    ts_tte.set_active_time_interval(source_interval)

    ts_tte.view_lightcurve(-40, 100)

    fluence_plugin = ts_tte.to_spectrumlike()

    if det.startswith("b"):

        fluence_plugin.set_active_measurements("250-30000")

    else:

        fluence_plugin.set_active_measurements("9-900")

    fluence_plugin.rebin_on_background(1.0)

    fluence_plugins.append(fluence_plugin)
05:52:26 INFO      Auto-determined polynomial order: 0                                binned_spectrum_series.py:356
05:52:32 INFO      None 0-order polynomial fit with the mle method                               time_series.py:426
         INFO      Saved fitted background to n3_bkg.h5                                          time_series.py:972
         INFO      Saved background to n3_bkg.h5                                         time_series_builder.py:430
         INFO      Successfully restored fit from n3_bkg.h5                              time_series_builder.py:166
         INFO      Interval set to 1.28-64.257 for n3                                    time_series_builder.py:274
         INFO      Auto-probed noise models:                                                    SpectrumLike.py:486
         INFO      - observation: poisson                                                       SpectrumLike.py:487
         INFO      - background: gaussian                                                       SpectrumLike.py:488
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
05:52:36 INFO      Now using 120 bins                                                          SpectrumLike.py:1706
05:52:38 INFO      Auto-determined polynomial order: 1                                binned_spectrum_series.py:356
05:52:43 INFO      None 1-order polynomial fit with the mle method                               time_series.py:426
         INFO      Saved fitted background to n4_bkg.h5                                          time_series.py:972
         INFO      Saved background to n4_bkg.h5                                         time_series_builder.py:430
         INFO      Successfully restored fit from n4_bkg.h5                              time_series_builder.py:166
         INFO      Interval set to 1.28-64.257 for n4                                    time_series_builder.py:274
         INFO      Auto-probed noise models:                                                    SpectrumLike.py:486
         INFO      - observation: poisson                                                       SpectrumLike.py:487
         INFO      - background: gaussian                                                       SpectrumLike.py:488
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
05:52:44 INFO      Auto-determined polynomial order: 1                                binned_spectrum_series.py:356
05:52:50 INFO      None 1-order polynomial fit with the mle method                               time_series.py:426
         INFO      Saved fitted background to b0_bkg.h5                                          time_series.py:972
         INFO      Saved background to b0_bkg.h5                                         time_series_builder.py:430
         INFO      Successfully restored fit from b0_bkg.h5                              time_series_builder.py:166
         INFO      Interval set to 1.28-64.257 for b0                                    time_series_builder.py:274
05:52:51 INFO      Auto-probed noise models:                                                    SpectrumLike.py:486
         INFO      - observation: poisson                                                       SpectrumLike.py:487
         INFO      - background: gaussian                                                       SpectrumLike.py:488
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
../_images/notebooks_grb080916C_12_42.png
../_images/notebooks_grb080916C_12_43.png
../_images/notebooks_grb080916C_12_44.png

Setting up the fit

Let’s see if we can reproduce the results from the catalog.

Set priors for the model

We will fit the spectrum using Bayesian analysis, so we must set priors on the model parameters.

[9]:
model.GRB080916009.spectrum.main.shape.alpha.prior = Truncated_gaussian(
    lower_bound=-1.5, upper_bound=1, mu=-1, sigma=0.5
)
model.GRB080916009.spectrum.main.shape.beta.prior = Truncated_gaussian(
    lower_bound=-5, upper_bound=-1.6, mu=-2.25, sigma=0.5
)
model.GRB080916009.spectrum.main.shape.break_energy.prior = Log_normal(mu=2, sigma=1)
model.GRB080916009.spectrum.main.shape.break_energy.bounds = (None, None)
model.GRB080916009.spectrum.main.shape.K.prior = Log_uniform_prior(
    lower_bound=1e-3, upper_bound=1e1
)
model.GRB080916009.spectrum.main.shape.break_scale.prior = Log_uniform_prior(
    lower_bound=1e-4, upper_bound=10
)

Clone the model and setup the Bayesian analysis class

Next, we clone the model we built from the catalog so that we can look at the results later and fit the cloned model. We pass this model and the DataList of the plugins to a BayesianAnalysis class and set the sampler to MultiNest.

[10]:
new_model = clone_model(model)

bayes = BayesianAnalysis(new_model, DataList(*fluence_plugins))

# share spectrum gives a linear speed up when
# spectrumlike plugins have the same RSP input energies
bayes.set_sampler("multinest", share_spectrum=True)
         INFO      sampler set to multinest                                                bayesian_analysis.py:186

Examine at the catalog fitted model

We can quickly examine how well the catalog fit matches the data. There appears to be a discrepancy between the data and the model! Let’s refit to see if we can fix it.

[11]:
fig = display_spectrum_model_counts(bayes, min_rate=20, step=False)
../_images/notebooks_grb080916C_18_0.png

Run the sampler

We let MultiNest condition the model on the data

[12]:
bayes.sampler.setup(n_live_points=400)
bayes.sample()
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  400
 dimensionality =    5
 *****************************************************
  analysing data from chains/fit-.txt ln(ev)=  -3102.6880863086462      +/-  0.23047239969918928
 Total Likelihood Evaluations:        20295
 Sampling finished. Exiting MultiNest

05:53:02 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
GRB080916009...K (1.470 -0.016 +0.020) x 10^-2 1 / (keV s cm2)
GRB080916009...alpha -1.089 -0.006 +0.028
GRB080916009...break_energy (1.8982 +0.0033 +0.4) x 10^2 keV
GRB080916009...break_scale (0.0 +1.1 +2.8) x 10^-1
GRB080916009...beta -1.978 -0.10 +0.011
Values of -log(posterior) at the minimum:

-log(posterior)
n3 -1019.380088
n4 -1009.927962
b0 -1049.514679
total -3078.822729
Values of statistical measures:

statistical measures
AIC 6167.815912
BIC 6187.048123
DIC 6177.737405
PDIC 3.211992
log(Z) -1347.480315

Now our model seems to match much better with the data!

[13]:
bayes.restore_median_fit()
fig = display_spectrum_model_counts(bayes, min_rate=20)
         INFO      fit restored to median of posterior                                          sampler_base.py:157
../_images/notebooks_grb080916C_22_1.png

But how different are we from the catalog model? Let’s plot our fit along with the catalog model. Luckily, 3ML can handle all the units for is

[14]:
conversion = u.Unit("keV2/(cm2 s keV)").to("erg2/(cm2 s keV)")
energy_grid = np.logspace(1, 4, 100) * u.keV
vFv = (energy_grid**2 * model.get_point_source_fluxes(0, energy_grid)).to(
    "erg2/(cm2 s keV)"
)
[15]:
fig = plot_spectra(bayes.results, flux_unit="erg2/(cm2 s keV)")
ax = fig.get_axes()[0]
_ = ax.loglog(energy_grid, vFv, color="blue", label="catalog model")
../_images/notebooks_grb080916C_25_2.png

Time Resolved Analysis

Now that we have examined fluence fit, we can move to performing a time-resolved analysis.

Selecting a temporal binning

We first get the brightest NaI detector and create time bins via the Bayesian blocks algorithm. We can use the fitted background to make sure that our intervals are chosen in an unbiased way.

[16]:
n3 = time_series["n3"]
[17]:
n3.create_time_bins(0, 60, method="bayesblocks", use_background=True, p0=0.2)
05:53:58 INFO      Created 15 bins via bayesblocks                                       time_series_builder.py:632

Sometimes, glitches in the GBM data cause spikes in the data that the Bayesian blocks algorithm detects as fast changes in the count rate. We will have to remove those intervals manually.

Note: In the future, 3ML will provide an automated method to remove these unwanted spikes.

[18]:
fig = n3.view_lightcurve(use_binner=True)
../_images/notebooks_grb080916C_30_0.png
[19]:
bad_bins = []
for i, w in enumerate(n3.bins.widths):

    if w < 5e-2:
        bad_bins.append(i)


edges = [n3.bins.starts[0]]

for i, b in enumerate(n3.bins):

    if i not in bad_bins:
        edges.append(b.stop)

starts = edges[:-1]
stops = edges[1:]


n3.create_time_bins(starts, stops, method="custom")
         INFO      Created 12 bins via custom                                            time_series_builder.py:632

Now our light curve looks much more acceptable.

[20]:
fig = n3.view_lightcurve(use_binner=True)
../_images/notebooks_grb080916C_33_0.png

The time series objects can read time bins from each other, so we will map these time bins onto the other detectors’ time series and create a list of time plugins for each detector and each time bin created above.

[21]:
time_resolved_plugins = {}

for k, v in time_series.items():
    v.read_bins(n3)
    time_resolved_plugins[k] = v.to_spectrumlike(from_bins=True)
         INFO      Created 12 bins via custom                                            time_series_builder.py:632
05:53:59 INFO      Interval set to 1.28-64.257 for n3                                    time_series_builder.py:274
         INFO      Created 12 bins via custom                                            time_series_builder.py:632
         INFO      Interval set to 1.28-64.257 for n4                                    time_series_builder.py:274
         INFO      Created 12 bins via custom                                            time_series_builder.py:632
05:54:00 INFO      Interval set to 1.28-64.257 for b0                                    time_series_builder.py:274

Setting up the model

For the time-resolved analysis, we will fit the classic Band function to the data. We will set some principled priors.

[22]:
band = Band()
band.alpha.prior = Truncated_gaussian(lower_bound=-1.5, upper_bound=1, mu=-1, sigma=0.5)
band.beta.prior = Truncated_gaussian(lower_bound=-5, upper_bound=-1.6, mu=-2, sigma=0.5)
band.xp.prior = Log_normal(mu=2, sigma=1)
band.xp.bounds = (None, None)
band.K.prior = Log_uniform_prior(lower_bound=1e-10, upper_bound=1e3)
ps = PointSource("grb", 0, 0, spectral_shape=band)
band_model = Model(ps)

Perform the fits

One way to perform Bayesian spectral fits to all the intervals is to loop through each one. There can are many ways to do this, so find an analysis pattern that works for you.

[23]:
models = []
results = []
analysis = []
for interval in range(12):

    # clone the model above so that we have a separate model
    # for each fit

    this_model = clone_model(band_model)

    # for each detector set up the plugin
    # for this time interval

    this_data_list = []
    for k, v in time_resolved_plugins.items():

        pi = v[interval]

        if k.startswith("b"):
            pi.set_active_measurements("250-30000")
        else:
            pi.set_active_measurements("9-900")

        pi.rebin_on_background(1.0)

        this_data_list.append(pi)

    # create a data list

    dlist = DataList(*this_data_list)

    # set up the sampler and fit

    bayes = BayesianAnalysis(this_model, dlist)

    # get some speed with share spectrum
    bayes.set_sampler("multinest", share_spectrum=True)
    bayes.sampler.setup(n_live_points=500)
    bayes.sample()

    # at this stage we coudl also
    # save the analysis result to
    # disk but we will simply hold
    # onto them in memory

    analysis.append(bayes)
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 107 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt
 ln(ev)=  -790.87588442245601      +/-  0.18719901776719264
 Total Likelihood Evaluations:        17079
 Sampling finished. Exiting MultiNest
05:54:10 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (3.5 -0.4 +0.8) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-5.7 -1.3 +0.7) x 10^-1
grb.spectrum.main.Band.xp (3.2 -0.7 +0.4) x 10^2 keV
grb.spectrum.main.Band.beta -2.10 -0.08 +0.11
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval0 -250.202623
n4_interval0 -268.097886
b0_interval0 -285.697487
total -803.997996
Values of statistical measures:

statistical measures
AIC 1616.109307
BIC 1631.518125
DIC 1569.219708
PDIC 1.048191
log(Z) -343.473032
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt
 ln(ev)=  -1949.9022288994058      +/-  0.21842129470953131
 Total Likelihood Evaluations:        23445
 Sampling finished. Exiting MultiNest
05:54:23 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (4.510 -0.17 -0.015) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-7.78 -0.22 +0.05) x 10^-1
grb.spectrum.main.Band.xp (5.16 +0.05 +0.6) x 10^2 keV
grb.spectrum.main.Band.beta -2.1597354121646606 -0.20 +0
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval1 -642.047674
n4_interval1 -644.670411
b0_interval1 -677.663858
total -1964.381944
Values of statistical measures:

statistical measures
AIC 3936.877202
BIC 3952.286020
DIC 3881.157929
PDIC 1.378817
log(Z) -846.831778
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 115 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt ln(ev)=  -914.75304645799190      +/-  0.20277498596601073
 Total Likelihood Evaluations:        19937
 Sampling finished. Exiting MultiNest

05:54:35 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (3.102 +0.018 +0.7) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-9.55 -0.33 +0.5) x 10^-1
grb.spectrum.main.Band.xp (2.997 -1.0 +0.015) x 10^2 keV
grb.spectrum.main.Band.beta -1.619 -0.006 +0.009
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval2 -288.400674
n4_interval2 -309.595126
b0_interval2 -324.438694
total -922.434494
Values of statistical measures:

statistical measures
AIC 1852.982303
BIC 1868.391121
DIC 1807.937441
PDIC 0.252380
log(Z) -397.272200
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 109 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt
 ln(ev)=  -790.79173923504970      +/-  0.17897040567462927
 Total Likelihood Evaluations:        17871
 Sampling finished. Exiting MultiNest
05:54:44 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (3.0667 +0.0005 +0.7) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-9.09 -0.19 +1.7) x 10^-1
grb.spectrum.main.Band.xp (3.11 -0.9 -0.04) x 10^2 keV
grb.spectrum.main.Band.beta -2.12 +0.07 +0.26
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval3 -242.352742
n4_interval3 -262.247759
b0_interval3 -298.186112
total -802.786612
Values of statistical measures:

statistical measures
AIC 1613.686538
BIC 1629.095356
DIC 1571.083221
PDIC 2.277199
log(Z) -343.436489
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt ln(ev)=  -2273.0041568144343      +/-  0.20267262874494801
 Total Likelihood Evaluations:        21653
 Sampling finished. Exiting MultiNest

05:54:55 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.13 +0.04 +0.19) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-9.56 +0.07 +0.6) x 10^-1
grb.spectrum.main.Band.xp (3.66 -0.5 -0.05) x 10^2 keV
grb.spectrum.main.Band.beta -1.92 -0.10 +0.05
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval4 -757.241521
n4_interval4 -746.320501
b0_interval4 -778.280326
total -2281.842349
Values of statistical measures:

statistical measures
AIC 4571.798012
BIC 4587.206830
DIC 4528.258552
PDIC 2.689920
log(Z) -987.153163
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt ln(ev)=  -1580.0515246241443      +/-  0.20160085380222845
 Total Likelihood Evaluations:        22786
 Sampling finished. Exiting MultiNest

05:55:07 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.97 +0.05 +0.5) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-8.73 +0.08 +1.1) x 10^-1
grb.spectrum.main.Band.xp (3.53 -0.7 -0.09) x 10^2 keV
grb.spectrum.main.Band.beta -1.870 -0.007 +0.05
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval5 -523.461314
n4_interval5 -527.317553
b0_interval5 -538.360408
total -1589.139274
Values of statistical measures:

statistical measures
AIC 3186.391863
BIC 3201.800680
DIC 3143.109766
PDIC 2.772886
log(Z) -686.207658
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt
 ln(ev)=  -1757.4274748612638      +/-  0.19450001533333303
 Total Likelihood Evaluations:        19207
 Sampling finished. Exiting MultiNest
05:55:17 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.00 -0.06 +0.25) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-10.0 -0.26 +0.9) x 10^-1
grb.spectrum.main.Band.xp (4.11 -0.8 +0.16) x 10^2 keV
grb.spectrum.main.Band.beta -2.16 -0.13 +0.14
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval6 -584.148043
n4_interval6 -576.285316
b0_interval6 -609.300740
total -1769.734099
Values of statistical measures:

statistical measures
AIC 3547.581513
BIC 3562.990331
DIC 3502.180684
PDIC 3.410686
log(Z) -763.241055
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt
 ln(ev)=  -1938.7425090535803      +/-  0.18946054758951594
 Total Likelihood Evaluations:        19454
 Sampling finished. Exiting MultiNest
05:55:26 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.69 -0.10 +0.11) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha -1.03 +/- 0.05
grb.spectrum.main.Band.xp (4.1 -0.4 +0.8) x 10^2 keV
grb.spectrum.main.Band.beta -2.165 -0.5 -0.019
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval7 -640.673215
n4_interval7 -650.177642
b0_interval7 -662.217113
total -1953.067970
Values of statistical measures:

statistical measures
AIC 3914.249255
BIC 3929.658073
DIC 3867.510772
PDIC 2.620288
log(Z) -841.985174
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt ln(ev)=  -2055.7200099652796      +/-  0.19680049939320529
 Total Likelihood Evaluations:        18126
 Sampling finished. Exiting MultiNest

05:55:36 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.54 -0.07 +0.14) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-8.4 -0.4 +0.5) x 10^-1
grb.spectrum.main.Band.xp (3.74 -0.5 +0.27) x 10^2 keV
grb.spectrum.main.Band.beta -2.29 -0.05 +0.16
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval8 -698.431221
n4_interval8 -666.032602
b0_interval8 -702.312438
total -2066.776261
Values of statistical measures:

statistical measures
AIC 4141.665837
BIC 4157.074654
DIC 4095.999188
PDIC 2.365720
log(Z) -892.787857
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt ln(ev)=  -1879.3641309132377      +/-  0.14955045500700084
 Total Likelihood Evaluations:        12254
 Sampling finished. Exiting MultiNest

05:55:43 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.1 -0.4 +1.4) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-8.6 -2.2 +3.4) x 10^-1
grb.spectrum.main.Band.xp (1.1 -0.4 +0.6) x 10^2 keV
grb.spectrum.main.Band.beta -1.81 -0.4 +0.08
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval9 -616.819556
n4_interval9 -616.018071
b0_interval9 -648.628166
total -1881.465792
Values of statistical measures:

statistical measures
AIC 3771.044899
BIC 3786.453717
DIC 3693.903408
PDIC -52.996412
log(Z) -816.197472
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt ln(ev)=  -1322.1323859753177      +/-  0.16769870639009782
 Total Likelihood Evaluations:        15071
 Sampling finished. Exiting MultiNest

05:55:50 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.1 +/- 0.4) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-7.2 -1.6 +1.2) x 10^-1
grb.spectrum.main.Band.xp (2.2 -0.4 +0.7) x 10^2 keV
grb.spectrum.main.Band.beta -1.96 -0.4 +0.10
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval10 -437.685788
n4_interval10 -433.243961
b0_interval10 -460.831726
total -1331.761474
Values of statistical measures:

statistical measures
AIC 2671.636262
BIC 2687.045079
DIC 2633.977363
PDIC 0.429609
log(Z) -574.194800
         INFO      Range 9-900 translates to channels 5-124                                    SpectrumLike.py:1237
         INFO      Now using 120 bins                                                          SpectrumLike.py:1706
         INFO      Range 9-900 translates to channels 5-123                                    SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      Range 250-30000 translates to channels 1-119                                SpectrumLike.py:1237
         INFO      Now using 119 bins                                                          SpectrumLike.py:1706
         INFO      sampler set to multinest                                                bayesian_analysis.py:186
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
  analysing data from chains/fit-.txt
 ln(ev)=  -812.01425283747699      +/-  0.14614156075061688
 Total Likelihood Evaluations:        12323
 Sampling finished. Exiting MultiNest
05:55:56 INFO      fit restored to maximum of posterior                                         sampler_base.py:168
         INFO      fit restored to maximum of posterior                                         sampler_base.py:168
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.7 -0.7 +2.4) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-5.1 -1.9 +3.5) x 10^-1
grb.spectrum.main.Band.xp (1.29 -0.32 +0.23) x 10^2 keV
grb.spectrum.main.Band.beta -2.10 -0.23 +0.25
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval11 -272.403311
n4_interval11 -255.758634
b0_interval11 -292.294484
total -820.456430
Values of statistical measures:

statistical measures
AIC 1649.026174
BIC 1664.434991
DIC 1615.748298
PDIC -1.274656
log(Z) -352.653309

Examine the fits

Now we can look at the fits in count space to make sure they are ok.

[24]:
for a in analysis:
    a.restore_median_fit()
    _ = display_spectrum_model_counts(a, min_rate=[20, 20, 20], step=False)
         INFO      fit restored to median of posterior                                          sampler_base.py:157
05:55:57 INFO      fit restored to median of posterior                                          sampler_base.py:157
         INFO      fit restored to median of posterior                                          sampler_base.py:157
         INFO      fit restored to median of posterior                                          sampler_base.py:157
05:55:58 INFO      fit restored to median of posterior                                          sampler_base.py:157
         INFO      fit restored to median of posterior                                          sampler_base.py:157
05:55:59 INFO      fit restored to median of posterior                                          sampler_base.py:157
         INFO      fit restored to median of posterior                                          sampler_base.py:157
         INFO      fit restored to median of posterior                                          sampler_base.py:157
         INFO      fit restored to median of posterior                                          sampler_base.py:157
05:56:00 INFO      fit restored to median of posterior                                          sampler_base.py:157
         INFO      fit restored to median of posterior                                          sampler_base.py:157
../_images/notebooks_grb080916C_41_12.png
../_images/notebooks_grb080916C_41_13.png
../_images/notebooks_grb080916C_41_14.png
../_images/notebooks_grb080916C_41_15.png
../_images/notebooks_grb080916C_41_16.png
../_images/notebooks_grb080916C_41_17.png
../_images/notebooks_grb080916C_41_18.png
../_images/notebooks_grb080916C_41_19.png
../_images/notebooks_grb080916C_41_20.png
../_images/notebooks_grb080916C_41_21.png
../_images/notebooks_grb080916C_41_22.png
../_images/notebooks_grb080916C_41_23.png

Finally, we can plot the models together to see how the spectra evolve with time.

[25]:
fig = plot_spectra(
    *[a.results for a in analysis[::1]],
    flux_unit="erg2/(cm2 s keV)",
    fit_cmap="viridis",
    contour_cmap="viridis",
    contour_style_kwargs=dict(alpha=0.1),
)
../_images/notebooks_grb080916C_43_13.png

This example can serve as a template for performing analysis on GBM data. However, as 3ML provides an abstract interface and modular building blocks, similar analysis pipelines can be built for any time series data.