def setup(self): self.model = LogParabolaSpectralModel( amplitude=3.76e-11 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.TeV, alpha=2.44, beta=0.25, ) self.model.covariance = [ [1.31e-23, 0, -6.80e-14, 3.04e-13], [0, 0, 0, 0], [-6.80e-14, 0, 0.00899, 0.00904], [3.04e-13, 0, 0.00904, 0.0284], ]
class TestSpectralModelErrorPropagation: """Test spectral model error propagation. https://github.com/gammapy/gammapy/blob/master/docs/development/pigs/pig-014.rst#proposal https://nbviewer.jupyter.org/github/gammapy/gammapy-extra/blob/master/experiments/uncertainty_estimation_prototype.ipynb """ def setup(self): self.model = LogParabolaSpectralModel( amplitude=3.76e-11 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.TeV, alpha=2.44, beta=0.25, ) self.model.covariance = [ [1.31e-23, 0, -6.80e-14, 3.04e-13], [0, 0, 0, 0], [-6.80e-14, 0, 0.00899, 0.00904], [3.04e-13, 0, 0.00904, 0.0284], ] def test_evaluate_error_scalar(self): # evaluate_error on scalar out = self.model.evaluate_error(1 * u.TeV) assert isinstance(out, u.Quantity) assert out.unit == "cm-2 s-1 TeV-1" assert out.shape == (2,) assert_allclose(out.data, [3.7600e-11, 3.6193e-12], rtol=1e-3) def test_evaluate_error_array(self): out = self.model.evaluate_error([1, 100] * u.TeV) assert out.shape == (2, 2) expected = [[3.76e-11, 2.469e-18], [3.619e-12, 9.375e-18]] assert_allclose(out.data, expected, rtol=1e-3) def test_evaluate_error_unit(self): out = self.model.evaluate_error(1e6 * u.MeV) assert out.unit == "cm-2 s-1 TeV-1" assert_allclose(out.data, [3.760e-11, 3.6193e-12], rtol=1e-3) def test_integral_error(self): out = self.model.integral_error(1 * u.TeV, 10 * u.TeV) assert out.unit == "cm-2 s-1" assert out.shape == (2,) assert_allclose(out.data, [2.197e-11, 2.796e-12], rtol=1e-3) def test_energy_flux_error(self): out = self.model.energy_flux_error(1 * u.TeV, 10 * u.TeV) assert out.unit == "TeV cm-2 s-1" assert out.shape == (2,) assert_allclose(out.data, [4.119e-11, 8.157e-12], rtol=1e-3)
def spectral_model(self): """Best fit spectral model (`~gammapy.modeling.models.SpectralModel`).""" d = self.data spec_type = self.data["SpectrumType"].strip() pars, errs = {}, {} pars["amplitude"] = d["Flux_Density"] errs["amplitude"] = d["Unc_Flux_Density"] pars["reference"] = d["Pivot_Energy"] if spec_type == "PowerLaw": pars["index"] = d["PowerLaw_Index"] errs["index"] = d["Unc_PowerLaw_Index"] model = PowerLawSpectralModel(**pars) elif spec_type == "LogParabola": pars["alpha"] = d["Spectral_Index"] pars["beta"] = d["beta"] errs["alpha"] = d["Unc_Spectral_Index"] errs["beta"] = d["Unc_beta"] model = LogParabolaSpectralModel(**pars) else: raise ValueError(f"Invalid spec_type: {spec_type!r}") model.parameters.set_parameter_errors(errs) return model
def define_model(): crab_spectrum = LogParabolaSpectralModel(amplitude=1e-11 / u.cm**2 / u.s / u.TeV, reference=1 * u.TeV, alpha=2.3, beta=0.2) crab_model = SkyModel(spatial_model=None, spectral_model=crab_spectrum, name="crab") return crab_model
def spectral_model(self): """Best fit spectral model (`~gammapy.modeling.models.SpectralModel`).""" spec_type = self.data["SpectrumType"].strip() pars, errs = {}, {} pars["amplitude"] = self.data["Flux_Density"] errs["amplitude"] = self.data["Unc_Flux_Density"] pars["reference"] = self.data["Pivot_Energy"] if spec_type == "PowerLaw": pars["index"] = self.data["Spectral_Index"] errs["index"] = self.data["Unc_Spectral_Index"] model = PowerLawSpectralModel(**pars) elif spec_type == "PLExpCutoff": pars["index"] = self.data["Spectral_Index"] pars["ecut"] = self.data["Cutoff"] errs["index"] = self.data["Unc_Spectral_Index"] errs["ecut"] = self.data["Unc_Cutoff"] model = ExpCutoffPowerLaw3FGLSpectralModel(**pars) elif spec_type == "LogParabola": pars["alpha"] = self.data["Spectral_Index"] pars["beta"] = self.data["beta"] errs["alpha"] = self.data["Unc_Spectral_Index"] errs["beta"] = self.data["Unc_beta"] model = LogParabolaSpectralModel(**pars) elif spec_type == "PLSuperExpCutoff": # TODO: why convert to GeV here? Remove? pars["reference"] = pars["reference"].to("GeV") pars["index_1"] = self.data["Spectral_Index"] pars["index_2"] = self.data["Exp_Index"] pars["ecut"] = self.data["Cutoff"].to("GeV") errs["index_1"] = self.data["Unc_Spectral_Index"] errs["index_2"] = self.data["Unc_Exp_Index"] errs["ecut"] = self.data["Unc_Cutoff"].to("GeV") model = SuperExpCutoffPowerLaw3FGLSpectralModel(**pars) else: raise ValueError(f"Invalid spec_type: {spec_type!r}") model.parameters.set_parameter_errors(errs) return model
def spectral_model(self): """Best fit spectral model (`~gammapy.modeling.models.SpectralModel`).""" spec_type = self.data["SpectrumType"].strip() pars, errs = {}, {} pars["reference"] = self.data["Pivot_Energy"] if spec_type == "PowerLaw": pars["amplitude"] = self.data["PL_Flux_Density"] pars["index"] = self.data["PL_Index"] errs["amplitude"] = self.data["Unc_PL_Flux_Density"] errs["index"] = self.data["Unc_PL_Index"] model = PowerLawSpectralModel(**pars) elif spec_type == "LogParabola": pars["amplitude"] = self.data["LP_Flux_Density"] pars["alpha"] = self.data["LP_Index"] pars["beta"] = self.data["LP_beta"] errs["amplitude"] = self.data["Unc_LP_Flux_Density"] errs["alpha"] = self.data["Unc_LP_Index"] errs["beta"] = self.data["Unc_LP_beta"] model = LogParabolaSpectralModel(**pars) elif spec_type == "PLSuperExpCutoff": pars["amplitude"] = self.data["PLEC_Flux_Density"] pars["index_1"] = self.data["PLEC_Index"] pars["index_2"] = self.data["PLEC_Exp_Index"] pars["expfactor"] = self.data["PLEC_Expfactor"] errs["amplitude"] = self.data["Unc_PLEC_Flux_Density"] errs["index_1"] = self.data["Unc_PLEC_Index"] errs["index_2"] = np.nan_to_num(self.data["Unc_PLEC_Exp_Index"]) errs["expfactor"] = self.data["Unc_PLEC_Expfactor"] model = SuperExpCutoffPowerLaw4FGLSpectralModel(**pars) else: raise ValueError(f"Invalid spec_type: {spec_type!r}") model.parameters.set_parameter_errors(errs) return model
model=SuperExpCutoffPowerLaw4FGLSpectralModel( index_1=1.5, index_2=2, amplitude=1 / u.cm ** 2 / u.s / u.TeV, reference=1 * u.TeV, expfactor=1e-2, ), val_at_2TeV=u.Quantity(0.3431043087721737, "cm-2 s-1 TeV-1"), integral_1_10TeV=u.Quantity(1.2125247, "cm-2 s-1"), eflux_1_10TeV=u.Quantity(3.38072082, "TeV cm-2 s-1"), ), dict( name="logpar", model=LogParabolaSpectralModel( alpha=2.3 * u.Unit(""), amplitude=4 / u.cm ** 2 / u.s / u.TeV, reference=1 * u.TeV, beta=0.5 * u.Unit(""), ), val_at_2TeV=u.Quantity(0.6387956571420305, "cm-2 s-1 TeV-1"), integral_1_10TeV=u.Quantity(2.255689748270628, "cm-2 s-1"), eflux_1_10TeV=u.Quantity(3.9586515834989267, "TeV cm-2 s-1"), e_peak=0.74082 * u.TeV, ), dict( name="norm-logpar", model=LogParabolaNormSpectralModel( alpha=2.3 * u.Unit(""), norm=4 * u.Unit(""), reference=1 * u.TeV, beta=0.5 * u.Unit(""), ),
def logpar_reference_model(): logpar = LogParabolaSpectralModel(amplitude="2e-12 cm-2s-1TeV-1", alpha=1.5, beta=0.5) return SkyModel(spatial_model=PointSpatialModel(), spectral_model=logpar)
from astropy import units as u import matplotlib.pyplot as plt from gammapy.modeling.models import ( CompoundSpectralModel, LogParabolaSpectralModel, Models, PowerLawSpectralModel, SkyModel, ) energy_range = [0.1, 100] * u.TeV pwl = PowerLawSpectralModel( index=2.0, amplitude="1e-12 cm-2 s-1 TeV-1", reference="1 TeV" ) lp = LogParabolaSpectralModel( amplitude="1e-12 cm-2 s-1 TeV-1", reference="10 TeV", alpha=2.0, beta=1.0 ) model = CompoundSpectralModel(pwl, lp, operator.add) model.plot(energy_range) plt.grid(which="both") # %% # YAML representation # ------------------- # Here is an example YAML file using the model: model = SkyModel(spectral_model=model, name="compound-model") models = Models([model]) print(models.to_yaml())
""" # %% # Example plot # ------------ # Here is an example plot of the model: from astropy import units as u import matplotlib.pyplot as plt from gammapy.modeling.models import LogParabolaSpectralModel, Models, SkyModel energy_range = [0.1, 100] * u.TeV model = LogParabolaSpectralModel( alpha=2.3, amplitude="1e-12 cm-2 s-1 TeV-1", reference=1 * u.TeV, beta=0.5, ) model.plot(energy_range) plt.grid(which="both") # %% # YAML representation # ------------------- # Here is an example YAML file using the model: model = SkyModel(spectral_model=model, name="log-parabola-model") models = Models([model]) print(models.to_yaml())
class TestSpectralModelErrorPropagation: """Test spectral model error propagation. https://github.com/gammapy/gammapy/blob/master/docs/development/pigs/pig-014.rst#proposal https://nbviewer.jupyter.org/github/gammapy/gammapy-extra/blob/master/experiments/uncertainty_estimation_prototype.ipynb """ def setup(self): self.model = LogParabolaSpectralModel( amplitude=3.76e-11 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.TeV, alpha=2.44, beta=0.25, ) self.model.covariance = [ [1.31e-23, 0, -6.80e-14, 3.04e-13], [0, 0, 0, 0], [-6.80e-14, 0, 0.00899, 0.00904], [3.04e-13, 0, 0.00904, 0.0284], ] def test_evaluate_error_scalar(self): # evaluate_error on scalar out = self.model.evaluate_error(1 * u.TeV) assert isinstance(out, u.Quantity) assert out.unit == "cm-2 s-1 TeV-1" assert out.shape == (2, ) assert_allclose(out.data, [3.7600e-11, 3.6193e-12], rtol=1e-3) def test_evaluate_error_array(self): out = self.model.evaluate_error([1, 100] * u.TeV) assert out.shape == (2, 2) expected = [[3.76e-11, 2.469e-18], [3.619e-12, 9.375e-18]] assert_allclose(out.data, expected, rtol=1e-3) def test_evaluate_error_unit(self): out = self.model.evaluate_error(1e6 * u.MeV) assert out.unit == "cm-2 s-1 TeV-1" assert_allclose(out.data, [3.760e-11, 3.6193e-12], rtol=1e-3) @pytest.mark.xfail(reason="FIXME, do we need this method?") def test_integral_error(self): out = self.model.integral_error(1 * u.TeV, 10 * u.TeV) assert out.unit == "cm-2 s-1" assert out.shape == (2, ) assert_allclose(out.data, [2.197e-11, 2.796e-12], rtol=1e-3) @pytest.mark.xfail(reason="FIXME, do we need this method?") def test_energy_flux_error(self): out = self.model.energy_flux_error(1 * u.TeV, 10 * u.TeV) assert out.unit == "TeV cm-2 s-1" assert out.shape == (2, ) assert_allclose(out.data, [4.119e-11, 8.157e-12], rtol=1e-3) def test_ecpl_model(self): # Regression test for ECPL model # https://github.com/gammapy/gammapy/issues/2007 model = ExpCutoffPowerLawSpectralModel( amplitude=2.076183759227292e-12 * u.Unit("cm-2 s-1 TeV-1"), index=1.8763343736076483, lambda_=0.08703226432146616 * u.Unit("TeV-1"), reference=1 * u.TeV, ) model.covariance = [ [0.00204191498, -1.507724e-14, 0.0, -0.001834819, 0.0], [-1.507724e-14, 1.6864740e-25, 0.0, 1.854251e-14, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [-0.001834819175, 1.8542517e-14, 0.0, 0.0032559101, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0], ] out = model.evaluate_error(1 * u.TeV) assert_allclose(out.data, [1.903129e-12, 2.979976e-13], rtol=1e-3) out = model.evaluate_error(0.1 * u.TeV) assert_allclose(out.data, [1.548176e-10, 1.933612e-11], rtol=1e-3)
ecpl.plot(energy_range=[1e-4, 1e2] * u.TeV, ax=ax, energy_power=2) # assign covariance for plotting ecpl.parameters.covariance = result_ecpl.parameters.covariance ecpl.plot_error(energy_range=[1e-4, 1e2] * u.TeV, ax=ax, energy_power=2) ax.set_ylim(1e-13, 1e-11) # ## Log-Parabola Fit # # Finally we try to fit a `~gammapy.modeling.models.LogParabolaSpectralModel` model: # In[ ]: log_parabola = LogParabolaSpectralModel(alpha=2, amplitude="1e-12 cm-2 s-1 TeV-1", reference="1 TeV", beta=0.1) model = SkyModel(spectral_model=log_parabola) # In[ ]: dataset_log_parabola = FluxPointsDataset(model, flux_points) fitter = Fit([dataset_log_parabola]) result_log_parabola = fitter.run() print(log_parabola) # In[ ]: ax = flux_points.plot(energy_power=2) log_parabola.plot(energy_range=[1e-4, 1e2] * u.TeV, ax=ax, energy_power=2)
def rate(shape, emin, emax, param, cone, area): """ Calculates the rate of events for a power-law distribution, in a given energy range, collection area and solid angle Parameters ---------- shape: `string` weighted spectrum shape emin: `float` minimum energy emax: `float` maximum energy param: `dict` with weighted spectral parameters cone: `float` angle [deg] for the solid angle cone area: `float` collection area [cm**2] if shape is 'PowerLaw': param should include 'f0','e0','alpha' dFdE = f0 * np.power(E / e0, alpha) if shape is 'LogParabola': param should include 'f0','e0','alpha','beta' dFdE = f0 * np.power(E / e0, alpha + beta * np.log10(E/e0)) Returns ------- rate: `float` rate of events """ if (cone == 0): omega = 1 else: omega = 2 * np.pi * (1 - np.cos(cone)) * u.sr if (shape == "PowerLaw"): if (len(param) != 3): print("param included {} parameters, not 3".format(len(param))) print("param should include 'f0', 'e0', 'alpha'") sys.exit(1) for key in ['f0', 'e0', 'alpha']: if (key not in param.keys()): print("{} is missing in param".format(key)) print("param should include 'f0', 'e0', 'alpha'") sys.exit(1) integral = param['f0'] * int_diff_sp(emin, emax, param['alpha'], param['e0']) elif (shape == "LogParabola"): if (len(param) != 4): print("param included {} parameters, not 4".format(len(param))) print("param should include 'f0', 'e0', 'alpha', 'beta'") sys.exit(1) for key in ['f0', 'e0', 'alpha', 'beta']: if (key not in param.keys()): print("{} is missing in param".format(key)) print("param should include 'f0', 'e0', 'alpha', 'beta'") sys.exit(1) log_parabola = LogParabolaSpectralModel.from_log10( amplitude=param['f0'], reference=param['e0'], alpha=-1 * param['alpha'], beta=-1 * param['beta']) integral = log_parabola.integral(emin, emax) rate = area * omega * integral return rate
def weight(shape, emin, emax, sim_sp_idx, rate, nev, w_param): """ Calculates the weight of events to transform a power-law distribution with spectral index sim_sp_idx to a power-law distribution with spectral index w_sp_idx Parameters ---------- shape: `string` estimated spectrum shape emin: `float` minimum energy emax: `float` maximum energy sim_sp_idx: `float` simulated spectral index of the power-law distribution rate: `float` rate of simulated events nev: `int` number of simulated events w_param: `dict` with weighted spectral parameters if shape is 'PowerLaw': w_param should include 'f0','e0','alpha' dFdE = f0 * np.power(E / e0, alpha) if shape is 'LogParabola': w_param should include 'f0','e0','alpha','beta' dFdE = f0 * np.power(E / e0, alpha + beta * np.log10(E/e0)) Returns ------- weight: `float` rate of events """ sim_integral = nev / int_diff_sp(emin, emax, sim_sp_idx, w_param['e0']) if (shape == "PowerLaw"): if (len(w_param) != 3): print("param included {} parameters, not 3".format(len(w_param))) print("param should include 'f0', 'e0', 'alpha'") sys.exit(1) for key in ['f0', 'e0', 'alpha']: if (key not in w_param.keys()): print("{} is missing in param".format(key)) print("param should include 'f0', 'e0', 'alpha'") sys.exit(1) norm_sim = sim_integral * int_diff_sp(emin, emax, w_param['alpha'], w_param['e0']) elif (shape == "LogParabola"): if (len(w_param) != 4): print("param included {} parameters, not 4".format(len(w_param))) print("param should include 'f0', 'e0', 'alpha', 'beta'") sys.exit(1) for key in ['f0', 'e0', 'alpha', 'beta']: if (key not in w_param.keys()): print("{} is missing in param".format(key)) print("param should include 'f0', 'e0', 'alpha', 'beta'") sys.exit(1) log_parabola = LogParabolaSpectralModel.from_log10( amplitude=sim_integral / (u.s * u.cm * u.cm), reference=w_param['e0'], alpha=-1 * w_param['alpha'], beta=-1 * w_param['beta']) norm_sim = log_parabola.integral(emin, emax) * (u.s * u.cm * u.cm) weight = rate / norm_sim return weight
import logging import numpy as np from astropy.table import Table from gammapy.estimators import FluxPoints from astropy import units as u from gammapy.modeling.models import LogParabolaSpectralModel # ### HAWC flux points for Crab Nebula # The HAWC flux point are taken from https://arxiv.org/pdf/1905.12518.pdf # assigned to a `FluxPoints` object, then written to FITS. crab_model = LogParabolaSpectralModel(amplitude="2.31e-13 TeV-1 cm-2 s-1", alpha=2.73, beta=0.06, reference="7 TeV") e_min = np.array([1, 1.78, 3.16, 5.62, 10.0, 17.8, 31.6, 56.2, 100, 177 ]) * u.TeV e_max = np.array([1.78, 3.16, 5.62, 10.0, 17.8, 31.6, 56.2, 100, 177, 316 ]) * u.TeV e_ref = np.array([1.04, 1.83, 3.24, 5.84, 10.66, 19.6, 31.6, 66.8, 118, 204 ]) * u.TeV ts = np.array([2734, 4112, 4678, 3683, 2259, 1237, 572, 105, 28.8, 0.14]) is_ul = np.array( [False, False, False, False, False, False, False, False, False, True]) e2dnde = np.array([ 3.63e-11, 2.67e-11, 1.92e-11, 1.24e-11, 8.15e-12, 5.23e-12, 3.26e-12, 1.23e-12, 8.37e-13, np.nan ]) * u.Unit("cm-2 s-1 TeV")