Beispiel #1
0
    def fit_point(self, model, energy_group, energy_ref):
        from gammapy.spectrum import SpectrumFit

        sherpa_model = model.to_sherpa()
        sherpa_model.gamma.freeze()
        fit = SpectrumFit(self.obs, sherpa_model)

        erange = energy_group.energy_range
        # TODO: Notice channels contained in energy_group
        fit.fit_range = erange.min, 0.9999 * erange.max

        log.debug("Calling Sherpa fit for flux point " " in energy range:\n{}".format(fit))

        fit.fit()

        res = fit.global_result

        energy_err_hi = energy_group.energy_range.max - energy_ref
        energy_err_lo = energy_ref - energy_group.energy_range.min
        diff_flux = res.model(energy_ref).to("m-2 s-1 TeV-1")
        err = res.model_with_uncertainties(energy_ref.to("TeV").value)
        diff_flux_err = err.s * u.Unit("m-2 s-1 TeV-1")

        return OrderedDict(
            energy=energy_ref,
            energy_err_hi=energy_err_hi,
            energy_err_lo=energy_err_lo,
            diff_flux=diff_flux,
            diff_flux_err_hi=diff_flux_err,
            diff_flux_err_lo=diff_flux_err,
        )
Beispiel #2
0
    def fit_point(self, model, energy_group, energy_ref):
        from gammapy.spectrum import SpectrumFit

        fit = SpectrumFit(self.obs, model)
        erange = energy_group.energy_range

        # TODO: Notice channels contained in energy_group
        fit.fit_range = erange.min, erange.max

        log.debug('Calling Sherpa fit for flux point '
                  ' in energy range:\n{}'.format(fit))

        fit.fit()
        fit.est_errors()

        # First result contain correct model
        res = fit.result[0]

        e_max = energy_group.energy_range.max
        e_min = energy_group.energy_range.min
        diff_flux, diff_flux_err = res.model.evaluate_error(energy_ref)
        return OrderedDict(
            e_ref=energy_ref,
            e_min=e_min,
            e_max=e_max,
            dnde=diff_flux.to('m-2 s-1 TeV-1'),
            dnde_err=diff_flux_err.to('m-2 s-1 TeV-1'),
        )
Beispiel #3
0
    def fit_point(self, model, energy_group, energy_ref):
        from gammapy.spectrum import SpectrumFit

        sherpa_model = model.to_sherpa()
        sherpa_model.gamma.freeze()
        fit = SpectrumFit(self.obs, sherpa_model)

        erange = energy_group.energy_range
        # TODO: Notice channels contained in energy_group
        fit.fit_range = erange.min, 0.9999 * erange.max

        log.debug(
            'Calling Sherpa fit for flux point '
            ' in energy range:\n{}'.format(fit)
        )

        fit.fit()

        res = fit.global_result

        energy_err_hi = energy_group.energy_range.max - energy_ref
        energy_err_lo = energy_ref - energy_group.energy_range.min
        diff_flux = res.model(energy_ref).to('m-2 s-1 TeV-1')
        err = res.model_with_uncertainties(energy_ref.to('TeV').value)
        diff_flux_err = err.s * Unit('m-2 s-1 TeV-1')

        return OrderedDict(
            energy=energy_ref,
            energy_err_hi=energy_err_hi,
            energy_err_lo=energy_err_lo,
            diff_flux=diff_flux,
            diff_flux_err_hi=diff_flux_err,
            diff_flux_err_lo=diff_flux_err,
        )
Beispiel #4
0
    def fit_point(self, model, energy_group, energy_ref):
        from gammapy.spectrum import SpectrumFit

        # TODO: The code below won't work because SpectrumFit only accepts
        # gammapy models. Add Parameter class to freeze index
        # sherpa_model = model.to_sherpa()
        # sherpa_model.gamma.freeze()
        #fit = SpectrumFit(self.obs, sherpa_model)
        fit = SpectrumFit(self.obs, model)

        erange = energy_group.energy_range
        # TODO: Notice channels contained in energy_group
        fit.fit_range = erange.min, 0.9999 * erange.max

        log.debug('Calling Sherpa fit for flux point '
                  ' in energy range:\n{}'.format(fit))

        fit.fit()
        fit.est_errors()

        # First result contain correct model
        res = fit.result[0]

        e_max = energy_group.energy_range.max
        e_min = energy_group.energy_range.min
        diff_flux, diff_flux_err = res.model.evaluate_error(energy_ref)
        return OrderedDict(
            e_ref=energy_ref,
            e_min=e_min,
            e_max=e_max,
            dnde=diff_flux.to('m-2 s-1 TeV-1'),
            dnde_err=diff_flux_err.to('m-2 s-1 TeV-1'),
        )
print(pwl)

# In[ ]:

livetime = 2 * u.h
sim = SpectrumSimulation(aeff=aeff,
                         edisp=edisp,
                         source_model=pwl,
                         livetime=livetime)
sim.simulate_obs(seed=2309, obs_id=1)
print(sim.obs)

# In[ ]:

fit = SpectrumFit(obs_list=sim.obs, model=pwl.copy(), stat="cash")
fit.fit_range = [1, 10] * u.TeV
fit.run()
print(fit.result[0])

# ## Include background
#
# In this section we will include a background component. Furthermore, we will also simulate more than one observation and fit each one individuallt in order to get average fit results.

# In[ ]:

bkg_model = PowerLaw(index=2.5,
                     amplitude=1e-11 * u.Unit("cm-2 s-1 TeV-1"),
                     reference=1 * u.TeV)

# In[ ]:
# Fix index
fit.model.gamma.freeze()

# Fit norm in bands
diff_flux = list()
diff_flux_err = list()
e_err_hi = list()
e_err_lo = list()
energy = list()
for ii in range(len(binning) - 1):
    energ = np.sqrt(binning[ii] * binning[ii + 1])
    energy.append(energ)
    e_err_hi.append(binning[ii + 1])
    e_err_lo.append(binning[ii])
    fit.fit_range = binning[[ii, ii + 1]]
    fit.run()
    res = fit.result[0].fit
    diff_flux.append(res.model(energ).to('cm-2 s-1 TeV-1'))
    err = res.model_with_uncertainties(energ.to('keV').value)
    diff_flux_err.append(err.s * u.Unit('cm-2 s-1 keV-1'))

table = Table()
table['e_ref'] = energy
table['e_min'] = e_err_lo
table['e_max'] = e_err_hi
table['dnde'] = diff_flux
table['dnde_err'] = diff_flux_err

points = FluxPoints(table)
result = SpectrumResult(fit=best_fit, points=points)
# Fix index
fit.model.gamma.freeze()

# Fit norm in bands
diff_flux = list()
diff_flux_err = list()
e_err_hi = list()
e_err_lo = list()
energy = list()
for ii in range(len(binning)-1):
    energ= np.sqrt(binning[ii] * binning[ii+1])
    energy.append(energ)
    e_err_hi.append(binning[ii+1] - energ)
    e_err_lo.append(energ - binning[ii])
    fit.fit_range = binning[[ii,ii+1]]
    fit.run()
    res = fit.result[0].fit
    diff_flux.append(res.model(energ).to('cm-2 s-1 TeV-1'))
    err = res.model_with_uncertainties(energ.to('keV').value)
    diff_flux_err.append(err.s * u.Unit('cm-2 s-1 keV-1'))

points = DifferentialFluxPoints.from_arrays(energy=energy, diff_flux=diff_flux,
                                            diff_flux_err_hi=diff_flux_err,
                                            diff_flux_err_lo=diff_flux_err,
                                            energy_err_hi = e_err_hi,
                                            energy_err_lo = e_err_lo)
result = SpectrumResult(fit=best_fit, points=points)
result.plot_spectrum()
plt.savefig('fluxpoints.png')
Beispiel #8
0
    def compute(cls, model, obs_list, binning):
        """Compute differential fluxpoints

        The norm of the global model is fit to the
        `~gammapy.spectrum.SpectrumObservationList` in the provided energy
        binning and the differential flux is evaluated at the log bin center.

        TODO : Add upper limit calculation

        Parameters
        ----------
        model : `~gammapy.spectrum.models.SpectralModel`
            Global model
        obs_list : `~gammapy.spectrum.SpectrumObservationList`
            Observations
        binning : `~astropy.units.Quantity`
            Energy binning, see
            :func:`~gammapy.spectrum.utils.calculate_flux_point_binning` for a
            method to get flux points with a minimum significance.
        """
        from gammapy.spectrum import SpectrumFit

        binning = EnergyBounds(binning)
        low_bins = binning.lower_bounds
        high_bins = binning.upper_bounds

        diff_flux = list()
        diff_flux_err = list()
        e_err_hi = list()
        e_err_lo = list()
        energy = list()

        from ..spectrum import models, powerlaw
        from sherpa.models import PowLaw1D

        if isinstance(model, models.PowerLaw):
            temp = model.to_sherpa()
            temp.gamma.freeze()
            sherpa_models = [temp] * binning.nbins
        else:
            sherpa_models = [None] * binning.nbins

        for low, high, sherpa_model in zip(low_bins, high_bins, sherpa_models):
            log.info('Computing flux points in bin [{}, {}]'.format(low, high))

            # Make PowerLaw approximation for higher order models
            if sherpa_model is None:
                flux_low = model(low)
                flux_high = model(high)
                index = powerlaw.power_law_g_from_points(e1=low,
                                                         e2=high,
                                                         f1=flux_low,
                                                         f2=flux_high)

                log.debug('Approximated power law index: {}'.format(index))
                sherpa_model = PowLaw1D('powlaw1d.default')
                sherpa_model.gamma = index
                sherpa_model.gamma.freeze()
                sherpa_model.ref = model.parameters.reference.to('keV')
                sherpa_model.ampl = 1e-20

            fit = SpectrumFit(obs_list, sherpa_model)

            # If 'low' or 'high' fall onto a bin edge of the
            # SpectrumObservation binning, numerical fluctuations can lead to
            # the inclusion of unwanted bins
            correction = 1e-5
            fit.fit_range = ((1 + correction) * low, (1 - correction) * high)
            fit.fit()
            res = fit.global_result

            bin_center = np.sqrt(low * high)
            energy.append(bin_center)
            e_err_hi.append(high - bin_center)
            e_err_lo.append(bin_center - low)
            diff_flux.append(res.model(bin_center).to('m-2 s-1 TeV-1'))
            err = res.model_with_uncertainties(bin_center.to('TeV').value)
            diff_flux_err.append(err.s * Unit('m-2 s-1 TeV-1'))

        return cls.from_arrays(energy=energy,
                               diff_flux=diff_flux,
                               diff_flux_err_hi=diff_flux_err,
                               diff_flux_err_lo=diff_flux_err,
                               energy_err_hi=e_err_hi,
                               energy_err_lo=e_err_lo)