Ejemplo n.º 1
0
    def make_aeff(self, observation):
        """Make effective area

        Parameters
        ----------
        observation: `DataStoreObservation`
            Observation to compute effective area for.

        Returns
        -------
        aeff : `EffectiveAreaTable`
            Effective area table.
        """
        offset = observation.pointing_radec.separation(self.region.center)
        aeff = observation.aeff.to_effective_area_table(offset,
                                                        energy=self.e_true)

        if self.containment_correction:
            if not isinstance(self.region, CircleSkyRegion):
                raise TypeError(
                    "Containment correction only supported for circular regions."
                )
            table_psf = observation.psf.to_energy_dependent_table_psf(
                theta=offset)
            aeff = apply_containment_fraction(aeff, table_psf,
                                              self.region.radius)

        return aeff
Ejemplo n.º 2
0
    def apply_containment_correction(self, observation, bkg):
        """Apply PSF containment correction.

        Parameters
        ----------
        observation : `~gammapy.data.DataStoreObservation`
            observation
        bkg : `~gammapy.background.BackgroundEstimate`
            background esimate
        """
        if not isinstance(bkg.on_region, CircleSkyRegion):
            raise TypeError("Incorrect region type for containment correction."
                            " Should be CircleSkyRegion.")

        log.info("Apply containment correction")
        # First need psf
        angles = np.linspace(0.0, 1.5, 150) * u.deg
        offset = observation.pointing_radec.separation(bkg.on_region.center)
        if isinstance(observation.psf, PSF3D):
            psf = observation.psf.to_energy_dependent_table_psf(theta=offset)
        else:
            psf = observation.psf.to_energy_dependent_table_psf(offset, angles)

        new_aeff = apply_containment_fraction(self._aeff, psf,
                                              bkg.on_region.radius)

        # TODO: check whether keeping containment is necessary
        self.containment = new_aeff.data.data.value / self._aeff.data.data.value
        self._aeff = new_aeff
Ejemplo n.º 3
0
def test_apply_containment_fraction():
    n_edges_energy = 5
    energy = energy_logspace(0.1, 10.0, nbins=n_edges_energy + 1, unit="TeV")
    area = np.ones(n_edges_energy) * 4 * u.m**2
    aeff = EffectiveAreaTable(energy[:-1], energy[1:], data=area)

    nrad = 100
    rad = Angle(np.linspace(0, 0.5, nrad), "deg")
    psf_table = TablePSF.from_shape(shape="disk", width="0.2 deg", rad=rad)
    psf_values = (np.resize(psf_table.psf_value.value,
                            (n_edges_energy, nrad)) * psf_table.psf_value.unit)
    edep_psf_table = EnergyDependentTablePSF(aeff.energy.center,
                                             rad,
                                             psf_value=psf_values)

    new_aeff = apply_containment_fraction(aeff, edep_psf_table,
                                          Angle("0.1 deg"))

    assert_allclose(new_aeff.data.data.value, 1.0, rtol=5e-4)
    assert new_aeff.data.data.unit == "m2"
Ejemplo n.º 4
0
    def to_spectrum_dataset(self, on_region, containment_correction=False):
        """Return a ~gammapy.spectrum.SpectrumDataset from on_region.

        Counts and background are summed in the on_region.

        Effective area is taken from the average exposure divided by the livetime.
        Here we assume it is the sum of the GTIs.

        EnergyDispersion is obtained at the on_region center.
        Only regions with centers are supported.

        Parameters
        ----------
        on_region : `~regions.SkyRegion`
            the input ON region on which to extract the spectrum
        containment_correction : bool
            Apply containment correction for point sources and circular on regions

        Returns
        -------
        dataset : `~gammapy.spectrum.SpectrumDataset`
            the resulting reduced dataset
        """
        if self.gti is not None:
            livetime = self.gti.time_sum
        else:
            raise ValueError("No GTI in `MapDataset`, cannot compute livetime")

        if self.counts is not None:
            counts = self.counts.get_spectrum(on_region, np.sum)
        else:
            counts = None

        if self.background_model is not None:
            background = self.background_model.evaluate().get_spectrum(
                on_region, np.sum
            )
        else:
            background = None

        if self.exposure is not None:
            exposure = self.exposure.get_spectrum(on_region, np.mean)
            aeff = EffectiveAreaTable(
                energy_lo=exposure.energy.edges[:-1],
                energy_hi=exposure.energy.edges[1:],
                data=exposure.data / livetime,
            )
        else:
            aeff = None

        if containment_correction:
            if not isinstance(on_region, CircleSkyRegion):
                raise TypeError(
                    "Containement correction is only supported for"
                    " `CircleSkyRegion`."
                )
            elif self.psf is None or isinstance(self.psf, PSFKernel):
                raise ValueError("No PSFMap set. Containement correction impossible")
            else:
                psf_table = self.psf.get_energy_dependent_table_psf(on_region.center)
                aeff = apply_containment_fraction(aeff, psf_table, on_region.radius)

        if self.edisp is not None:
            if isinstance(self.edisp, EnergyDispersion):
                edisp = self.edisp
            else:
                self.edisp.get_energy_dispersion(on_region.center, self._energy_axis)
        else:
            edisp = None

        return SpectrumDataset(
            counts=counts,
            background=background,
            aeff=aeff,
            edisp=edisp,
            livetime=livetime,
            gti=self.gti,
            name=self.name,
        )