Beispiel #1
0
    def test_cash(self):
        """Simple CASH fit to the on vector"""
        dataset = SpectrumDataset(model=self.source_model, counts=self.src)

        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)
Beispiel #2
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()
Beispiel #3
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)
Beispiel #4
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 = PowerLaw(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)