Example #1
0
    def setup(self):
        self.nbins = 30
        binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV
        self.source_model = PowerLawSpectralModel(index=2,
                                                  amplitude=1e5 / u.TeV,
                                                  reference=0.1 * u.TeV)
        self.bkg_model = PowerLawSpectralModel(index=3,
                                               amplitude=1e4 / u.TeV,
                                               reference=0.1 * u.TeV)

        self.alpha = 0.1
        random_state = get_random_state(23)
        npred = self.source_model.integral(binning[:-1], binning[1:])
        source_counts = random_state.poisson(npred)
        self.src = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=source_counts)
        # Currently it's necessary to specify a lifetime
        self.src.livetime = 1 * u.s

        npred_bkg = self.bkg_model.integral(binning[:-1], binning[1:])

        bkg_counts = random_state.poisson(npred_bkg)
        off_counts = random_state.poisson(npred_bkg * 1.0 / self.alpha)
        self.bkg = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=bkg_counts)
        self.off = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=off_counts)
Example #2
0
    def setup(self):
        self.nbins = 30
        binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV
        self.source_model = PowerLawSpectralModel(index=2,
                                                  amplitude=1e5 *
                                                  u.Unit("cm-2 s-1 TeV-1"),
                                                  reference=0.1 * u.TeV)
        bkg_model = PowerLawSpectralModel(index=3,
                                          amplitude=1e4 *
                                          u.Unit("cm-2 s-1 TeV-1"),
                                          reference=0.1 * u.TeV)

        self.alpha = 0.1
        random_state = get_random_state(23)
        npred = self.source_model.integral(binning[:-1], binning[1:]).value
        source_counts = random_state.poisson(npred)
        self.src = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=source_counts)

        self.src.livetime = 1 * u.s
        self.aeff = EffectiveAreaTable.from_constant(binning, "1 cm2")

        npred_bkg = bkg_model.integral(binning[:-1], binning[1:]).value

        bkg_counts = random_state.poisson(npred_bkg)
        off_counts = random_state.poisson(npred_bkg * 1.0 / self.alpha)
        self.bkg = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=bkg_counts)
        self.off = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=off_counts)
Example #3
0
    def setup(self):
        self.nbins = 30
        binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV

        self.source_model = PowerLawSpectralModel(index=2.1,
                                                  amplitude=1e5 / u.TeV / u.s,
                                                  reference=0.1 * u.TeV)

        self.livetime = 100 * u.s

        bkg_rate = np.ones(self.nbins) / u.s
        bkg_expected = bkg_rate * self.livetime

        self.bkg = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=bkg_expected)

        random_state = get_random_state(23)
        self.npred = (self.source_model.integral(binning[:-1], binning[1:]) *
                      self.livetime)
        self.npred += bkg_expected
        source_counts = random_state.poisson(self.npred)

        self.src = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=source_counts)
        self.dataset = SpectrumDataset(
            model=self.source_model,
            counts=self.src,
            livetime=self.livetime,
            background=self.bkg,
        )
Example #4
0
    def setup(self):
        self.nbins = 30
        binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV

        self.source_model = PowerLawSpectralModel(index=2.1,
                                                  amplitude=1e5 *
                                                  u.Unit("cm-2 s-1 TeV-1"),
                                                  reference=0.1 * u.TeV)

        self.livetime = 100 * u.s
        aeff = EffectiveAreaTable.from_constant(binning, "1 cm2")

        bkg_rate = np.ones(self.nbins) / u.s
        bkg_expected = (bkg_rate * self.livetime).to_value("")

        self.bkg = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=bkg_expected)

        random_state = get_random_state(23)
        flux = self.source_model.integral(binning[:-1], binning[1:])
        self.npred = (flux * aeff.data.data[0] * self.livetime).to_value("")
        self.npred += bkg_expected
        source_counts = random_state.poisson(self.npred)

        self.src = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=source_counts)
        self.dataset = SpectrumDataset(
            model=self.source_model,
            counts=self.src,
            aeff=aeff,
            livetime=self.livetime,
            background=self.bkg,
        )
Example #5
0
    def setup(self):
        etrue = np.logspace(-1, 1, 10) * u.TeV
        self.e_true = etrue
        ereco = np.logspace(-1, 1, 5) * u.TeV
        elo = ereco[:-1]
        ehi = ereco[1:]
        self.e_reco = ereco
        self.aeff = EffectiveAreaTable(etrue[:-1], etrue[1:],
                                       np.ones(9) * u.cm**2)
        self.edisp = EDispKernel.from_diagonal_response(etrue, ereco)

        data = np.ones(elo.shape)
        data[-1] = 0  # to test stats calculation with empty bins
        self.on_counts = CountsSpectrum(elo, ehi, data)
        self.off_counts = CountsSpectrum(elo, ehi, np.ones(elo.shape) * 10)

        start = u.Quantity([0], "s")
        stop = u.Quantity([1000], "s")
        time_ref = Time("2010-01-01 00:00:00.0")
        self.gti = GTI.create(start, stop, time_ref)
        self.livetime = self.gti.time_sum

        self.dataset = SpectrumDatasetOnOff(
            counts=self.on_counts,
            counts_off=self.off_counts,
            aeff=self.aeff,
            edisp=self.edisp,
            livetime=self.livetime,
            acceptance=np.ones(elo.shape),
            acceptance_off=np.ones(elo.shape) * 10,
            name="test",
            gti=self.gti,
        )
Example #6
0
def make_observation_list():
    """obs with dummy IRF"""
    nbin = 3
    energy = np.logspace(-1, 1, nbin + 1) * u.TeV
    livetime = 2 * u.h
    data_on = np.arange(nbin)
    dataoff_1 = np.ones(3)
    dataoff_2 = np.ones(3) * 3
    dataoff_1[1] = 0
    dataoff_2[1] = 0
    on_vector = CountsSpectrum(energy_lo=energy[:-1],
                               energy_hi=energy[1:],
                               data=data_on)
    off_vector1 = CountsSpectrum(energy_lo=energy[:-1],
                                 energy_hi=energy[1:],
                                 data=dataoff_1)
    off_vector2 = CountsSpectrum(energy_lo=energy[:-1],
                                 energy_hi=energy[1:],
                                 data=dataoff_2)
    aeff = EffectiveAreaTable.from_constant(energy, "1 cm2")
    edisp = EDispKernel.from_gauss(e_true=energy,
                                   e_reco=energy,
                                   sigma=0.2,
                                   bias=0)

    time_ref = Time("2010-01-01")
    gti1 = make_gti({
        "START": [5, 6, 1, 2],
        "STOP": [8, 7, 3, 4]
    },
                    time_ref=time_ref)
    gti2 = make_gti({"START": [14], "STOP": [15]}, time_ref=time_ref)

    obs1 = SpectrumDatasetOnOff(
        counts=on_vector,
        counts_off=off_vector1,
        aeff=aeff,
        edisp=edisp,
        livetime=livetime,
        mask_safe=np.ones(on_vector.energy.nbin, dtype=bool),
        acceptance=1,
        acceptance_off=2,
        name="1",
        gti=gti1,
    )
    obs2 = SpectrumDatasetOnOff(
        counts=on_vector,
        counts_off=off_vector2,
        aeff=aeff,
        edisp=edisp,
        livetime=livetime,
        mask_safe=np.ones(on_vector.energy.nbin, dtype=bool),
        acceptance=1,
        acceptance_off=4,
        name="2",
        gti=gti2,
    )

    obs_list = [obs1, obs2]
    return obs_list
Example #7
0
    def setup(self):
        etrue = np.logspace(-1, 1, 10) * u.TeV
        self.e_true = etrue
        ereco = np.logspace(-1, 1, 5) * u.TeV
        elo = ereco[:-1]
        ehi = ereco[1:]

        self.aeff = EffectiveAreaTable(etrue[:-1], etrue[1:],
                                       np.ones(9) * u.cm**2)
        self.edisp = EnergyDispersion.from_diagonal_response(etrue, ereco)

        data = np.ones(elo.shape)
        data[-1] = 0  # to test stats calculation with empty bins
        self.on_counts = CountsSpectrum(elo, ehi, data)
        self.off_counts = CountsSpectrum(elo, ehi, np.ones(elo.shape) * 10)

        self.livetime = 1000 * u.s

        self.dataset = SpectrumDatasetOnOff(
            counts=self.on_counts,
            counts_off=self.off_counts,
            aeff=self.aeff,
            edisp=self.edisp,
            livetime=self.livetime,
            acceptance=np.ones(elo.shape),
            acceptance_off=np.ones(elo.shape) * 10,
            obs_id="test",
        )
Example #8
0
    def _counts_spectrum(self, ebounds):
        from gammapy.spectrum import CountsSpectrum

        if not ebounds:
            ebounds = self._default_plot_ebounds()
        spec = CountsSpectrum(energy_lo=ebounds[:-1], energy_hi=ebounds[1:])
        spec.fill_energy(self.energy)
        return spec
Example #9
0
    def get_spectrum(self, region=None, func=np.nansum):
        """Extract spectrum in a given region.

        The spectrum can be computed by summing (or, more generally, applying ``func``)
        along the spatial axes in each energy bin. This occurs only inside the ``region``,
        which by default is assumed to be the whole spatial extension of the map.

        Parameters
        ----------
        region: `~regions.Region`
             Region (pixel or sky regions accepted).
        func : numpy.ufunc
            Function to reduce the data.

        Returns
        -------
        spectrum : `~gammapy.spectrum.CountsSpectrum`
            Spectrum in the given region.
        """
        from gammapy.spectrum import CountsSpectrum

        energy_axis = self.geom.get_axis_by_name("energy")

        if region:
            mask = self.geom.region_mask([region])
            data = self.data[mask].reshape(energy_axis.nbin, -1)
            data = func(data, axis=1)
        else:
            data = func(self.data, axis=(1, 2))

        edges = energy_axis.edges
        return CountsSpectrum(data=data,
                              energy_lo=edges[:-1],
                              energy_hi=edges[1:],
                              unit=self.unit)
Example #10
0
    def test_fake(self):
        """Test the fake dataset"""
        source_model = SkyModel(spectral_model=PowerLawSpectralModel())
        dataset = SpectrumDatasetOnOff(
            counts=self.on_counts,
            counts_off=self.off_counts,
            models=source_model,
            aeff=self.aeff,
            livetime=self.livetime,
            edisp=self.edisp,
            acceptance=1,
            acceptance_off=10,
        )
        real_dataset = dataset.copy()
        # Define background model counts
        elo = self.on_counts.energy.edges[:-1]
        ehi = self.on_counts.energy.edges[1:]
        data = np.ones(self.on_counts.data.shape)
        background_model = CountsSpectrum(elo, ehi, data)
        dataset.fake(background_model=background_model,
                     random_state=314,
                     name="fake")

        assert real_dataset.counts.data.shape == dataset.counts.data.shape
        assert real_dataset.counts_off.data.shape == dataset.counts_off.data.shape
        assert (real_dataset.counts.energy.center.mean() ==
                dataset.counts.energy.center.mean())
        assert real_dataset.acceptance.mean() == dataset.acceptance.mean()
        assert real_dataset.acceptance_off.mean(
        ) == dataset.acceptance_off.mean()
        assert dataset.counts_off.data.sum() == 39
        assert dataset.counts.data.sum() == 5
        assert dataset.name == "fake"
Example #11
0
def sens():
    etrue = np.logspace(0, 1, 21) * u.TeV
    elo = etrue[:-1]
    ehi = etrue[1:]
    area = np.zeros(20) + 1e6 * u.m**2

    arf = EffectiveAreaTable(energy_lo=elo, energy_hi=ehi, data=area)

    ereco = np.logspace(0, 1, 5) * u.TeV
    rmf = EnergyDispersion.from_diagonal_response(etrue, ereco)

    bkg_array = np.ones(4)
    bkg_array[-1] = 1e-3
    bkg = CountsSpectrum(energy_lo=ereco[:-1],
                         energy_hi=ereco[1:],
                         data=bkg_array,
                         unit="s-1")

    sens = SensitivityEstimator(arf=arf,
                                rmf=rmf,
                                bkg=bkg,
                                livetime=1 * u.h,
                                index=2,
                                gamma_min=20,
                                alpha=0.2)
    sens.run()
    return sens
Example #12
0
class TestSimpleFit:
    """Test fit on counts spectra without any IRFs"""
    def setup(self):
        self.nbins = 30
        binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV
        self.source_model = PowerLawSpectralModel(index=2,
                                                  amplitude=1e5 / u.TeV,
                                                  reference=0.1 * u.TeV)
        self.bkg_model = PowerLawSpectralModel(index=3,
                                               amplitude=1e4 / u.TeV,
                                               reference=0.1 * u.TeV)

        self.alpha = 0.1
        random_state = get_random_state(23)
        npred = self.source_model.integral(binning[:-1], binning[1:])
        source_counts = random_state.poisson(npred)
        self.src = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=source_counts)
        # Currently it's necessary to specify a lifetime
        self.src.livetime = 1 * u.s

        npred_bkg = self.bkg_model.integral(binning[:-1], binning[1:])

        bkg_counts = random_state.poisson(npred_bkg)
        off_counts = random_state.poisson(npred_bkg * 1.0 / self.alpha)
        self.bkg = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=bkg_counts)
        self.off = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=off_counts)

    def test_wstat(self):
        """WStat with on source and background spectrum"""
        on_vector = self.src.copy()
        on_vector.data += self.bkg.data
        obs = SpectrumDatasetOnOff(
            counts=on_vector,
            counts_off=self.off,
            acceptance=1,
            acceptance_off=1 / self.alpha,
        )
        obs.model = self.source_model

        self.source_model.parameters.index = 1.12

        fit = Fit(obs)
        result = fit.run()
        pars = self.source_model.parameters

        assert_allclose(pars["index"].value, 1.997342, rtol=1e-3)
        assert_allclose(pars["amplitude"].value, 100245.187067, rtol=1e-3)
        assert_allclose(result.total_stat, 30.022316, rtol=1e-3)
Example #13
0
class TestCountsSpectrum:
    def setup(self):
        self.counts = [0, 0, 2, 5, 17, 3]
        self.bins = energy_logspace(1, 10, 7, "TeV")
        self.spec = CountsSpectrum(data=self.counts,
                                   energy_lo=self.bins[:-1],
                                   energy_hi=self.bins[1:])

    def test_wrong_init(self):
        bins = energy_logspace(1, 10, 8, "TeV")
        with pytest.raises(ValueError):
            CountsSpectrum(data=self.counts,
                           energy_lo=bins[:-1],
                           energy_hi=bins[1:])

    @requires_dependency("matplotlib")
    def test_plot(self):
        with mpl_plot_check():
            self.spec.plot(show_energy=1 * u.TeV)

        with mpl_plot_check():
            self.spec.plot_hist()

        with mpl_plot_check():
            self.spec.peek()

    def test_io(self, tmpdir):
        filename = tmpdir / "test.fits"
        self.spec.write(filename)
        spec2 = CountsSpectrum.read(filename)
        assert_quantity_allclose(spec2.energy.edges, self.bins)

    def test_downsample(self):
        rebinned_spec = self.spec.downsample(2)
        assert rebinned_spec.energy.nbin == self.spec.energy.nbin / 2
        assert rebinned_spec.data.shape[0] == self.spec.data.shape[0] / 2
        assert rebinned_spec.total_counts == self.spec.total_counts

        idx = rebinned_spec.energy.coord_to_idx([2, 3, 5] * u.TeV)
        actual = rebinned_spec.data[idx]
        desired = [0, 7, 20]
        assert (actual == desired).all()
Example #14
0
def spectrum_dataset():
    e_true = np.logspace(0, 1, 21) * u.TeV
    e_reco = np.logspace(0, 1, 5) * u.TeV
    aeff = EffectiveAreaTable.from_constant(value=1e6 * u.m**2, energy=e_true)
    edisp = EDispKernel.from_diagonal_response(e_true, e_reco)

    data = 3600 * np.ones(4)
    data[-1] *= 1e-3
    background = CountsSpectrum(energy_lo=e_reco[:-1],
                                energy_hi=e_reco[1:],
                                data=data)
    return SpectrumDataset(aeff=aeff,
                           livetime="1h",
                           edisp=edisp,
                           background=background)
Example #15
0
    def test_spectrum_dataset_stack_diagonal_safe_mask(self):
        aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges,
                                                       "HESS")
        edisp = EDispKernel.from_diagonal_response(self.src.energy.edges,
                                                   self.src.energy.edges)
        livetime = self.livetime
        dataset1 = SpectrumDataset(
            counts=self.src.copy(),
            livetime=livetime,
            aeff=aeff,
            edisp=edisp,
            background=self.bkg.copy(),
        )

        livetime2 = 0.5 * livetime
        aeff2 = EffectiveAreaTable(self.src.energy.edges[:-1],
                                   self.src.energy.edges[1:],
                                   2 * aeff.data.data)
        bkg2 = CountsSpectrum(
            self.src.energy.edges[:-1],
            self.src.energy.edges[1:],
            data=2 * self.bkg.data,
        )
        safe_mask2 = np.ones_like(self.src.data, bool)
        safe_mask2[0] = False
        dataset2 = SpectrumDataset(
            counts=self.src.copy(),
            livetime=livetime2,
            aeff=aeff2,
            edisp=edisp,
            background=bkg2,
            mask_safe=safe_mask2,
        )
        dataset1.stack(dataset2)

        assert_allclose(dataset1.counts.data[1:], self.src.data[1:] * 2)
        assert_allclose(dataset1.counts.data[0], self.src.data[0])
        assert dataset1.livetime == 1.5 * self.livetime
        assert_allclose(dataset1.background.data[1:], 3 * self.bkg.data[1:])
        assert_allclose(dataset1.background.data[0], self.bkg.data[0])
        assert_allclose(
            dataset1.aeff.data.data.to_value("m2"),
            4.0 / 3 * aeff.data.data.to_value("m2"),
        )
        assert_allclose(dataset1.edisp.pdf_matrix[1:], edisp.pdf_matrix[1:])
        assert_allclose(dataset1.edisp.pdf_matrix[0],
                        0.5 * edisp.pdf_matrix[0])
Example #16
0
    def plot_energy_hist(self, ax=None, ebounds=None, **kwargs):
        """
        A plot showing counts as a function of energy.

        Convert to a `~gammapy.spectrum.CountsSpectrum` internally
        """

        if ebounds is None:
            emin = np.min(self['ENERGY'].quantity)
            emax = np.max(self['ENERGY'].quantity)
            ebounds = EnergyBounds.equal_log_spacing(emin, emax, 100)

        from gammapy.spectrum import CountsSpectrum
        spec = CountsSpectrum.from_eventlist(self, ebounds)
        spec.plot(ax=ax, **kwargs)

        return ax
Example #17
0
    def plot_energy_hist(self, ax=None, ebounds=None, **kwargs):
        """
        A plot showing counts as a function of energy.

        Convert to a `~gammapy.spectrum.CountsSpectrum` internally
        """

        if ebounds is None:
            emin = np.min(self['ENERGY'].quantity)
            emax = np.max(self['ENERGY'].quantity)
            ebounds = EnergyBounds.equal_log_spacing(emin, emax, 100)

        from gammapy.spectrum import CountsSpectrum
        spec = CountsSpectrum.from_eventlist(self, ebounds)
        spec.plot(ax=ax, **kwargs)

        return ax
Example #18
0
 def setup(self):
     self.counts = [0, 0, 2, 5, 17, 3]
     self.bins = energy_logspace(1, 10, 7, "TeV")
     self.spec = CountsSpectrum(
         data=self.counts, energy_lo=self.bins[:-1], energy_hi=self.bins[1:]
     )
Example #19
0
 def test_io(self, tmpdir):
     filename = tmpdir / "test.fits"
     self.spec.write(filename)
     spec2 = CountsSpectrum.read(filename)
     assert_quantity_allclose(spec2.energy.edges, self.bins)
Example #20
0
class TestSpectrumDataset:
    """Test fit on counts spectra without any IRFs"""
    def setup(self):
        self.nbins = 30
        binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV

        self.source_model = SkyModel(spectral_model=PowerLawSpectralModel(
            index=2.1,
            amplitude=1e5 * u.Unit("cm-2 s-1 TeV-1"),
            reference=0.1 * u.TeV,
        ))

        self.livetime = 100 * u.s
        aeff = EffectiveAreaTable.from_constant(binning, "1 cm2")

        bkg_rate = np.ones(self.nbins) / u.s
        bkg_expected = (bkg_rate * self.livetime).to_value("")

        self.bkg = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=bkg_expected)

        random_state = get_random_state(23)
        flux = self.source_model.spectral_model.integral(
            binning[:-1], binning[1:])
        self.npred = (flux * aeff.data.data[0] * self.livetime).to_value("")
        self.npred += bkg_expected
        source_counts = random_state.poisson(self.npred)

        self.src = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=source_counts)
        self.dataset = SpectrumDataset(
            models=self.source_model,
            counts=self.src,
            aeff=aeff,
            livetime=self.livetime,
            background=self.bkg,
            name="test",
        )

    def test_data_shape(self):
        assert self.dataset.data_shape[0] == self.nbins

    def test_energy_range(self):
        energy_range = self.dataset.energy_range
        assert energy_range.unit == u.TeV
        assert_allclose(energy_range.to_value("TeV"), [0.1, 10.0])

    def test_cash(self):
        """Simple CASH fit to the on vector"""
        fit = Fit([self.dataset])
        result = fit.run()

        # assert result.success
        assert "minuit" in repr(result)

        npred = self.dataset.npred().data.sum()
        assert_allclose(npred, self.npred.sum(), rtol=1e-3)
        assert_allclose(result.total_stat, -18087404.624, rtol=1e-3)

        pars = result.parameters
        assert_allclose(pars["index"].value, 2.1, rtol=1e-2)
        assert_allclose(pars.error("index"), 0.00127, rtol=1e-2)

        assert_allclose(pars["amplitude"].value, 1e5, rtol=1e-3)
        assert_allclose(pars.error("amplitude"), 153.450, rtol=1e-2)

    def test_fake(self):
        """Test the fake dataset"""
        real_dataset = self.dataset.copy()
        self.dataset.fake(314)
        assert real_dataset.counts.data.shape == self.dataset.counts.data.shape
        assert real_dataset.background.data.sum(
        ) == self.dataset.background.data.sum()
        assert int(real_dataset.counts.data.sum()) == 907010
        assert self.dataset.counts.data.sum() == 907331

    def test_incorrect_mask(self):
        mask_fit = np.ones(self.nbins, dtype=np.dtype("float"))
        with pytest.raises(ValueError):
            SpectrumDataset(
                models=self.source_model,
                counts=self.src,
                livetime=self.livetime,
                mask_fit=mask_fit,
                background=self.bkg,
            )

    def test_set_model(self):
        aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges,
                                                       "HESS")
        edisp = EDispKernel.from_diagonal_response(self.src.energy.edges,
                                                   self.src.energy.edges)
        dataset = SpectrumDataset(None, self.src, self.livetime, None, aeff,
                                  edisp, self.bkg)

        spectral_model = PowerLawSpectralModel()
        model = SkyModel(spectral_model=spectral_model, name="test")
        dataset.models = model
        assert dataset.models["test"] is model

        models = Models([model])
        dataset.models = models
        assert dataset.models["test"] is model

    def test_npred_models(self):
        e_reco = MapAxis.from_energy_bounds("1 TeV", "10 TeV", nbin=3).edges
        dataset = SpectrumDataset.create(e_reco=e_reco)
        dataset.livetime = 1 * u.h
        dataset.aeff.data.data += 1e10 * u.Unit("cm2")

        pwl_1 = PowerLawSpectralModel(index=2)
        pwl_2 = PowerLawSpectralModel(index=2)
        model_1 = SkyModel(spectral_model=pwl_1)
        model_2 = SkyModel(spectral_model=pwl_2)

        dataset.models = Models([model_1, model_2])

        npred = dataset.npred()

        assert_allclose(npred.data.sum(), 64.8)

    def test_str(self):
        assert "SpectrumDataset" in str(self.dataset)

    def test_spectrumdataset_create(self):
        e_reco = u.Quantity([0.1, 1, 10.0], "TeV")
        e_true = u.Quantity([0.05, 0.5, 5, 20.0], "TeV")
        empty_dataset = SpectrumDataset.create(e_reco, e_true, name="test")

        assert empty_dataset.name == "test"
        assert empty_dataset.counts.total_counts == 0
        assert empty_dataset.data_shape[0] == 2
        assert empty_dataset.background.total_counts == 0
        assert empty_dataset.background.energy.nbin == 2
        assert empty_dataset.aeff.data.axis("energy").nbin == 3
        assert empty_dataset.edisp.data.axis("e_reco").nbin == 2
        assert empty_dataset.livetime.value == 0
        assert len(empty_dataset.gti.table) == 0
        assert empty_dataset.energy_range[0] is None
        assert_allclose(empty_dataset.mask_safe, 0)

    def test_spectrum_dataset_stack_diagonal_safe_mask(self):
        aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges,
                                                       "HESS")
        edisp = EDispKernel.from_diagonal_response(self.src.energy.edges,
                                                   self.src.energy.edges)
        livetime = self.livetime
        dataset1 = SpectrumDataset(
            counts=self.src.copy(),
            livetime=livetime,
            aeff=aeff,
            edisp=edisp,
            background=self.bkg.copy(),
        )

        livetime2 = 0.5 * livetime
        aeff2 = EffectiveAreaTable(self.src.energy.edges[:-1],
                                   self.src.energy.edges[1:],
                                   2 * aeff.data.data)
        bkg2 = CountsSpectrum(
            self.src.energy.edges[:-1],
            self.src.energy.edges[1:],
            data=2 * self.bkg.data,
        )
        safe_mask2 = np.ones_like(self.src.data, bool)
        safe_mask2[0] = False
        dataset2 = SpectrumDataset(
            counts=self.src.copy(),
            livetime=livetime2,
            aeff=aeff2,
            edisp=edisp,
            background=bkg2,
            mask_safe=safe_mask2,
        )
        dataset1.stack(dataset2)

        assert_allclose(dataset1.counts.data[1:], self.src.data[1:] * 2)
        assert_allclose(dataset1.counts.data[0], self.src.data[0])
        assert dataset1.livetime == 1.5 * self.livetime
        assert_allclose(dataset1.background.data[1:], 3 * self.bkg.data[1:])
        assert_allclose(dataset1.background.data[0], self.bkg.data[0])
        assert_allclose(
            dataset1.aeff.data.data.to_value("m2"),
            4.0 / 3 * aeff.data.data.to_value("m2"),
        )
        assert_allclose(dataset1.edisp.pdf_matrix[1:], edisp.pdf_matrix[1:])
        assert_allclose(dataset1.edisp.pdf_matrix[0],
                        0.5 * edisp.pdf_matrix[0])

    def test_spectrum_dataset_stack_nondiagonal_no_bkg(self):
        aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges,
                                                       "HESS")
        edisp1 = EDispKernel.from_gauss(self.src.energy.edges,
                                        self.src.energy.edges, 0.1, 0.0)
        livetime = self.livetime
        dataset1 = SpectrumDataset(counts=None,
                                   livetime=livetime,
                                   aeff=aeff,
                                   edisp=edisp1,
                                   background=None)

        livetime2 = livetime
        aeff2 = EffectiveAreaTable(self.src.energy.edges[:-1],
                                   self.src.energy.edges[1:], aeff.data.data)
        edisp2 = EDispKernel.from_gauss(self.src.energy.edges,
                                        self.src.energy.edges, 0.2, 0.0)
        dataset2 = SpectrumDataset(
            counts=self.src.copy(),
            livetime=livetime2,
            aeff=aeff2,
            edisp=edisp2,
            background=None,
        )
        dataset1.stack(dataset2)

        assert dataset1.counts is None
        assert dataset1.background is None
        assert dataset1.livetime == 2 * self.livetime
        assert_allclose(dataset1.aeff.data.data.to_value("m2"),
                        aeff.data.data.to_value("m2"))
        assert_allclose(dataset1.edisp.get_bias(1 * u.TeV), 0.0, atol=1.2e-3)
        assert_allclose(dataset1.edisp.get_resolution(1 * u.TeV),
                        0.1581,
                        atol=1e-2)

    def test_info_dict(self):
        info_dict = self.dataset.info_dict()

        assert_allclose(info_dict["n_on"], 907010)
        assert_allclose(info_dict["background"], 3000.0)

        assert_allclose(info_dict["significance"], 2924.522174)
        assert_allclose(info_dict["excess"], 904010)
        assert_allclose(info_dict["livetime"].value, 1e2)

        assert info_dict["name"] == "test"

    @requires_dependency("matplotlib")
    def test_peek(self):
        with mpl_plot_check():
            self.dataset.peek()
        self.dataset.edisp = None
        with mpl_plot_check():
            self.dataset.peek()

    @requires_dependency("matplotlib")
    def test_plot_fit(self):
        with mpl_plot_check():
            self.dataset.plot_fit()
Example #21
0
class TestSpectrumDataset:
    """Test fit on counts spectra without any IRFs"""
    def setup(self):
        self.nbins = 30
        binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV

        self.source_model = PowerLawSpectralModel(index=2.1,
                                                  amplitude=1e5 / u.TeV / u.s,
                                                  reference=0.1 * u.TeV)

        self.livetime = 100 * u.s

        bkg_rate = np.ones(self.nbins) / u.s
        bkg_expected = bkg_rate * self.livetime

        self.bkg = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=bkg_expected)

        random_state = get_random_state(23)
        self.npred = (self.source_model.integral(binning[:-1], binning[1:]) *
                      self.livetime)
        self.npred += bkg_expected
        source_counts = random_state.poisson(self.npred)

        self.src = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=source_counts)
        self.dataset = SpectrumDataset(
            model=self.source_model,
            counts=self.src,
            livetime=self.livetime,
            background=self.bkg,
        )

    def test_data_shape(self):
        assert self.dataset.data_shape[0] == self.nbins

    def test_energy_range(self):
        energy_range = self.dataset.energy_range
        assert energy_range.unit == u.TeV
        assert_allclose(energy_range.to_value("TeV"), [0.1, 10.0])

    def test_cash(self):
        """Simple CASH fit to the on vector"""
        fit = Fit(self.dataset)
        result = fit.run()

        assert result.success
        assert "minuit" in repr(result)

        npred = self.dataset.npred().data.sum()
        assert_allclose(npred, self.npred.sum(), rtol=1e-3)
        assert_allclose(result.total_stat, -18087404.624, rtol=1e-3)

        pars = result.parameters
        assert_allclose(pars["index"].value, 2.1, rtol=1e-2)
        assert_allclose(pars.error("index"), 0.00127, rtol=1e-2)

        assert_allclose(pars["amplitude"].value, 1e5, rtol=1e-3)
        assert_allclose(pars.error("amplitude"), 153.450, rtol=1e-2)

    def test_fake(self):
        """Test the fake dataset"""
        real_dataset = self.dataset.copy()
        self.dataset.fake(314)
        assert real_dataset.counts.data.shape == self.dataset.counts.data.shape
        assert real_dataset.background.data.sum(
        ) == self.dataset.background.data.sum()
        assert int(real_dataset.counts.data.sum()) == 907010
        assert self.dataset.counts.data.sum() == 907331

    def test_incorrect_mask(self):
        mask_fit = np.ones(self.nbins, dtype=np.dtype("float"))
        with pytest.raises(ValueError):
            SpectrumDataset(
                model=self.source_model,
                counts=self.src,
                livetime=self.livetime,
                mask_fit=mask_fit,
                background=self.bkg,
            )

    def test_set_model(self):
        aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges,
                                                       "HESS")
        edisp = EnergyDispersion.from_diagonal_response(
            self.src.energy.edges, self.src.energy.edges)
        dataset = SpectrumDataset(None, self.src, self.livetime, None, aeff,
                                  edisp, self.bkg)
        with pytest.raises(AttributeError):
            dataset.parameters

        dataset.model = self.source_model
        assert dataset.parameters[0] == self.source_model.parameters[0]

    def test_str(self):
        assert "SpectrumDataset" in str(self.dataset)

    def test_spectrumdataset_create(self):
        e_reco = u.Quantity([0.1, 1, 10.0], "TeV")
        e_true = u.Quantity([0.05, 0.5, 5, 20.0], "TeV")
        empty_dataset = SpectrumDataset.create(e_reco, e_true)

        assert empty_dataset.counts.total_counts == 0
        assert empty_dataset.data_shape[0] == 2
        assert empty_dataset.background.total_counts == 0
        assert empty_dataset.background.energy.nbin == 2
        assert empty_dataset.aeff.data.axis("energy").nbin == 3
        assert empty_dataset.edisp.data.axis("e_reco").nbin == 2
        assert empty_dataset.livetime.value == 0
        assert len(empty_dataset.gti.table) == 0
        assert empty_dataset.energy_range[0] is None
        assert_allclose(empty_dataset.mask_safe, 0)

    def test_spectrum_dataset_stack_diagonal_safe_mask(self):
        aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges,
                                                       "HESS")
        edisp = EnergyDispersion.from_diagonal_response(
            self.src.energy.edges, self.src.energy.edges)
        livetime = self.livetime
        dataset1 = SpectrumDataset(
            counts=self.src.copy(),
            livetime=livetime,
            aeff=aeff,
            edisp=edisp,
            background=self.bkg.copy(),
        )

        livetime2 = 0.5 * livetime
        aeff2 = EffectiveAreaTable(self.src.energy.edges[:-1],
                                   self.src.energy.edges[1:],
                                   2 * aeff.data.data)
        bkg2 = CountsSpectrum(
            self.src.energy.edges[:-1],
            self.src.energy.edges[1:],
            data=2 * self.bkg.data,
        )
        safe_mask2 = np.ones_like(self.src.data, bool)
        safe_mask2[0] = False
        dataset2 = SpectrumDataset(
            counts=self.src.copy(),
            livetime=livetime2,
            aeff=aeff2,
            edisp=edisp,
            background=bkg2,
            mask_safe=safe_mask2,
        )
        dataset1.stack(dataset2)

        assert_allclose(dataset1.counts.data[1:], self.src.data[1:] * 2)
        assert_allclose(dataset1.counts.data[0], self.src.data[0])
        assert dataset1.livetime == 1.5 * self.livetime
        assert_allclose(dataset1.background.data[1:], 3 * self.bkg.data[1:])
        assert_allclose(dataset1.background.data[0], self.bkg.data[0])
        assert_allclose(
            dataset1.aeff.data.data.to_value("m2"),
            4.0 / 3 * aeff.data.data.to_value("m2"),
        )
        assert_allclose(dataset1.edisp.pdf_matrix[1:], edisp.pdf_matrix[1:])
        assert_allclose(dataset1.edisp.pdf_matrix[0],
                        0.5 * edisp.pdf_matrix[0])

    def test_spectrum_dataset_stack_nondiagonal_no_bkg(self):
        aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges,
                                                       "HESS")
        edisp1 = EnergyDispersion.from_gauss(self.src.energy.edges,
                                             self.src.energy.edges, 0.1, 0.0)
        livetime = self.livetime
        dataset1 = SpectrumDataset(counts=None,
                                   livetime=livetime,
                                   aeff=aeff,
                                   edisp=edisp1,
                                   background=None)

        livetime2 = livetime
        aeff2 = EffectiveAreaTable(self.src.energy.edges[:-1],
                                   self.src.energy.edges[1:], aeff.data.data)
        edisp2 = EnergyDispersion.from_gauss(self.src.energy.edges,
                                             self.src.energy.edges, 0.2, 0.0)
        dataset2 = SpectrumDataset(
            counts=self.src.copy(),
            livetime=livetime2,
            aeff=aeff2,
            edisp=edisp2,
            background=None,
        )
        dataset1.stack(dataset2)

        assert dataset1.counts is None
        assert dataset1.background is None
        assert dataset1.livetime == 2 * self.livetime
        assert_allclose(dataset1.aeff.data.data.to_value("m2"),
                        aeff.data.data.to_value("m2"))
        assert_allclose(dataset1.edisp.get_bias(1 * u.TeV), 0.0, atol=1e-3)
        assert_allclose(dataset1.edisp.get_resolution(1 * u.TeV),
                        0.1581,
                        atol=1e-2)
Example #22
0
 def test_wrong_init(self):
     bins = MapAxis.from_energy_bounds(1, 10, 8, "TeV").edges
     with pytest.raises(ValueError):
         CountsSpectrum(data=self.counts,
                        energy_lo=bins[:-1],
                        energy_hi=bins[1:])
Example #23
0
 def setup(self):
     self.counts = [0, 0, 2, 5, 17, 3]
     self.bins = MapAxis.from_energy_bounds(1, 10, 6, "TeV").edges
     self.spec = CountsSpectrum(data=self.counts,
                                energy_lo=self.bins[:-1],
                                energy_hi=self.bins[1:])
Example #24
0
# In[ ]:

arf.data.data *= containment

# ## Estimate background
#
# We now provide a workaround to estimate the background from the tabulated IRF in the energy bins we consider.

# In[ ]:

bkg_data = irfs["bkg"].evaluate_integrate(fov_lon=0 * u.deg,
                                          fov_lat=offset,
                                          energy_reco=energy_reco)
bkg = CountsSpectrum(energy_reco[:-1],
                     energy_reco[1:],
                     data=(bkg_data * solid_angles))

# ## Compute sensitivity
#
# We impose a minimal number of expected signal counts of 5 per bin and a minimal significance of 3 per bin. We assume an alpha of 0.2 (ratio between ON and OFF area).
# We then run the sensitivity estimator.

# In[ ]:

sensitivity_estimator = SensitivityEstimator(arf=arf,
                                             rmf=rmf,
                                             bkg=bkg,
                                             livetime="5h",
                                             gamma_min=5,
                                             sigma=3,
# In[ ]:

arf.data.data *= containment

# ## Estimate background
#
# We now provide a workaround to estimate the background from the tabulated IRF in the energy bins we consider.

# In[ ]:

bkg_data = irfs["bkg"].evaluate_integrate(fov_lon=0 * u.deg,
                                          fov_lat=offset,
                                          energy_reco=energy_reco)
bkg = CountsSpectrum(
    energy_reco[:-1],
    energy_reco[1:],
    data=(bkg_data * solid_angles).to_value("s-1"),
    unit="s-1",
)

# ## Compute sensitivity
#
# We impose a minimal number of expected signal counts of 5 per bin and a minimal significance of 3 per bin. We assume an alpha of 0.2 (ratio between ON and OFF area).
# We then run the sensitivity estimator.

# In[ ]:

sensitivity_estimator = SensitivityEstimator(arf=arf,
                                             rmf=rmf,
                                             bkg=bkg,
                                             livetime="5h",
                                             gamma_min=5,
Example #26
0
class TestFit:
    """Test fit on counts spectra without any IRFs"""
    def setup(self):
        self.nbins = 30
        binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV
        self.source_model = PowerLawSpectralModel(index=2,
                                                  amplitude=1e5 *
                                                  u.Unit("cm-2 s-1 TeV-1"),
                                                  reference=0.1 * u.TeV)
        bkg_model = PowerLawSpectralModel(index=3,
                                          amplitude=1e4 *
                                          u.Unit("cm-2 s-1 TeV-1"),
                                          reference=0.1 * u.TeV)

        self.alpha = 0.1
        random_state = get_random_state(23)
        npred = self.source_model.integral(binning[:-1], binning[1:]).value
        source_counts = random_state.poisson(npred)
        self.src = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=source_counts)

        self.src.livetime = 1 * u.s
        self.aeff = EffectiveAreaTable.from_constant(binning, "1 cm2")

        npred_bkg = bkg_model.integral(binning[:-1], binning[1:]).value

        bkg_counts = random_state.poisson(npred_bkg)
        off_counts = random_state.poisson(npred_bkg * 1.0 / self.alpha)
        self.bkg = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=bkg_counts)
        self.off = CountsSpectrum(energy_lo=binning[:-1],
                                  energy_hi=binning[1:],
                                  data=off_counts)

    def test_cash(self):
        """Simple CASH fit to the on vector"""
        dataset = SpectrumDataset(
            model=self.source_model,
            counts=self.src,
            aeff=self.aeff,
            livetime=self.src.livetime,
        )

        npred = dataset.npred().data
        assert_allclose(npred[5], 660.5171, rtol=1e-5)

        stat_val = dataset.likelihood()
        assert_allclose(stat_val, -107346.5291, rtol=1e-5)

        self.source_model.parameters["index"].value = 1.12

        fit = Fit([dataset])
        result = fit.run()

        # These values are check with sherpa fits, do not change
        pars = result.parameters
        assert_allclose(pars["index"].value, 1.995525, rtol=1e-3)
        assert_allclose(pars["amplitude"].value, 100245.9, rtol=1e-3)

    def test_wstat(self):
        """WStat with on source and background spectrum"""
        on_vector = self.src.copy()
        on_vector.data += self.bkg.data
        dataset = SpectrumDatasetOnOff(
            counts=on_vector,
            counts_off=self.off,
            aeff=self.aeff,
            livetime=self.src.livetime,
            acceptance=1,
            acceptance_off=1 / self.alpha,
        )
        dataset.model = self.source_model

        self.source_model.parameters.index = 1.12

        fit = Fit([dataset])
        result = fit.run()
        pars = self.source_model.parameters

        assert_allclose(pars["index"].value, 1.997342, rtol=1e-3)
        assert_allclose(pars["amplitude"].value, 100245.187067, rtol=1e-3)
        assert_allclose(result.total_stat, 30.022316, rtol=1e-3)

    def test_fit_range(self):
        """Test fit range without complication of thresholds"""
        dataset = SpectrumDatasetOnOff(counts=self.src,
                                       mask_safe=np.ones(self.src.energy.nbin,
                                                         dtype=bool))
        dataset.model = self.source_model

        assert np.sum(dataset.mask_safe) == self.nbins
        e_min, e_max = dataset.energy_range

        assert_allclose(e_max.value, 10)
        assert_allclose(e_min.value, 0.1)

    def test_likelihood_profile(self):
        dataset = SpectrumDataset(
            model=self.source_model,
            aeff=self.aeff,
            livetime=self.src.livetime,
            counts=self.src,
            mask_safe=np.ones(self.src.energy.nbin, dtype=bool),
        )
        fit = Fit([dataset])
        result = fit.run()
        true_idx = result.parameters["index"].value
        values = np.linspace(0.95 * true_idx, 1.05 * true_idx, 100)
        profile = fit.likelihood_profile("index", values=values)
        actual = values[np.argmin(profile["likelihood"])]
        assert_allclose(actual, true_idx, rtol=0.01)
Example #27
0
 def test_wrong_init(self):
     bins = energy_logspace(1, 10, 8, "TeV")
     with pytest.raises(ValueError):
         CountsSpectrum(data=self.counts, energy_lo=bins[:-1], energy_hi=bins[1:])
Example #28
0
 def test_io(self, tmp_path):
     self.spec.write(tmp_path / "tmp.fits")
     spec2 = CountsSpectrum.read(tmp_path / "tmp.fits")
     assert_quantity_allclose(spec2.energy.edges, self.bins)
# 
# In this section we will include a background component extracted from the IRF. Furthermore, we will also simulate more than one observation and fit each one individually in order to get average fit results.

# In[ ]:


# We assume a PowerLawSpectralModel shape of the background as well
bkg_data = (
    cta_irf["bkg"].evaluate_integrate(
        fov_lon=0 * u.deg, fov_lat=offset, energy_reco=energy
    )
    * solid_angle
    * livetime
)
bkg = CountsSpectrum(
    energy[:-1], energy[1:], data=bkg_data.to_value(""), unit=""
)


# In[ ]:


dataset = SpectrumDatasetOnOff(
    aeff=aeff,
    edisp=edisp,
    model=model_ref,
    livetime=livetime,
    acceptance=1,
    acceptance_off=5,
)