Ejemplo n.º 1
0
 def position_error(self):
     """Get 95% containment position error as (`~regions.EllipseSkyRegion`)"""
     if self.covariance is None:
         return EllipseSkyRegion(
             center=self.position,
             height=np.nan * u.deg,
             width=np.nan * u.deg,
             angle=np.nan * u.deg,
         )
     pars = self.parameters
     sub_covar = self.covariance.get_subcovariance(["lon_0",
                                                    "lat_0"]).data.copy()
     cos_lat = np.cos(self.lat_0.quantity.to_value("rad"))
     sub_covar[0, 0] *= cos_lat**2.0
     sub_covar[0, 1] *= cos_lat
     sub_covar[1, 0] *= cos_lat
     eig_vals, eig_vecs = np.linalg.eig(sub_covar)
     lon_err, lat_err = np.sqrt(eig_vals)
     y_vec = eig_vecs[:, 0]
     phi = (np.arctan2(y_vec[1], y_vec[0]) * u.rad).to("deg") + self.phi_0
     err = np.sort([lon_err, lat_err])
     scale_r95 = Gauss2DPDF().containment_radius(0.95)
     err *= scale_r95
     if err[1] == lon_err * scale_r95:
         phi += 90 * u.deg
         height = 2 * err[1] * pars["lon_0"].unit
         width = 2 * err[0] * pars["lat_0"].unit
     else:
         height = 2 * err[1] * pars["lat_0"].unit
         width = 2 * err[0] * pars["lon_0"].unit
     return EllipseSkyRegion(center=self.position,
                             height=height,
                             width=width,
                             angle=phi)
Ejemplo n.º 2
0
    def test_position_error(cat):
        scale_r95 = Gauss2DPDF().containment_radius(0.95)

        model = cat["HESS J1729-345"].spatial_model()
        pos_err = model.position_error
        assert_allclose(pos_err.angle.value, 0.0)
        assert_allclose(pos_err.height.value,
                        2 * 0.0414315 * scale_r95,
                        rtol=1e-4)
        assert_allclose(pos_err.width.value,
                        2 * 0.0344351 * scale_r95,
                        rtol=1e-4)
        assert_allclose(model.position.l.value, pos_err.center.l.value)
        assert_allclose(model.position.b.value, pos_err.center.b.value)

        model = cat["HESS J1858+020"].spatial_model()
        pos_err = model.position_error
        assert_allclose(pos_err.angle.value, 90.0)
        assert_allclose(pos_err.height.value,
                        2 * 0.0222614 * scale_r95,
                        rtol=1e-4)
        assert_allclose(pos_err.width.value,
                        2 * 0.0145084 * scale_r95,
                        rtol=1e-4)
        assert_allclose(model.position.l.value, pos_err.center.l.value)
        assert_allclose(model.position.b.value, pos_err.center.b.value)
Ejemplo n.º 3
0
    def _set_spatial_errors(self, model):
        d = self.data

        if "Pos_err_68" in d:
            percent = 0.68
            semi_minor = d["Pos_err_68"]
            semi_major = d["Pos_err_68"]
            phi_0 = 0.0
        else:
            percent = 0.95
            semi_minor = d["Conf_95_SemiMinor"]
            semi_major = d["Conf_95_SemiMajor"]
            phi_0 = d["Conf_95_PosAng"]

        if np.isnan(phi_0):
            phi_0 = 0.0 * u.deg

        scale_1sigma = Gauss2DPDF().containment_radius(percent)
        lat_err = semi_major / scale_1sigma
        lon_err = semi_minor / scale_1sigma / np.cos(d["DEJ2000"])

        if "TemplateSpatialModel" not in model.tag:
            model.parameters["lon_0"].error = lon_err
            model.parameters["lat_0"].error = lat_err
            model.phi_0 = phi_0
Ejemplo n.º 4
0
    def test_spatial_model(cat):
        m = cat[1].spatial_model()
        # p = m.parameters

        assert isinstance(m, PointSpatialModel)
        assert m.lon_0.unit == "deg"
        assert_allclose(m.lon_0.value, 195.614, atol=1e-2)
        # TODO: add assert on position error
        # assert_allclose(p.error("lon_0"), tbd)
        assert m.lat_0.unit == "deg"
        assert_allclose(m.lat_0.value, 3.507, atol=1e-2)
        assert m.frame == "galactic"

        m = cat[1].spatial_model("extended")

        assert isinstance(m, DiskSpatialModel)
        assert m.lon_0.unit == "deg"
        assert_allclose(m.lon_0.value, 195.614, atol=1e-10)
        assert m.lat_0.unit == "deg"
        assert_allclose(m.lat_0.value, 3.507, atol=1e-10)
        assert m.frame == "galactic"
        assert m.r_0.unit == "deg"
        assert_allclose(m.r_0.value, 2.0, atol=1e-3)

        model = cat["2HWC J0534+220"].spatial_model()
        pos_err = model.position_error
        scale_r95 = Gauss2DPDF().containment_radius(0.95)
        assert_allclose(pos_err.height.value, 2 * 0.057 * scale_r95, rtol=1e-4)
        assert_allclose(pos_err.width.value, 2 * 0.057 * scale_r95, rtol=1e-4)
        assert_allclose(model.position.l.value, pos_err.center.l.value)
        assert_allclose(model.position.b.value, pos_err.center.b.value)
Ejemplo n.º 5
0
    def test_spatial_model(ca_3hwc):
        m = ca_3hwc[1].spatial_model()

        assert isinstance(m, PointSpatialModel)
        assert m.lon_0.unit == "deg"
        assert_allclose(m.lon_0.value, 184.583, atol=1e-2)
        assert_allclose(m.lon_0.error, 0.112, atol=1e-2)
        assert m.lat_0.unit == "deg"
        assert_allclose(m.lat_0.value, -4.129, atol=1e-2)
        assert m.frame == "galactic"

        m = ca_3hwc["3HWC J0621+382"].spatial_model()

        assert isinstance(m, DiskSpatialModel)
        assert m.lon_0.unit == "deg"
        assert_allclose(m.lon_0.value, 175.444, atol=1e-10)
        assert m.lat_0.unit == "deg"
        assert_allclose(m.lat_0.value, 10.966, atol=1e-10)
        assert m.frame == "galactic"
        assert m.r_0.unit == "deg"
        assert_allclose(m.r_0.value, 0.5, atol=1e-3)

        model = ca_3hwc["3HWC J0621+382"].spatial_model()
        pos_err = model.position_error
        scale_r95 = Gauss2DPDF().containment_radius(0.95)
        assert_allclose(pos_err.height.value, 2 * 0.301 * scale_r95, rtol=1e-4)
        assert_allclose(pos_err.width.value, 2 * 0.301 * scale_r95, rtol=1e-4)
        assert_allclose(model.position.l.value, pos_err.center.l.value)
        assert_allclose(model.position.b.value, pos_err.center.b.value)
Ejemplo n.º 6
0
def test_compute_flux_spatial():
    center = SkyCoord("0 deg", "0 deg", frame="galactic")
    region = CircleSkyRegion(center=center, radius=0.1 * u.deg)

    nbin = 2
    energy_axis_true = MapAxis.from_energy_bounds(".1 TeV",
                                                  "10 TeV",
                                                  nbin=nbin,
                                                  name="energy_true")

    spectral_model = ConstantSpectralModel()
    spatial_model = PointSpatialModel(lon_0=0 * u.deg,
                                      lat_0=0 * u.deg,
                                      frame="galactic")

    models = SkyModel(spectral_model=spectral_model,
                      spatial_model=spatial_model)
    model = Models(models)

    exposure_region = RegionNDMap.create(region,
                                         axes=[energy_axis_true],
                                         binsz_wcs="0.01deg",
                                         unit="m2 s",
                                         data=1.0)

    geom = RegionGeom(region, axes=[energy_axis_true], binsz_wcs="0.01deg")
    psf = PSFKernel.from_gauss(geom.to_wcs_geom(), sigma="0.1 deg")

    evaluator = MapEvaluator(model=model[0], exposure=exposure_region, psf=psf)
    flux = evaluator.compute_flux_spatial()

    g = Gauss2DPDF(0.1)
    reference = g.containment_fraction(0.1)
    assert_allclose(flux.value, reference, rtol=0.003)
Ejemplo n.º 7
0
    def from_gauss(cls,
                   energy_axis_true,
                   rad_axis=None,
                   sigma=0.1 * u.deg,
                   geom=None):
        """Create all -sky PSF map from Gaussian width.

        This is used for testing and examples.

        The width can be the same for all energies
        or be an array with one value per energy node.
        It does not depend on position.

        Parameters
        ----------
        energy_axis_true : `~gammapy.maps.MapAxis`
            True energy axis.
        rad_axis : `~gammapy.maps.MapAxis`
            Offset angle wrt source position axis.
        sigma : `~astropy.coordinates.Angle`
            Gaussian width.
        geom : `Geom`
            Image geometry. By default an allsky geometry is created.

        Returns
        -------
        psf_map : `PSFMap`
            Point spread function map.
        """
        from gammapy.datasets.map import RAD_AXIS_DEFAULT

        if rad_axis is None:
            rad_axis = RAD_AXIS_DEFAULT.copy()

        if geom is None:
            geom = WcsGeom.create(
                npix=(2, 1),
                proj="CAR",
                binsz=180,
            )

        geom = geom.to_cube([rad_axis, energy_axis_true])

        coords = geom.get_coord(sparse=True)

        sigma = u.Quantity(sigma).reshape((-1, 1, 1, 1))
        gauss = Gauss2DPDF(sigma=sigma)

        data = gauss(coords["rad"]) * np.ones(geom.data_shape)

        psf_map = Map.from_geom(geom=geom,
                                data=data.to_value("sr-1"),
                                unit="sr-1")

        exposure_map = Map.from_geom(geom=geom.squash(axis_name="rad"),
                                     unit="m2 s",
                                     data=1.)
        return cls(psf_map=psf_map, exposure_map=exposure_map)
Ejemplo n.º 8
0
    def test_spatial_model(self):
        model = self.cat[221].spatial_model()
        assert model.tag == "PointSpatialModel"
        assert model.frame == "icrs"
        p = model.parameters
        assert_allclose(p["lon_0"].value, 221.281998, rtol=1e-5)
        assert_allclose(p["lat_0"].value, -3.4943, rtol=1e-5)

        model = self.cat["2FHL J1304.5-4353"].spatial_model()
        pos_err = model.position_error
        scale = Gauss2DPDF().containment_radius(0.95) / Gauss2DPDF().containment_radius(
            0.68
        )
        assert_allclose(pos_err.height.value, 2 * 0.041987 * scale, rtol=1e-4)
        assert_allclose(pos_err.width.value, 2 * 0.041987 * scale, rtol=1e-4)
        assert_allclose(model.position.ra.value, pos_err.center.ra.value)
        assert_allclose(model.position.dec.value, pos_err.center.dec.value)

        model = self.cat[97].spatial_model()
        assert model.tag == "GaussianSpatialModel"
        assert model.frame == "icrs"
        p = model.parameters
        assert_allclose(p["lon_0"].value, 94.309998, rtol=1e-5)
        assert_allclose(p["lat_0"].value, 22.58, rtol=1e-5)
        assert_allclose(p["sigma"].value, 0.27)

        model = self.cat[134].spatial_model()
        assert model.tag == "DiskSpatialModel"
        assert model.frame == "icrs"
        p = model.parameters
        assert_allclose(p["lon_0"].value, 125.660004, rtol=1e-5)
        assert_allclose(p["lat_0"].value, -42.84, rtol=1e-5)
        assert_allclose(p["r_0"].value, 0.37)

        model = self.cat[256].spatial_model()
        assert model.tag == "TemplateSpatialModel"
        assert model.frame == "fk5"
        assert model.normalize is True
Ejemplo n.º 9
0
    def from_gauss(
        cls, geom, sigma, max_radius=None, containment_fraction=0.99, factor=4
    ):
        """Create Gaussian PSF.

        This is used for testing and examples.
        The map geometry parameters (pixel size, energy bins) are taken from ``geom``.
        The Gaussian width ``sigma`` is a scalar,

        TODO : support array input if it should vary along the energy axis.

        Parameters
        ----------
        geom : `~gammapy.maps.WcsGeom`
            Map geometry
        sigma : `~astropy.coordinates.Angle`
            Gaussian width.
        max_radius : `~astropy.coordinates.Angle`
            Desired kernel map size.
        factor : int
            Oversample factor to compute the PSF

        Returns
        -------
        kernel : `~gammapy.irf.PSFKernel`
            the kernel Map with reduced geometry according to the max_radius
        """
        sigma = Angle(sigma)

        if max_radius is None:
            max_radius = (
                Gauss2DPDF(sigma.deg).containment_radius(
                    containment_fraction=containment_fraction
                )
                * u.deg
            )

        max_radius = Angle(max_radius)

        # Create a new geom according to given input
        geom = _make_kernel_geom(geom, max_radius)

        rad = Angle(np.linspace(0.0, max_radius.deg, 200), "deg")

        table_psf = TablePSF.from_shape(shape="gauss", width=sigma, rad=rad)

        return cls.from_table_psf(table_psf, geom=geom, factor=factor)
Ejemplo n.º 10
0
    def test_spatial_model(self, gammacat, ref):
        source = gammacat[ref["name"]]

        spatial_model = source.spatial_model()
        assert spatial_model.frame == "galactic"

        # TODO: put better asserts on model properties
        # TODO: add a point and shell source -> separate list of sources for morphology test parametrization?
        assert spatial_model.__class__.__name__ == ref["spatial_model"]

        model = gammacat["HESS J1634-472"].spatial_model()
        pos_err = model.position_error
        scale_r95 = Gauss2DPDF().containment_radius(0.95)
        assert_allclose(pos_err.height.value, 2 * 0.044721 * scale_r95, rtol=1e-4)
        assert_allclose(pos_err.width.value, 2 * 0.044721 * scale_r95, rtol=1e-4)
        assert_allclose(model.position.l.value, pos_err.center.l.value)
        assert_allclose(model.position.b.value, pos_err.center.b.value)
Ejemplo n.º 11
0
    def from_shape(cls, shape, width, rad):
        """Make TablePSF objects with commonly used shapes.

        This function is mostly useful for examples and testing.

        Parameters
        ----------
        shape : {'disk', 'gauss'}
            PSF shape.
        width : `~astropy.units.Quantity` with angle units
            PSF width angle (radius for disk, sigma for Gauss).
        rad : `~astropy.units.Quantity` with angle units
            Offset angle

        Returns
        -------
        psf : `TablePSF`
            Table PSF

        Examples
        --------
        >>> import numpy as np
        >>> from astropy.coordinates import Angle
        >>> from gammapy.irf import TablePSF
        >>> rad = Angle(np.linspace(0, 0.7, 100), 'deg')
        >>> psf = TablePSF.from_shape(shape='gauss', width='0.2 deg', rad=rad)
        """
        width = Angle(width)
        rad = Angle(rad)

        if shape == "disk":
            amplitude = 1 / (np.pi * width.radian**2)
            psf_value = np.where(rad < width, amplitude, 0)
        elif shape == "gauss":
            gauss2d_pdf = Gauss2DPDF(sigma=width.radian)
            psf_value = gauss2d_pdf(rad.radian)
        else:
            raise ValueError("Invalid shape: {}".format(shape))

        psf_value = u.Quantity(psf_value, "sr^-1")

        return cls(rad, psf_value)
Ejemplo n.º 12
0
    def from_gauss(cls, energy_axis_true, rad_axis=None, sigma=0.1 * u.deg):
        """Create all -sky PSF map from Gaussian width.

        This is used for testing and examples.

        The width can be the same for all energies
        or be an array with one value per energy node.
        It does not depend on position.

        Parameters
        ----------
        energy_axis_true : `~gammapy.maps.MapAxis`
            True energy axis.
        rad_axis : `~gammapy.maps.MapAxis`
            Offset angle wrt source position axis.
        sigma : `~astropy.coordinates.Angle`
            Gaussian width.

        Returns
        -------
        psf_map : `PSFMap`
            Point spread function map.
        """
        from gammapy.datasets.map import RAD_AXIS_DEFAULT

        if rad_axis is None:
            rad_axis = RAD_AXIS_DEFAULT.copy()

        axes = MapAxes([energy_axis_true, rad_axis])
        coords = axes.get_coord()

        sigma = np.broadcast_to(u.Quantity(sigma),
                                energy_axis_true.nbin,
                                subok=True)
        gauss = Gauss2DPDF(sigma=sigma.reshape((-1, 1)))
        data = gauss(coords["rad"])

        table_psf = EnergyDependentTablePSF(axes=axes,
                                            unit=data.unit,
                                            data=data.value)
        return cls.from_energy_dependent_table_psf(table_psf)
Ejemplo n.º 13
0
 def test_gauss_convolve(self):
     g = Gauss2DPDF(sigma=3 * u.deg).gauss_convolve(sigma=4 * u.deg)
     assert_allclose(g.sigma, 5 * u.deg)
Ejemplo n.º 14
0
 def setup(self):
     self.gs = [
         Gauss2DPDF(0.1 * u.deg),
         Gauss2DPDF(1 * u.deg),
         Gauss2DPDF(1 * u.deg),
     ]
Ejemplo n.º 15
0
 def test_gauss_convolve(self):
     g = Gauss2DPDF(sigma=3).gauss_convolve(sigma=4)
     assert_equal(g.sigma, 5)
Ejemplo n.º 16
0
 def setup(self):
     self.gs = [Gauss2DPDF(0.1), Gauss2DPDF(1), Gauss2DPDF(1)]