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")
[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)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 2) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 3) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
The TTE file /home/runner/work/threeML/threeML/docs/md_docs/slow_execute/glg_tte_n3_bn080916009_v01.fit.gz contains duplicate time tags and is thus invalid. Contact the FSSC
The TTE file /home/runner/work/threeML/threeML/docs/md_docs/slow_execute/glg_tte_n3_bn080916009_v01.fit.gz was not sorted in time but contains no duplicate events. We will sort the times, but use caution with this file. Contact the FSSC.
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 2) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 3) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 2) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 3) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
The TTE file /home/runner/work/threeML/threeML/docs/md_docs/slow_execute/glg_tte_n4_bn080916009_v01.fit.gz was not sorted in time but contains no duplicate events. We will sort the times, but use caution with this file. Contact the FSSC.
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 2) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 3) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 2) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 3) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
The TTE file /home/runner/work/threeML/threeML/docs/md_docs/slow_execute/glg_tte_b0_bn080916009_v01.fit.gz contains duplicate time tags and is thus invalid. Contact the FSSC
The TTE file /home/runner/work/threeML/threeML/docs/md_docs/slow_execute/glg_tte_b0_bn080916009_v01.fit.gz was not sorted in time but contains no duplicate events. We will sort the times, but use caution with this file. Contact the FSSC.
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 1) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 2) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
The default choice for MATRIX extension failed:KeyError("Extension ('MATRIX', 3) not found.")available: None 'EBOUNDS' 'SPECRESP MATRIX' 'SPECRESP MATRIX' 'SPECRESP MATRIX'
No TLMIN keyword found. This DRM does not follow OGIP standards. Assuming TLMIN=1
../_images/notebooks_grb080916C_12_16.png
../_images/notebooks_grb080916C_12_17.png
../_images/notebooks_grb080916C_12_18.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
)
We have set the min_value of GRB080916009.spectrum.main.SmoothlyBrokenPowerLaw.break_energy to 1e-99 because there was a postive transform
We have set the min_value of GRB080916009.spectrum.main.SmoothlyBrokenPowerLaw.break_energy to 1e-99 because there was a postive transform

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()
 *****************************************************
 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)=  -3101.7030180684878      +/-  0.22660367880748331
 Total Likelihood Evaluations:        21669
 Sampling finished. Exiting MultiNest

Maximum a posteriori probability (MAP) point:

result unit
parameter
GRB080916009...K (1.464 -0.010 +0.027) x 10^-2 1 / (keV s cm2)
GRB080916009...alpha -1.0961 +0.0023 +0.04
GRB080916009...break_energy (1.90 +0.06 +0.6) x 10^2 keV
GRB080916009...break_scale (0.0 +1.5 +3.1) x 10^-1
GRB080916009...beta -1.966 -0.18 -0.031
Values of -log(posterior) at the minimum:

-log(posterior)
n3 -1019.163645
n4 -1010.394657
b0 -1050.126755
total -3079.685057
Values of statistical measures:

statistical measures
AIC 6169.540568
BIC 6188.772779
DIC 6178.943007
PDIC 3.994626
log(Z) -1347.052505

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)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.267000198364258)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)
Minimum MC energy (5.0) is larger than minimum EBOUNDS energy (4.369999885559082)

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)
We have set the min_value of Band.xp to 1e-99 because there was a postive transform
We have set the min_value of Band.xp to 1e-99 because there was a postive transform

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)
 *****************************************************
 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)=  -794.23313915430845      +/-  0.18307557742665900
 Total Likelihood Evaluations:        17814
 Sampling finished. Exiting MultiNest
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (5.156 -0.025 +2.2) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-3.4 -0.7 +2.4) x 10^-1
grb.spectrum.main.Band.xp (2.13 -0.4 -0.05) x 10^2 keV
grb.spectrum.main.Band.beta -1.908 -0.026 +0.17
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval0 -249.988613
n4_interval0 -268.234593
b0_interval0 -286.081546
total -804.304752
Values of statistical measures:

statistical measures
AIC 1616.722819
BIC 1632.131636
DIC 1576.777511
PDIC 2.041296
log(Z) -344.931070
 *****************************************************
 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)=  -1951.6163871246006      +/-  0.21797861461220208
 Total Likelihood Evaluations:        23067
 Sampling finished. Exiting MultiNest

Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (4.25 +0.04 +0.5) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-8.671 -0.035 +1.2) x 10^-1
grb.spectrum.main.Band.xp (5.65 -1.2 -0.09) x 10^2 keV
grb.spectrum.main.Band.beta -2.031 +0.004 +0.11
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval1 -644.295357
n4_interval1 -644.837146
b0_interval1 -674.615645
total -1963.748148
Values of statistical measures:

statistical measures
AIC 3935.609610
BIC 3951.018427
DIC 3887.560197
PDIC 6.107314
log(Z) -847.576228
 *****************************************************
 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)=  -907.80826965880237      +/-  0.20320309411430471
 Total Likelihood Evaluations:        19223
 Sampling finished. Exiting MultiNest
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.35 -0.10 +0.23) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha -1.10 -0.04 +0.08
grb.spectrum.main.Band.xp (7.7 -1.6 +2.6) x 10^2 keV
grb.spectrum.main.Band.beta -2.24 -0.5 -0.17
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval2 -290.725053
n4_interval2 -313.265454
b0_interval2 -326.137299
total -930.127806
Values of statistical measures:

statistical measures
AIC 1868.368927
BIC 1883.777745
DIC 1807.790310
PDIC 2.305470
log(Z) -394.256122
 *****************************************************
 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)=  -788.18296630866348      +/-  0.17716726377141628
 Total Likelihood Evaluations:        17711
 Sampling finished. Exiting MultiNest
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.84 -0.28 +0.4) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-9.4 -0.7 +1.1) x 10^-1
grb.spectrum.main.Band.xp (3.5 -0.5 +0.8) x 10^2 keV
grb.spectrum.main.Band.beta -2.197 -0.6 +0.033
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval3 -242.565433
n4_interval3 -262.519550
b0_interval3 -298.499019
total -803.584002
Values of statistical measures:

statistical measures
AIC 1615.281319
BIC 1630.690137
DIC 1570.656230
PDIC 2.933813
log(Z) -342.303513
 *****************************************************
 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)=  -2270.7228167452217      +/-  0.19815068438300870
 Total Likelihood Evaluations:        20322
 Sampling finished. Exiting MultiNest
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.06 -0.13 +0.11) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-9.77 -0.4 +0.33) x 10^-1
grb.spectrum.main.Band.xp (4.0 -0.4 +0.7) x 10^2 keV
grb.spectrum.main.Band.beta -1.96 -0.13 +0.06
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval4 -757.086391
n4_interval4 -746.735868
b0_interval4 -778.484447
total -2282.306706
Values of statistical measures:

statistical measures
AIC 4572.726726
BIC 4588.135544
DIC 4528.076200
PDIC 3.557677
log(Z) -986.162389
 *****************************************************
 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)=  -1573.2138802112599      +/-  0.19244378702462778
 Total Likelihood Evaluations:        19981
 Sampling finished. Exiting MultiNest

Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.84 -0.22 +0.13) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-8.99 -0.6 +0.35) x 10^-1
grb.spectrum.main.Band.xp (4.11 -0.33 +0.7) x 10^2 keV
grb.spectrum.main.Band.beta -2.14 -0.31 +0.11
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval5 -523.770652
n4_interval5 -527.483096
b0_interval5 -536.605600
total -1587.859348
Values of statistical measures:

statistical measures
AIC 3183.832010
BIC 3199.240827
DIC 3136.371051
PDIC 3.143850
log(Z) -683.238107
 *****************************************************
 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)=  -1761.2905554102631      +/-  0.19816661850454784
 Total Likelihood Evaluations:        19240
 Sampling finished. Exiting MultiNest
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.32 -0.05 +0.17) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-8.96 +0.13 +0.6) x 10^-1
grb.spectrum.main.Band.xp (3.21 -0.4 +0.19) x 10^2 keV
grb.spectrum.main.Band.beta -2.122 -0.009 +0.17
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval6 -585.176840
n4_interval6 -575.870192
b0_interval6 -608.570903
total -1769.617935
Values of statistical measures:

statistical measures
AIC 3547.349185
BIC 3562.758003
DIC 3505.644427
PDIC 2.324421
log(Z) -764.918769
 *****************************************************
 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)=  -1939.3941396924686      +/-  0.19267194757058037
 Total Likelihood Evaluations:        20357
 Sampling finished. Exiting MultiNest
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.69 -0.12 +0.09) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha -1.04 -0.05 +0.04
grb.spectrum.main.Band.xp (4.2 -0.4 +0.9) x 10^2 keV
grb.spectrum.main.Band.beta -2.24 -0.5 +0.04
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval7 -640.905272
n4_interval7 -650.280597
b0_interval7 -662.208165
total -1953.394034
Values of statistical measures:

statistical measures
AIC 3914.901383
BIC 3930.310201
DIC 3868.681534
PDIC 3.104665
log(Z) -842.268173
 *****************************************************
 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)=  -2054.6416430209160      +/-  0.19071162222979110
 Total Likelihood Evaluations:        18983
 Sampling finished. Exiting MultiNest

Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.54 -0.09 +0.14) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-8.5 -0.5 +0.7) x 10^-1
grb.spectrum.main.Band.xp (3.7 -0.5 +0.4) x 10^2 keV
grb.spectrum.main.Band.beta -2.27 -0.15 +0.16
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval8 -698.351644
n4_interval8 -666.210963
b0_interval8 -702.092707
total -2066.655313
Values of statistical measures:

statistical measures
AIC 4141.423941
BIC 4156.832758
DIC 4096.935862
PDIC 2.785140
log(Z) -892.319528
 *****************************************************
 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)=  -1878.2846689698104      +/-  0.14241390129164119
 Total Likelihood Evaluations:        13992
 Sampling finished. Exiting MultiNest

Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.2 -0.4 +1.3) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-8.2 -2.3 +3.1) x 10^-1
grb.spectrum.main.Band.xp (1.1 -0.4 +0.6) x 10^2 keV
grb.spectrum.main.Band.beta -1.89 -0.33 +0.16
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval9 -616.995079
n4_interval9 -616.401793
b0_interval9 -648.279790
total -1881.676662
Values of statistical measures:

statistical measures
AIC 3771.466639
BIC 3786.875456
DIC 3683.516819
PDIC -63.698421
log(Z) -815.728667
 *****************************************************
 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.4398855824672      +/-  0.16853859539339605
 Total Likelihood Evaluations:        15514
 Sampling finished. Exiting MultiNest
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (1.95 -0.20 +0.7) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-7.7 -0.8 +1.8) x 10^-1
grb.spectrum.main.Band.xp (2.31 -0.6 +0.30) x 10^2 keV
grb.spectrum.main.Band.beta -1.99 -0.15 +0.18
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval10 -437.675865
n4_interval10 -433.473940
b0_interval10 -460.931260
total -1332.081065
Values of statistical measures:

statistical measures
AIC 2672.275444
BIC 2687.684262
DIC 2633.754414
PDIC 0.530949
log(Z) -574.328345
 *****************************************************
 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.15325649929048      +/-  0.14786773502477099
 Total Likelihood Evaluations:        12215
 Sampling finished. Exiting MultiNest
Maximum a posteriori probability (MAP) point:

result unit
parameter
grb.spectrum.main.Band.K (2.8 -0.9 +1.9) x 10^-2 1 / (keV s cm2)
grb.spectrum.main.Band.alpha (-5.0 -2.4 +2.7) x 10^-1
grb.spectrum.main.Band.xp (1.30 -0.32 +0.34) x 10^2 keV
grb.spectrum.main.Band.beta -2.15 -0.29 +0.26
Values of -log(posterior) at the minimum:

-log(posterior)
n3_interval11 -272.447253
n4_interval11 -255.806117
b0_interval11 -292.391472
total -820.644842
Values of statistical measures:

statistical measures
AIC 1649.402999
BIC 1664.811816
DIC 1615.612728
PDIC -1.280344
log(Z) -352.713678

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)
../_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.