Esempio n. 1
0
    def to_edisp_kernel(self, offset, energy_true=None, energy=None):
        """Detector response R(Delta E_reco, Delta E_true)

        Probability to reconstruct an energy in a given true energy band
        in a given reconstructed energy band

        Parameters
        ----------
        offset : `~astropy.coordinates.Angle`
            Offset
        energy_true : `~astropy.units.Quantity`, None
            True energy axis
        energy : `~astropy.units.Quantity`
            Reconstructed energy axis

        Returns
        -------
        edisp : `~gammapy.irf.EDispKernel`
            Energy dispersion matrix
        """
        offset = Angle(offset)

        # TODO: expect directly MapAxis here?
        if energy is None:
            energy_axis = self.axes["energy_true"].copy(name="energy")
        else:
            energy_axis = MapAxis.from_energy_edges(energy)

        if energy_true is None:
            energy_axis_true = self.axes["energy_true"]
        else:
            energy_axis_true = MapAxis.from_energy_edges(
                energy_true,
                name="energy_true",
            )

        axes = MapAxes([energy_axis_true, energy_axis])
        coords = axes.get_coord(mode="edges", axis_name="energy")

        # migration value of energy bounds
        migra = coords["energy"] / coords["energy_true"]

        values = self.integral(
            axis_name="migra",
            offset=offset,
            energy_true=coords["energy_true"],
            migra=migra,
        )

        data = np.diff(values)

        return EDispKernel(
            axes=axes,
            data=data.to_value(""),
        )
Esempio n. 2
0
    def __init__(self, data, spectral_model):
        # TODO: Check data
        self.data = data

        if hasattr(self.data["norm"], "geom"):
            self.energy_axis = self.data["norm"].geom.axes["energy"]
            self._keys = self.data.keys()
            self._expand_slice = (slice(None), np.newaxis, np.newaxis)
        else:
            # Here we assume there is only one row per energy
            e_edges = self.data["e_min"].quantity
            e_edges = e_edges.insert(len(self.data), self.data["e_max"].quantity[-1])
            self.energy_axis = MapAxis.from_energy_edges(e_edges)
            self._keys = self.data.columns
            self._expand_slice = slice(None)

        # Note that here we could use the specification from dnde_ref to build piecewise PL
        # But does it work beyond min and max centers?
        self.spectral_model = spectral_model

        self._available_quantities = []

        for quantity in OPTIONAL_QUANTITIES:
            norm_quantity = f"norm_{quantity}"
            if norm_quantity in self._keys:
                self._available_quantities.append(quantity)
Esempio n. 3
0
    def run(self, dataset):
        """Make the profiles

        Parameters
        ----------
        dataset : `~gammapy.datasets.MapDataset` or `~gammapy.datasets.MapDatasetOnOff`
            the dataset to use for profile extraction

        Returns
        --------
        imageprofile : `~gammapy.estimators.ImageProfile`
            Return an image profile class containing the result
        """
        if self.energy_edges is not None:
            axis = MapAxis.from_energy_edges(self.energy_edges)
            dataset = dataset.resample_energy_axis(energy_axis=axis)
        else:
            dataset = dataset.to_image()

        spectrum_datasets = self.get_spectrum_datasets(dataset)

        results = self.make_prof(spectrum_datasets)
        table = table_from_row_data(results)
        if isinstance(self.regions[0], RectangleSkyRegion):
            table.meta["PROFILE_TYPE"] = "orthogonal_rectangle"
        table.meta["SPECTRAL_MODEL"] = self.spectrum.to_dict()

        # return ImageProfile(table)
        return table
Esempio n. 4
0
    def test(aeff):
        assert aeff.data.axes["energy_true"].nbin == 96
        assert aeff.data.axes["offset"].nbin == 6
        assert aeff.data.data.shape == (96, 6)

        assert aeff.data.axes["energy_true"].unit == "TeV"
        assert aeff.data.axes["offset"].unit == "deg"
        assert aeff.data.data.unit == "m2"

        assert_quantity_allclose(aeff.high_threshold, 100 * u.TeV, rtol=1e-3)
        assert_quantity_allclose(aeff.low_threshold, 0.870964 * u.TeV, rtol=1e-3)

        test_val = aeff.data.evaluate(energy_true="14 TeV", offset="0.2 deg")
        assert_allclose(test_val.value, 683177.5, rtol=1e-3)

        # Test ARF export
        offset = 0.236 * u.deg
        e_axis = np.logspace(0, 1, 20) * u.TeV
        effareafrom2d = aeff.to_effective_area_table(offset, e_axis)

        energy = np.sqrt(e_axis[:-1] * e_axis[1:])
        area = aeff.data.evaluate(energy_true=energy, offset=offset)

        energy_axis_true = MapAxis.from_energy_edges(e_axis, name="energy_true")
        effarea1d = EffectiveAreaTable(energy_axis_true=energy_axis_true, data=area)

        actual = effareafrom2d.data.evaluate(energy_true="2.34 TeV")
        desired = effarea1d.data.evaluate(energy_true="2.34 TeV")
        assert_equal(actual, desired)

        # Test ARF export #2
        offset = 1.2 * u.deg
        actual = aeff.to_effective_area_table(offset=offset).data.data
        desired = aeff.data.evaluate(offset=offset)
        assert_allclose(actual.value, desired.value.squeeze(), rtol=1e-9)
Esempio n. 5
0
def test_select_mask(models_gauss):
    center_sky = SkyCoord("0d", "0d")
    circle = CircleSkyRegion(center=center_sky, radius=1 * u.deg)
    axis = MapAxis.from_energy_edges(np.logspace(-1, 1, 3), unit="TeV")
    geom = WcsGeom.create(skydir=center_sky,
                          width=(5, 4),
                          axes=[axis],
                          binsz=0.02)

    mask = geom.region_mask([circle])

    contribute = models_gauss.select_mask(mask,
                                          margin=None,
                                          use_evaluation_region=True)
    assert contribute.names == ["source-1", "source-2"]

    inside = models_gauss.select_mask(mask,
                                      margin=None,
                                      use_evaluation_region=False)
    assert inside.names == ["source-1"]

    contribute_margin = models_gauss.select_mask(mask,
                                                 margin=0.1 * u.deg,
                                                 use_evaluation_region=True)
    assert contribute_margin.names == ["source-1", "source-2", "source-3"]
Esempio n. 6
0
    def run(self, datasets):
        """Estimate flux for a given energy range.

        Parameters
        ----------
        datasets : list of `~gammapy.datasets.SpectrumDataset`
            Spectrum datasets.

        Returns
        -------
        result : dict
            Dict with results for the flux point.
        """
        datasets = Datasets(datasets)
        models = datasets.models.copy()

        model = self.get_scale_model(models)

        energy_min, energy_max = datasets.energy_ranges
        energy_axis = MapAxis.from_energy_edges([energy_min.min(), energy_max.max()])

        with np.errstate(invalid="ignore", divide="ignore"):
            result = model.reference_fluxes(energy_axis=energy_axis)
            # convert to scalar values
            result = {key: value.item() for key, value in result.items()}

        models[self.source].spectral_model = model
        datasets.models = models
        result.update(super().run(datasets, model.norm))
        return result
Esempio n. 7
0
    def lightcurve(self):
        """Lightcurve (`~gammapy.estimators.FluxPoints`)."""
        time_axis = self.data["time_axis"]
        tag = "Flux_History"

        energy_axis = MapAxis.from_energy_edges(self.energy_range)
        geom = RegionGeom.create(region=self.position, axes=[energy_axis, time_axis])

        names = ["flux", "flux_errp", "flux_errn", "flux_ul"]
        maps = Maps.from_geom(geom=geom, names=names)

        maps["flux"].quantity = self.data[tag]
        maps["flux_errp"].quantity = self.data[f"Unc_{tag}"][:, 1]
        maps["flux_errn"].quantity = -self.data[f"Unc_{tag}"][:, 0]
        maps["flux_ul"].quantity = compute_flux_points_ul(
            maps["flux"].quantity, maps["flux_errp"].quantity
        )
        is_ul = np.isnan(maps["flux_errn"])
        maps["flux_ul"].data[~is_ul] = np.nan

        return FluxPoints.from_maps(
            maps=maps,
            sed_type="flux",
            reference_model=self.sky_model(),
            meta=self.flux_points_meta.copy(),
        )
Esempio n. 8
0
def make_edisp_map_test():
    pointing = SkyCoord(0, 0, unit="deg")

    energy_axis_true = MapAxis.from_energy_edges(
        energy_edges=[0.2, 0.7, 1.5, 2.0, 10.0] * u.TeV,
        name="energy_true",
    )

    migra_axis = MapAxis(nodes=np.linspace(0.0, 3.0, 51), unit="", name="migra")

    offset_axis = MapAxis.from_nodes([0.0, 1.0, 2.0, 3.0] * u.deg, name="offset")

    edisp2d = EnergyDispersion2D.from_gauss(
        energy_axis_true=energy_axis_true,
        migra_axis=migra_axis,
        offset_axis=offset_axis,
        bias=0,
        sigma=0.2,
    )

    geom = WcsGeom.create(
        skydir=pointing, binsz=1.0, width=5.0, axes=[migra_axis, energy_axis_true]
    )

    aeff2d = fake_aeff2d()
    exposure_geom = geom.squash(axis_name="migra")
    exposure_map = make_map_exposure_true_energy(pointing, "1 h", aeff2d, exposure_geom)

    return make_edisp_map(edisp2d, pointing, geom, exposure_map)
Esempio n. 9
0
    def to_edisp_kernel(self, offset, energy_true=None, energy=None):
        """Detector response R(Delta E_reco, Delta E_true)

        Probability to reconstruct an energy in a given true energy band
        in a given reconstructed energy band

        Parameters
        ----------
        offset : `~astropy.coordinates.Angle`
            Offset
        energy_true : `~astropy.units.Quantity`, None
            True energy axis
        energy : `~astropy.units.Quantity`
            Reconstructed energy axis

        Returns
        -------
        edisp : `~gammapy.irf.EDispKernel`
            Energy dispersion matrix
        """
        offset = Angle(offset)

        # TODO: expect directly MapAxis here?
        if energy is None:
            energy_axis = self.data.axes["energy_true"].copy(name="energy")
        else:
            energy_axis = MapAxis.from_energy_edges(energy)

        if energy_true is None:
            energy_axis_true = self.data.axes["energy_true"]
        else:
            energy_axis_true = MapAxis.from_energy_edges(
                energy_true, name="energy_true"
            )

        data = []
        for value in energy_axis_true.center:
            vec = self.get_response(
                offset=offset, energy_true=value, energy=energy_axis.edges
            )
            data.append(vec)

        return EDispKernel(
            energy_axis=energy_axis,
            energy_axis_true=energy_axis_true,
            data=np.asarray(data),
        )
Esempio n. 10
0
    def to_edisp_kernel(self, offset, energy_true=None, energy=None):
        """Detector response R(Delta E_reco, Delta E_true)

        Probability to reconstruct an energy in a given true energy band
        in a given reconstructed energy band

        Parameters
        ----------
        offset : `~astropy.coordinates.Angle`
            Offset
        energy_true : `~astropy.units.Quantity`, None
            True energy axis
        energy : `~astropy.units.Quantity`
            Reconstructed energy axis

        Returns
        -------
        edisp : `~gammapy.irf.EDispKernel`
            Energy dispersion matrix
        """
        from gammapy.makers.utils import make_edisp_kernel_map

        offset = Angle(offset)

        # TODO: expect directly MapAxis here?
        if energy is None:
            energy_axis = self.axes["energy_true"].copy(name="energy")
        else:
            energy_axis = MapAxis.from_energy_edges(energy)

        if energy_true is None:
            energy_axis_true = self.axes["energy_true"]
        else:
            energy_axis_true = MapAxis.from_energy_edges(
                energy_true,
                name="energy_true",
            )

        pointing = SkyCoord("0d", "0d")

        center = pointing.directional_offset_by(position_angle=0 * u.deg,
                                                separation=offset)
        geom = RegionGeom.create(region=center,
                                 axes=[energy_axis, energy_axis_true])

        edisp = make_edisp_kernel_map(geom=geom, edisp=self, pointing=pointing)
        return edisp.get_edisp_kernel()
Esempio n. 11
0
    def from_gauss(cls,
                   e_true,
                   migra,
                   bias,
                   sigma,
                   offset,
                   pdf_threshold=1e-6):
        """Create Gaussian energy dispersion matrix (`EnergyDispersion2D`).

        The output matrix will be Gaussian in (e_true / e_reco).

        The ``bias`` and ``sigma`` should be either floats or arrays of same dimension than
        ``e_true``. ``bias`` refers to the mean value of the ``migra``
        distribution minus one, i.e. ``bias=0`` means no bias.

        Note that, the output matrix is flat in offset.

        Parameters
        ----------
        e_true : `~astropy.units.Quantity`
            Bin edges of true energy axis
        migra : `~astropy.units.Quantity`
            Bin edges of migra axis
        bias : float or `~numpy.ndarray`
            Center of Gaussian energy dispersion, bias
        sigma : float or `~numpy.ndarray`
            RMS width of Gaussian energy dispersion, resolution
        offset : `~astropy.units.Quantity`
            Bin edges of offset
        pdf_threshold : float, optional
            Zero suppression threshold
        """
        e_true = Quantity(e_true)
        # erf does not work with Quantities
        energy_axis_true = MapAxis.from_energy_edges(e_true,
                                                     interp="log",
                                                     name="energy_true")

        true2d, migra2d = np.meshgrid(energy_axis_true.center, migra)

        migra2d_lo = migra2d[:-1, :]
        migra2d_hi = migra2d[1:, :]

        # Analytical formula for integral of Gaussian
        s = np.sqrt(2) * sigma
        t1 = (migra2d_hi - 1 - bias) / s
        t2 = (migra2d_lo - 1 - bias) / s
        pdf = (scipy.special.erf(t1) - scipy.special.erf(t2)) / 2

        data = pdf.T[:, :, np.newaxis] * np.ones(len(offset) - 1)

        data[data < pdf_threshold] = 0

        offset_axis = MapAxis.from_edges(offset, name="offset")
        migra_axis = MapAxis.from_edges(migra, name="migra")
        return cls(energy_axis_true=energy_axis_true,
                   migra_axis=migra_axis,
                   offset_axis=offset_axis,
                   data=data)
Esempio n. 12
0
    def _get_energy_axis(self, dataset):
        """Energy axis"""
        if self.energy_edges is None:
            energy_axis = dataset.counts.geom.axes["energy"].squash()
        else:
            energy_axis = MapAxis.from_energy_edges(self.energy_edges)

        return energy_axis
Esempio n. 13
0
    def test_from_parametrization():
        # Log center of this is 100 GeV
        area_ref = 1.65469579e07 * u.cm ** 2

        axis = MapAxis.from_energy_edges([80, 125] * u.GeV, name="energy_true")
        area = EffectiveAreaTable2D.from_parametrization(axis, "HESS")

        assert_allclose(area.quantity, area_ref)
        assert area.unit == area_ref.unit

        # Log center of this is 0.1, 2 TeV
        area_ref = [1.65469579e07, 1.46451957e09] * u.cm * u.cm

        axis = MapAxis.from_energy_edges([0.08, 0.125, 32] * u.TeV, name="energy_true")
        area = EffectiveAreaTable2D.from_parametrization(axis, "HESS")
        assert_allclose(area.quantity[:, 0], area_ref)
        assert area.unit == area_ref.unit
Esempio n. 14
0
    def from_diagonal_response(cls, energy_true, energy=None):
        """Create energy dispersion from a diagonal response, i.e. perfect energy resolution

        This creates the matrix corresponding to a perfect energy response.
        It contains ones where the energy_true center is inside the e_reco bin.
        It is a square diagonal matrix if energy_true = e_reco.

        This is useful in cases where code always applies an edisp,
        but you don't want it to do anything.

        Parameters
        ----------
        energy_true, energy : `~astropy.units.Quantity`
            Energy edges for true and reconstructed energy axis

        Examples
        --------
        If ``energy_true`` equals ``energy``, you get a diagonal matrix::

            energy_true = [0.5, 1, 2, 4, 6] * u.TeV
            edisp = EnergyDispersion.from_diagonal_response(energy_true)
            edisp.plot_matrix()

        Example with different energy binnings::

            energy_true = [0.5, 1, 2, 4, 6] * u.TeV
            energy = [2, 4, 6] * u.TeV
            edisp = EnergyDispersion.from_diagonal_response(energy_true, energy)
            edisp.plot_matrix()
        """
        from .edisp_map import get_overlap_fraction

        if energy is None:
            energy = energy_true

        energy_axis = MapAxis.from_energy_edges(energy)
        energy_axis_true = MapAxis.from_energy_edges(energy_true,
                                                     name="energy_true")

        data = get_overlap_fraction(energy_axis, energy_axis_true)
        return cls(
            energy_axis=energy_axis,
            energy_axis_true=energy_axis_true,
            data=data,
        )
Esempio n. 15
0
    def test_from_diagonal_response(self):
        energy_axis_true = MapAxis.from_energy_edges([0.5, 1, 2, 4, 6] * u.TeV, name="energy_true")
        energy_axis = MapAxis.from_energy_edges([2, 4, 6] * u.TeV)

        edisp = EDispKernel.from_diagonal_response(energy_axis_true, energy_axis)

        assert edisp.pdf_matrix.shape == (4, 2)
        expected = [[0, 0], [0, 0], [1, 0], [0, 1]]

        assert_equal(edisp.pdf_matrix, expected)

        # Test square matrix
        edisp = EDispKernel.from_diagonal_response(energy_axis_true)
        assert_allclose(edisp.axes["energy"].edges, edisp.axes["energy_true"].edges)
        assert edisp.axes["energy"].unit == "TeV"
        assert_equal(edisp.pdf_matrix[0][0], 1)
        assert_equal(edisp.pdf_matrix[2][0], 0)
        assert edisp.pdf_matrix.sum() == 4
Esempio n. 16
0
def bkg_2d():
    """A simple Background2D test case"""
    energy = [0.1, 10, 1000] * u.TeV
    energy_axis = MapAxis.from_energy_edges(energy)

    offset = [0, 1, 2, 3] * u.deg
    offset_axis = MapAxis.from_edges(offset, name="offset")
    data = np.zeros((2, 3)) * u.Unit("s-1 MeV-1 sr-1")
    data.value[1, 0] = 2
    data.value[1, 1] = 4
    return Background2D(energy_axis=energy_axis, offset_axis=offset_axis, data=data,)
Esempio n. 17
0
    def run(self, dataset):
        """Compute correlated excess, Li & Ma significance and flux maps

        If a model is set on the dataset the excess map estimator will compute the excess taking into account
        the predicted counts of the model.

        Parameters
        ----------
        dataset : `~gammapy.datasets.MapDataset` or `~gammapy.datasets.MapDatasetOnOff`
            input dataset

        Returns
        -------
        images : dict
            Dictionary containing result correlated maps. Keys are:

                * counts : correlated counts map
                * background : correlated background map
                * excess : correlated excess map
                * ts : TS map
                * sqrt_ts : sqrt(delta TS), or Li-Ma significance map
                * err : symmetric error map (from covariance)
                * flux : flux map. An exposure map must be present in the dataset to compute flux map
                * errn : negative error map
                * errp : positive error map
                * ul : upper limit map

        """
        if not isinstance(dataset, MapDataset):
            raise ValueError(
                "Unsupported dataset type. Excess map is not applicable to 1D datasets."
            )

        if self.energy_edges is None:
            energy_axis = dataset.counts.geom.axes["energy"]
            energy_edges = u.Quantity(
                [energy_axis.edges[0], energy_axis.edges[-1]])
        else:
            energy_edges = self.energy_edges

        axis = MapAxis.from_energy_edges(energy_edges)

        resampled_dataset = dataset.resample_energy_axis(energy_axis=axis,
                                                         name=dataset.name)
        if isinstance(dataset, MapDatasetOnOff):
            resampled_dataset.models = dataset.models
        else:
            resampled_dataset.background = dataset.npred().resample_axis(
                axis=axis)
            resampled_dataset.models = None
        result = self.estimate_excess_map(resampled_dataset)

        return result
Esempio n. 18
0
def map_flux_estimate():
    axis = MapAxis.from_energy_edges((0.1, 1.0, 10.0), unit="TeV")

    nmap = WcsNDMap.create(npix=5, axes=[axis])

    cols = dict()
    cols["norm"] = nmap.copy(data=1.0)
    cols["norm_err"] = nmap.copy(data=0.1)
    cols["norm_errn"] = nmap.copy(data=0.2)
    cols["norm_errp"] = nmap.copy(data=0.15)
    cols["norm_ul"] = nmap.copy(data=2.0)

    return cols
Esempio n. 19
0
    def from_constant(cls, energy, value):
        """Create constant value effective area.

        Parameters
        ----------
        energy : `~astropy.units.Quantity`
            Energy binning, analytic function is evaluated at log centers
        value : `~astropy.units.Quantity`
            Effective area
        """
        value = u.Quantity(value)
        energy_axis_true = MapAxis.from_energy_edges(energy,
                                                     name="energy_true")
        return cls(axes=[energy_axis_true], data=value.value, unit=value.unit)
Esempio n. 20
0
    def from_constant(cls, energy, value):
        """Create constant value effective area.

        Parameters
        ----------
        energy : `~astropy.units.Quantity`
            Energy binning, analytic function is evaluated at log centers
        value : `~astropy.units.Quantity`
            Effective area
        """
        data = np.ones((len(energy) - 1)) * u.Quantity(value)
        energy_axis_true = MapAxis.from_energy_edges(energy,
                                                     name="energy_true")
        return cls(energy_axis_true=energy_axis_true, data=data)
Esempio n. 21
0
def test_bkg_2d_wrong_units():
    energy = [0.1, 10, 1000] * u.TeV
    energy_axis = MapAxis.from_energy_edges(energy)

    offset_axis = MapAxis.from_edges([0, 1, 2], unit="deg", name="offset")

    wrong_unit = u.cm**2 * u.s
    data = np.ones((energy_axis.nbin, offset_axis.nbin)) * wrong_unit
    bkg2d_test = Background2D(axes=[energy_axis, offset_axis])
    with pytest.raises(ValueError) as error:
        Background2D(axes=[energy_axis, offset_axis], data=data)
        assert error.match(
            f"Error: {wrong_unit} is not an allowed unit. {bkg2d_test.tag} requires {bkg2d_test.default_unit} data quantities."
        )
Esempio n. 22
0
def region_map_flux_estimate():
    axis = MapAxis.from_energy_edges((0.1, 1.0, 10.0), unit="TeV")
    geom = RegionGeom.create("galactic;circle(0, 0, 0.1)", axes=[axis])

    maps = Maps.from_geom(
        geom=geom,
        names=["norm", "norm_err", "norm_errn", "norm_errp", "norm_ul"])

    maps["norm"].data = np.array([1.0, 1.0])
    maps["norm_err"].data = np.array([0.1, 0.1])
    maps["norm_errn"].data = np.array([0.2, 0.2])
    maps["norm_errp"].data = np.array([0.15, 0.15])
    maps["norm_ul"].data = np.array([2.0, 2.0])
    return maps
Esempio n. 23
0
def table_flux_estimate():
    axis = MapAxis.from_energy_edges((0.1, 1.0, 10.0), unit="TeV")

    cols = dict()
    cols["norm"] = np.array([1.0, 1.0])
    cols["norm_err"] = np.array([0.1, 0.1])
    cols["norm_errn"] = np.array([0.2, 0.2])
    cols["norm_errp"] = np.array([0.15, 0.15])
    cols["norm_ul"] = np.array([2.0, 2.0])
    cols["e_min"] = axis.edges[:-1]
    cols["e_max"] = axis.edges[1:]

    table = Table(cols, names=cols.keys())

    return table
Esempio n. 24
0
def test_axes_basics():
    energy_axis = MapAxis.from_energy_edges([1, 3] * u.TeV)

    time_ref = Time('1999-01-01T00:00:00.123456789')

    time_axis = TimeMapAxis(edges_min=[0, 1, 3] * u.d,
                            edges_max=[0.8, 1.9, 5.4] * u.d,
                            reference_time=time_ref)

    axes = MapAxes([energy_axis, time_axis])

    assert axes.shape == (1, 3)
    assert axes.is_unidimensional
    assert not axes.is_flat

    assert axes.primary_axis.name == "time"
Esempio n. 25
0
    def lightcurve(self, interval="1-year"):
        """Lightcurve (`~gammapy.estimators.FluxPoints`).

        Parameters
        ----------
        interval : {'1-year', '2-month'}
            Time interval of the lightcurve. Default is '1-year'.
            Note that '2-month' is not available for all catalogue version.
        """

        if interval == "1-year":
            tag = "Flux_History"
            time_axis = self.data["time_axis"]
            tag_sqrt_ts = "Sqrt_TS_History"
        elif interval == "2-month":
            tag = "Flux2_History"
            if tag not in self.data:
                raise ValueError(
                    "Only '1-year' interval is available for this catalogue version"
                )

            time_axis = self.data["time_axis_2"]
            tag_sqrt_ts = "Sqrt_TS2_History"
        else:
            raise ValueError("Time intervals available are '1-year' or '2-month'")

        energy_axis = MapAxis.from_energy_edges([50, 300000] * u.MeV)
        geom = RegionGeom.create(region=self.position, axes=[energy_axis, time_axis])

        names = ["flux", "flux_errp", "flux_errn", "flux_ul", "ts"]
        maps = Maps.from_geom(geom=geom, names=names)

        maps["flux"].quantity = self.data[tag]
        maps["flux_errp"].quantity = self.data[f"Unc_{tag}"][:, 1]
        maps["flux_errn"].quantity = -self.data[f"Unc_{tag}"][:, 0]
        maps["flux_ul"].quantity = compute_flux_points_ul(
            maps["flux"].quantity, maps["flux_errp"].quantity
        )
        maps["ts"].quantity = self.data[tag_sqrt_ts] ** 2

        return FluxPoints.from_maps(
            maps=maps,
            sed_type="flux",
            reference_model=self.sky_model(),
            meta=self.flux_points.meta.copy(),
        )
Esempio n. 26
0
def test_psf_3d_wrong_units():
    energy_axis = MapAxis.from_energy_edges([80, 125] * u.GeV,
                                            name="energy_true")

    offset_axis = MapAxis.from_edges([0, 1, 2], unit="deg", name="offset")

    rad_axis = MapAxis.from_edges([0, 1, 2], unit="deg", name="rad")

    wrong_unit = u.cm**2 * u.s
    data = np.ones(
        (energy_axis.nbin, offset_axis.nbin, rad_axis.nbin)) * wrong_unit
    psf3d_test = PSF3D(axes=[energy_axis, offset_axis, rad_axis])
    with pytest.raises(ValueError) as error:
        PSF3D(axes=[energy_axis, offset_axis, rad_axis], data=data)
        assert error.match(
            f"Error: {wrong_unit} is not an allowed unit. {psf3d_test.tag} requires {psf3d_test.default_unit} data quantities."
        )
Esempio n. 27
0
def test_bkg_3d_wrong_units():
    energy = [0.1, 10, 1000] * u.TeV
    energy_axis = MapAxis.from_energy_edges(energy)

    fov_lon = [0, 1, 2, 3] * u.deg
    fov_lon_axis = MapAxis.from_edges(fov_lon, name="fov_lon")

    fov_lat = [0, 1, 2, 3] * u.deg
    fov_lat_axis = MapAxis.from_edges(fov_lat, name="fov_lat")

    wrong_unit = u.cm**2 * u.s
    data = np.ones((2, 3, 3)) * wrong_unit
    with pytest.raises(ValueError) as error:
        Background3D(axes=[energy_axis, fov_lon_axis, fov_lat_axis], data=data)
    assert error.match(
        "Error: (.*) is not an allowed unit. (.*) requires (.*) data quantities."
    )
Esempio n. 28
0
def bkg_3d_custom(symmetry="constant"):
    if symmetry == "constant":
        data = np.ones((2, 3, 3))
    elif symmetry == "symmetric":
        data = np.ones((2, 3, 3))
        data[:, 1, 1] *= 2
    elif symmetry == "asymmetric":
        data = np.indices((3, 3))[1] + 1
        data = np.stack(2 * [data])
    else:
        raise ValueError(f"Unkown value for symmetry: {symmetry}")

    energy_axis = MapAxis.from_energy_edges([0.1, 10, 1000] * u.TeV)
    fov_lon_axis = MapAxis.from_edges([-3, -1, 1, 3] * u.deg, name="fov_lon")
    fov_lat_axis = MapAxis.from_edges([-3, -1, 1, 3] * u.deg, name="fov_lat")
    return Background3D(axes=[energy_axis, fov_lon_axis, fov_lat_axis],
                        data=data,
                        unit=u.Unit("s-1 MeV-1 sr-1"))
Esempio n. 29
0
def bkg_3d():
    """Example with simple values to test evaluate"""
    energy = [0.1, 10, 1000] * u.TeV
    energy_axis = MapAxis.from_energy_edges(energy)

    fov_lon = [0, 1, 2, 3] * u.deg
    fov_lon_axis = MapAxis.from_edges(fov_lon, name="fov_lon")

    fov_lat = [0, 1, 2, 3] * u.deg
    fov_lat_axis = MapAxis.from_edges(fov_lat, name="fov_lat")

    data = np.ones((2, 3, 3))
    # Axis order is (energy, fov_lon, fov_lat)
    # data.value[1, 0, 0] = 1
    data[1, 1, 1] = 100
    return Background3D(axes=[energy_axis, fov_lon_axis, fov_lat_axis],
                        data=data,
                        unit="s-1 GeV-1 sr-1")
Esempio n. 30
0
    def __init__(self, data, reference_spectral_model):
        # TODO: Check data
        self._data = data

        if hasattr(self._data["norm"], "geom"):
            self.energy_axis = self.data["norm"].geom.axes["energy"]
            self._expand_slice = (slice(None), np.newaxis, np.newaxis)
        else:
            # Here we assume there is only one row per energy
            e_edges = self._data["e_min"].quantity
            e_edges = e_edges.insert(len(self._data),
                                     self._data["e_max"].quantity[-1])
            self.energy_axis = MapAxis.from_energy_edges(e_edges)
            self._expand_slice = slice(None)

        # Note that here we could use the specification from dnde_ref to build piecewise PL
        # But does it work beyond min and max centers?

        self._reference_spectral_model = reference_spectral_model