Most of the current plugins support the ability to generate synthetic data directly from a model. This can be very useful to assertain the detectability of a source/component/line or simply to see how models look once they are transformed into data. Below we will demonstrate how different plugins transform a model into synthetic data.
In [47]:
import numpy as np
%matplotlib notebook
import matplotlib.pyplot as plt
from threeML import *
import warnings
warnings.simplefilter('ignore')
In [48]:
# Select an astromodels function to from which to simualte
generating_function = Powerlaw(K=1., index=-2, piv=10.)
# set up the x grig points
x_points = np.logspace(0, 2, 50)
# call the from_function classmethod
xyl_generator = XYLike.from_function("sim_data",
function = generating_function,
x = x_points,
yerr = 0.3 * generating_function(x_points))
xyl_generator.plot(x_scale='log',y_scale='log');
In [49]:
energies = np.logspace(0,2,51)
# create the low and high energy bin edges
low_edge = energies[:-1]
high_edge = energies[1:]
Now, let's use a blackbody for the source spectrum.
In [50]:
# get a BPL source function
source_function = Blackbody(K=1, kT = 5.)
In [51]:
spectrum_generator = SpectrumLike.from_function('fake',
source_function=source_function,
energy_min=low_edge,
energy_max=high_edge)
spectrum_generator.view_count_spectrum()
In [52]:
spectrum_generator = SpectrumLike.from_function('fake',
source_function=source_function,
source_errors= 0.5 * source_function(low_edge),
energy_min=low_edge,
energy_max=high_edge)
spectrum_generator.view_count_spectrum()
In [53]:
# power law background function
background_function = Powerlaw(K=.7,index=-1.5, piv=10.)
spectrum_generator = SpectrumLike.from_function('fake',
source_function=source_function,
background_function=background_function,
energy_min=low_edge,
energy_max=high_edge)
spectrum_generator.view_count_spectrum()
In [54]:
spectrum_generator = SpectrumLike.from_function('fake',
source_function=source_function,
background_function=background_function,
background_errors= 0.1 * background_function(low_edge),
energy_min=low_edge,
energy_max=high_edge)
spectrum_generator.view_count_spectrum()
In [55]:
from threeML.io.package_data import get_path_of_data_file
from threeML.plugins.OGIP.response import OGIPResponse
# we will use a demo response
response = OGIPResponse(get_path_of_data_file('datasets/ogip_powerlaw.rsp'))
In [56]:
# rescale the functions for the response
source_function = Blackbody(K=1E-7, kT = 500.)
background_function = Powerlaw(K=1,index=-1.5, piv=1.E3)
spectrum_generator = DispersionSpectrumLike.from_function('fake',
source_function=source_function,
background_function=background_function,
response = response
)
spectrum_generator.view_count_spectrum()
In [57]:
data_path = get_path_of_data_file("datasets/xy_powerlaw.txt")
xyl = XYLike.from_text_file("xyl", data_path)
fit_function = Powerlaw()
xyl.fit(fit_function)
xyl.plot(x_scale='log', y_scale='log');
Once our fit has been finished, we can produce simulated data sets from those model parameters.
In [58]:
synthetic_xyl = xyl.get_simulated_dataset()
synthetic_xyl.plot(x_scale='log', y_scale='log');
Both spectrum plugins work in the same way when generating data from a fit. They both keep track of the statistical properties of the likelihoods in the plugin so that the simulated datasets have the appropriate statistical properties. Additionally, background, responsses, etc. are simulated and/or kept track of as well.
Let's fit an example energy dispersed spectrum.
In [63]:
ogip_data = OGIPLike('ogip',
observation=get_path_of_data_file('datasets/ogip_powerlaw.pha'),
background = get_path_of_data_file('datasets/ogip_powerlaw.bak'),
response=get_path_of_data_file('datasets/ogip_powerlaw.rsp')
)
ogip_data.view_count_spectrum()
# define the function
fit_function = Cutoff_powerlaw()
# define the point source
point_source = PointSource('ps', 0, 0, spectral_shape=fit_function)
#define the model
model = Model(point_source)
# create a data list
datalist = DataList(ogip_data)
# make the joint likelihood
jl = JointLikelihood(model, datalist)
#fit
jl.fit();
Now we can now generate synthetic datasets from the fitted model. This will include the background sampled properly from the profile likelihood. The instrument response is automatically passed to the new plugin.
In [62]:
synthetic_ogip = ogip_data.get_simulated_dataset()
synthetic_ogip.view_count_spectrum()
In [ ]: