Analyzing GRB 080916C

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")
[4]:
Table length=1
nameradectrigger_timet90
objectfloat64float64float64float64
GRB080916009119.800-56.60054725.008861362.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)


Linked parameters (0):

(none)

Independent variables:

(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)
../_images/notebooks_grb080916C_12_9.png
../_images/notebooks_grb080916C_12_10.png
../_images/notebooks_grb080916C_12_11.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)

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()
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
GRB080916009...K (1.469 +/- 0.018) x 10^-2 1 / (cm2 keV s)
GRB080916009...alpha -1.073 -0.019 +0.020
GRB080916009...break_energy (2.36 -0.33 +0.32) x 10^2 keV
GRB080916009...break_scale (2.6 -0.8 +0.9) x 10^-1
GRB080916009...beta -2.12 -0.11 +0.10

Values of -log(posterior) at the minimum:

-log(posterior)
b0 -1051.870823
n3 -1021.465423
n4 -1014.154848
total -3087.491093

Values of statistical measures:

statistical measures
AIC 6185.152641
BIC 6204.384852
DIC 6172.726263
PDIC 4.664403
log(Z) -1346.717432
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  400
 dimensionality =    5
 *****************************************************
 ln(ev)=  -3100.9314830335557      +/-  0.22284341836332919
 Total Likelihood Evaluations:        24729
 Sampling finished. Exiting MultiNest

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)
../_images/notebooks_grb080916C_22_0.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)

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")

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)

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 = (0, 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)
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (3.6 -0.6 +0.5) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-5.5 +/- 1.2) x 10^-1
grb.spectrum.main.Band.xp (3.3 +/- 0.6) x 10^2 keV
grb.spectrum.main.Band.beta -2.20 -0.27 +0.26

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval0 -279.501800
n3_interval0 -244.332976
n4_interval0 -261.943445
total -785.778221

Values of statistical measures:

statistical measures
AIC 1579.669757
BIC 1595.078574
DIC 1557.867811
PDIC 2.491818
log(Z) -342.286437
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (4.10 -0.14 +0.15) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-8.62 -0.29 +0.28) x 10^-1
grb.spectrum.main.Band.xp (6.4 +/- 0.6) x 10^2 keV
grb.spectrum.main.Band.beta -2.18 +/- 0.10

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval1 -665.865598
n3_interval1 -633.851366
n4_interval1 -637.513326
total -1937.230290

Values of statistical measures:

statistical measures
AIC 3882.573894
BIC 3897.982711
DIC 3857.970422
PDIC 3.971512
log(Z) -843.629653
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (3.9 -0.6 +0.5) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-8.4 -0.9 +1.0) x 10^-1
grb.spectrum.main.Band.xp (2.7 +/- 0.7) x 10^2 keV
grb.spectrum.main.Band.beta -1.80 -0.11 +0.17

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval2 -317.227476
n3_interval2 -282.412924
n4_interval2 -306.036314
total -905.676714

Values of statistical measures:

statistical measures
AIC 1819.466743
BIC 1834.875560
DIC 1798.192815
PDIC -0.620745
log(Z) -396.819499
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.9 +/- 0.4) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-9.2 -0.9 +1.0) x 10^-1
grb.spectrum.main.Band.xp (3.5 +/- 0.7) x 10^2 keV
grb.spectrum.main.Band.beta -2.36 +/- 0.32

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval3 -292.410312
n3_interval3 -236.580772
n4_interval3 -256.554966
total -785.546049

Values of statistical measures:

statistical measures
AIC 1579.205413
BIC 1594.614231
DIC 1558.296932
PDIC 3.121258
log(Z) -342.193982
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.04 +/- 0.11) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-9.8 +/- 0.4) x 10^-1
grb.spectrum.main.Band.xp (4.1 +/- 0.5) x 10^2 keV
grb.spectrum.main.Band.beta -2.00 +/- 0.10

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval4 -772.391000
n3_interval4 -750.552692
n4_interval4 -740.922013
total -2263.865705

Values of statistical measures:

statistical measures
AIC 4535.844724
BIC 4551.253541
DIC 4515.447965
PDIC 3.535870
log(Z) -986.053683
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.77 +/- 0.19) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-9.2 +/- 0.5) x 10^-1
grb.spectrum.main.Band.xp (4.4 +/- 0.6) x 10^2 keV
grb.spectrum.main.Band.beta -2.24 +/- 0.20

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval5 -530.484927
n3_interval5 -516.895060
n4_interval5 -520.999941
total -1568.379928

Values of statistical measures:

statistical measures
AIC 3144.873169
BIC 3160.281987
DIC 3123.006741
PDIC 3.198584
log(Z) -683.104951
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.95 +/- 0.12) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha -1.01 -0.05 +0.04
grb.spectrum.main.Band.xp (4.6 +/- 0.6) x 10^2 keV
grb.spectrum.main.Band.beta -2.49 +/- 0.30

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval6 -603.136105
n3_interval6 -577.531400
n4_interval6 -570.555602
total -1751.223108

Values of statistical measures:

statistical measures
AIC 3510.559529
BIC 3525.968347
DIC 3487.293200
PDIC 3.246952
log(Z) -762.150486
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.68 +/- 0.11) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha -1.04 +/- 0.05
grb.spectrum.main.Band.xp (4.4 +/- 0.7) x 10^2 keV
grb.spectrum.main.Band.beta -2.38 +/- 0.26

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval7 -656.289301
n3_interval7 -633.887222
n4_interval7 -644.586773
total -1934.763296

Values of statistical measures:

statistical measures
AIC 3877.639905
BIC 3893.048723
DIC 3855.255109
PDIC 3.106573
log(Z) -842.270392
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.53 +/- 0.12) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-8.5 +/- 0.6) x 10^-1
grb.spectrum.main.Band.xp (3.9 +/- 0.5) x 10^2 keV
grb.spectrum.main.Band.beta -2.44 -0.28 +0.26

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval8 -696.348828
n3_interval8 -692.146204
n4_interval8 -660.661605
total -2049.156637

Values of statistical measures:

statistical measures
AIC 4106.426589
BIC 4121.835407
DIC 4085.419196
PDIC 3.150361
log(Z) -891.876974
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.6 -0.9 +0.7) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-8.0 -2.6 +2.9) x 10^-1
grb.spectrum.main.Band.xp (1.2 +/- 0.5) x 10^2 keV
grb.spectrum.main.Band.beta -1.99 +/- 0.23

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval9 -645.831303
n3_interval9 -614.372553
n4_interval9 -613.320913
total -1873.524769

Values of statistical measures:

statistical measures
AIC 3755.162852
BIC 3770.571670
DIC 3678.790508
PDIC -62.074333
log(Z) -815.900088
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.2 +/- 0.5) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-7.0 +/- 1.3) x 10^-1
grb.spectrum.main.Band.xp (2.2 +/- 0.5) x 10^2 keV
grb.spectrum.main.Band.beta -2.05 -0.27 +0.22

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval10 -456.054359
n3_interval10 -432.889628
n4_interval10 -428.861288
total -1317.805276

Values of statistical measures:

statistical measures
AIC 2643.723866
BIC 2659.132684
DIC 2624.315699
PDIC 0.480486
log(Z) -574.294261
  analysing data from chains/fit-.txt
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (3.3 -1.4 +1.3) x 10^-2 1 / (cm2 keV s)
grb.spectrum.main.Band.alpha (-4.5 +/- 2.4) x 10^-1
grb.spectrum.main.Band.xp (1.30 +/- 0.30) x 10^2 keV
grb.spectrum.main.Band.beta -2.18 -0.34 +0.31

Values of -log(posterior) at the minimum:

-log(posterior)
b0_interval11 -288.715915
n3_interval11 -268.537154
n4_interval11 -252.043121
total -809.296190

Values of statistical measures:

statistical measures
AIC 1626.705694
BIC 1642.114512
DIC 1609.022812
PDIC 0.122371
log(Z) -352.600231
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -788.14364824596362      +/-  0.17487841348511493
 Total Likelihood Evaluations:        16976
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -1942.5290624950521      +/-  0.20836653502316885
 Total Likelihood Evaluations:        29025
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -913.71066409063133      +/-  0.19287301374152255
 Total Likelihood Evaluations:        17954
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -787.93076169419589      +/-  0.17451256862722223
 Total Likelihood Evaluations:        18267
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -2270.4725113736431      +/-  0.19681024189041060
 Total Likelihood Evaluations:        21160
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -1572.9072782578137      +/-  0.19077222472342042
 Total Likelihood Evaluations:        20372
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -1754.9163477396487      +/-  0.19082557099682843
 Total Likelihood Evaluations:        21599
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -1939.3992487423766      +/-  0.19179280493260278
 Total Likelihood Evaluations:        19935
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -2053.6226259562077      +/-  0.18610658650450865
 Total Likelihood Evaluations:        20755
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -1878.6793805788338      +/-  0.14587617783375365
 Total Likelihood Evaluations:        12496
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -1322.3614033305889      +/-  0.16813012382990544
 Total Likelihood Evaluations:        15014
 Sampling finished. Exiting MultiNest
 *****************************************************
 MultiNest v3.10
 Copyright Farhan Feroz & Mike Hobson
 Release Jul 2015

 no. of live points =  500
 dimensionality =    4
 *****************************************************
 ln(ev)=  -811.89203584113238      +/-  0.14581596841063021
 Total Likelihood Evaluations:        12667
 Sampling finished. Exiting MultiNest

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, -99], step=False)
../_images/notebooks_grb080916C_41_0.png
../_images/notebooks_grb080916C_41_1.png
../_images/notebooks_grb080916C_41_2.png
../_images/notebooks_grb080916C_41_3.png
../_images/notebooks_grb080916C_41_4.png
../_images/notebooks_grb080916C_41_5.png
../_images/notebooks_grb080916C_41_6.png
../_images/notebooks_grb080916C_41_7.png
../_images/notebooks_grb080916C_41_8.png
../_images/notebooks_grb080916C_41_9.png
../_images/notebooks_grb080916C_41_10.png
../_images/notebooks_grb080916C_41_11.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.