Пример #1
0
def test_psf_map_from_gauss():
    energy_axis = MapAxis.from_nodes(
        [1, 3, 10], name="energy_true", interp="log", unit="TeV"
    )
    rad = np.linspace(0, 1.5, 100) * u.deg
    rad_axis = MapAxis.from_nodes(rad, name="rad", unit="deg")

    # define sigmas starting at 0.1 in steps of 0.1 deg
    sigma = [0.1, 0.2, 0.4] * u.deg

    # with energy-dependent sigma
    psfmap = PSFMap.from_gauss(energy_axis, rad_axis, sigma)

    assert psfmap.psf_map.geom.axes[0] == rad_axis
    assert psfmap.psf_map.geom.axes[1] == energy_axis
    assert psfmap.exposure_map.geom.axes["rad"].nbin == 1
    assert psfmap.exposure_map.geom.axes["energy_true"] == psfmap.psf_map.geom.axes[1]
    assert psfmap.psf_map.unit == "sr-1"
    assert psfmap.psf_map.data.shape == (3, 100, 1, 2)

    radius = psfmap.containment_radius(fraction=0.394, energy_true=[1, 3, 10] * u.TeV)
    assert_allclose(radius, sigma, rtol=0.01)

    # test that it won't work with different number of sigmas and energies
    with pytest.raises(ValueError):
        PSFMap.from_gauss(energy_axis, rad_axis, sigma=[1, 2] * u.deg)
Пример #2
0
def test_psfmap_from_gauss():
    rad = np.linspace(0, 1.5, 100) * u.deg
    energy = np.logspace(-1, 2, 10) * u.TeV
    energy_axis = MapAxis.from_nodes(energy,
                                     name="energy_true",
                                     interp="log",
                                     unit="TeV")
    rad_axis = MapAxis.from_nodes(rad, name="rad", unit="deg")

    # define sigmas starting at 0.1 in steps of 0.1 deg
    sigma = (np.arange(energy.shape[0]) * 0.1 + 0.1) * u.deg

    # with energy-dependent sigma
    psfmap = PSFMap.from_gauss(energy_axis, rad_axis, sigma)
    assert psfmap.psf_map.geom.axes[0] == rad_axis
    assert psfmap.psf_map.geom.axes[1] == energy_axis
    assert psfmap.psf_map.unit == Unit("sr-1")
    assert psfmap.psf_map.data.shape == (energy.shape[0], rad.shape[0], 1, 2)
    assert_allclose(
        psfmap.get_energy_dependent_table_psf().containment_radius(1 *
                                                                   u.TeV)[0],
        psfmap.containment_radius_map(1 * u.TeV).data[0][0] * u.deg,
    )
    assert_allclose(
        psfmap.containment_radius_map(energy[3], 0.68).data[0][0] /
        sigma[3].value,
        1.51,
        atol=1e-2,
    )
    assert_allclose(
        psfmap.containment_radius_map(energy[3], 0.95).data[0][0] /
        sigma[3].value,
        2.45,
        atol=1e-2,
    )

    # with constant sigma
    psfmap1 = PSFMap.from_gauss(energy_axis, rad_axis, sigma[0])
    assert psfmap1.psf_map.geom.axes[0] == rad_axis
    assert psfmap1.psf_map.geom.axes[1] == energy_axis
    assert psfmap1.psf_map.unit == Unit("sr-1")
    assert psfmap1.psf_map.data.shape == (energy.shape[0], rad.shape[0], 1, 2)
    assert_allclose(
        psfmap1.get_energy_dependent_table_psf().containment_radius(1 *
                                                                    u.TeV)[0],
        psfmap1.containment_radius_map(1 * u.TeV).data[0][0] * u.deg,
    )

    # check that the PSF with the same sigma is the same
    psfvalue = psfmap.get_energy_dependent_table_psf().data.data[0]
    psfvalue1 = psfmap1.get_energy_dependent_table_psf().data.data[0]
    assert_allclose(psfvalue, psfvalue1, atol=1e-7)

    # test that it won't work with different number of sigmas and energies
    with pytest.raises(AssertionError):
        psfmap2 = PSFMap.from_gauss(energy_axis, rad_axis, sigma[:3])
Пример #3
0
def get_dataset():
    counts = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-counts-cube.fits.gz")
    background = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-background-cube.fits.gz")

    exposure = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-exposure-cube.fits.gz")

    # for some reason the WCS defintions are not aligned...
    exposure.geom._wcs = counts.geom.wcs

    psf = PSFMap.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-psf-cube.fits.gz",
        format="gtpsf")

    # reduce size of the PSF
    psf = psf.slice_by_idx(slices={"rad": slice(0, 130)})

    edisp = EDispKernelMap.from_diagonal_response(
        energy_axis=counts.geom.axes["energy"],
        energy_axis_true=exposure.geom.axes["energy_true"],
        geom=psf.psf_map.geom)

    mask_safe = counts.geom.boundary_mask(width="0.2 deg")

    return MapDataset(counts=counts,
                      background=background,
                      exposure=exposure,
                      psf=psf,
                      name="fermi-3fhl-gc",
                      edisp=edisp,
                      mask_safe=mask_safe)
Пример #4
0
    def make_psf(self, geom, observation):
        """Make psf map.

        Parameters
        ----------
        geom : `~gammapy.maps.Geom`
            Reference geom.
        observation : `~gammapy.data.Observation`
            Observation container.

        Returns
        -------
        psf : `~gammapy.irf.PSFMap`
            Psf map.
        """
        psf = observation.psf

        if isinstance(psf, PSFMap):
            return PSFMap(psf.psf_map.interp_to_geom(geom))

        exposure = self.make_exposure_irf(geom.squash(axis_name="rad"), observation)

        return make_psf_map(
            psf=psf,
            pointing=observation.pointing_radec,
            geom=geom,
            exposure_map=exposure,
        )
Пример #5
0
def test_convolve_full(region):
    energy = MapAxis.from_bounds(1,
                                 100,
                                 unit='TeV',
                                 nbin=2,
                                 name='energy_true')
    nside = 256

    all_sky_geom = HpxGeom(nside=nside,
                           axes=[energy],
                           region=region,
                           nest=False,
                           frame='icrs')

    all_sky_map = Map.from_geom(all_sky_geom)
    all_sky_map.set_by_coord((0, 0, [2, 90]), 1)
    all_sky_map.set_by_coord((10, 10, [2, 90]), 1)
    all_sky_map.set_by_coord((30, 30, [2, 90]), 1)
    all_sky_map.set_by_coord((-40, -40, [2, 90]), 1)
    all_sky_map.set_by_coord((60, 0, [2, 90]), 1)
    all_sky_map.set_by_coord((-45, 30, [2, 90]), 1)
    all_sky_map.set_by_coord((30, -45, [2, 90]), 1)

    wcs_geom = WcsGeom.create(width=5, binsz=0.05, axes=[energy])
    psf = PSFMap.from_gauss(energy_axis_true=energy, sigma=[0.5, 0.6] * u.deg)

    kernel = psf.get_psf_kernel(geom=wcs_geom, max_radius=1 * u.deg)
    convolved_map = all_sky_map.convolve_full(kernel)
    assert_allclose(convolved_map.data.sum(), 14, rtol=1e-5)
Пример #6
0
def test_convolve_nd():
    energy_axis = MapAxis.from_edges(
        np.logspace(-1.0, 1.0, 4), unit="TeV", name="energy_true"
    )
    geom = WcsGeom.create(binsz=0.02 * u.deg, width=4.0 * u.deg, axes=[energy_axis])
    m = Map.from_geom(geom)
    m.fill_by_coord([[0.2, 0.4], [-0.1, 0.6], [0.5, 3.6]])

    psf = PSFMap.from_gauss(energy_axis, sigma=[0.1, 0.2, 0.3] * u.deg)
    psf_kernel = psf.get_psf_kernel(geom=geom, max_radius=1 * u.deg)

    assert psf_kernel.psf_kernel_map.data.shape == (3, 101, 101)

    mc = m.convolve(psf_kernel)
    assert_allclose(mc.data.sum(axis=(1, 2)), [0, 1, 1], atol=1e-5)

    kernel_2d = Box2DKernel(3, mode="center")
    kernel_2d.normalize("peak")
    mc = m.convolve(kernel_2d.array)
    assert_allclose(mc.data[0, :, :].sum(), 0, atol=1e-5)
    assert_allclose(mc.data[1, :, :].sum(), 9, atol=1e-5)

    kernel_2d = Gaussian2DKernel(15, mode="center")
    kernel_2d.normalize("peak")
    mc_full = m.convolve(kernel_2d.array, mode="full")
    mc_same = m.convolve(kernel_2d.array, mode="same")
    coords = [[0.2, 0.1, 0.4, 0.44, -1.3], [-0.1, -0.13, 0.6, 0.57, 0.91], [0.5, 0.5, 3.6, 3.6, 0.5]]
    values_full = mc_full.get_by_coord(coords)
    values_same = mc_same.get_by_coord(coords)

    assert mc_same.data.shape == (3, 200, 200)
    assert mc_full.data.shape == (3, 320, 320)
    assert_allclose(values_full, values_same, rtol=1e-5)
Пример #7
0
def fermi_dataset():
    size = Angle("3 deg", "3.5 deg")
    counts = Map.read("$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-counts-cube.fits.gz")
    counts = counts.cutout(counts.geom.center_skydir, size)

    background = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-background-cube.fits.gz"
    )
    background = background.cutout(background.geom.center_skydir, size)
    background = BackgroundModel(background, datasets_names=["fermi-3fhl-gc"])

    exposure = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-exposure-cube.fits.gz"
    )
    exposure = exposure.cutout(exposure.geom.center_skydir, size)
    exposure.unit = "cm2s"
    mask_safe = counts.copy(data=np.ones_like(counts.data).astype("bool"))

    psf = EnergyDependentTablePSF.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-psf-cube.fits.gz"
    )
    psfmap = PSFMap.from_energy_dependent_table_psf(psf)

    dataset = MapDataset(
        counts=counts,
        models=[background],
        exposure=exposure,
        mask_safe=mask_safe,
        psf=psfmap,
        name="fermi-3fhl-gc",
    )
    dataset = dataset.to_image()

    return dataset
Пример #8
0
def fermi_dataset():
    size = Angle("3 deg", "3.5 deg")
    counts = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-counts-cube.fits.gz")
    counts = counts.cutout(counts.geom.center_skydir, size)

    background = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-background-cube.fits.gz")
    background = background.cutout(background.geom.center_skydir, size)
    background = BackgroundModel(background, datasets_names=["fermi-3fhl-gc"])

    exposure = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-exposure-cube.fits.gz")
    exposure = exposure.cutout(exposure.geom.center_skydir, size)
    exposure.unit = "cm2 s"

    psf = EnergyDependentTablePSF.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-psf-cube.fits.gz")
    psfmap = PSFMap.from_energy_dependent_table_psf(psf)
    edisp = EDispKernelMap.from_diagonal_response(
        energy_axis=counts.geom.axes["energy"],
        energy_axis_true=exposure.geom.axes["energy_true"],
    )

    return MapDataset(
        counts=counts,
        models=[background],
        exposure=exposure,
        psf=psfmap,
        name="fermi-3fhl-gc",
        edisp=edisp,
    )
Пример #9
0
def test_psfmap_read_write(tmp_path):
    psfmap = make_test_psfmap(0.15 * u.deg)

    psfmap.write(tmp_path / "tmp.fits")
    new_psfmap = PSFMap.read(tmp_path / "tmp.fits")

    assert_allclose(psfmap.psf_map.quantity, new_psfmap.psf_map.quantity)
Пример #10
0
def test_significance_map_estimator_map_dataset(simple_dataset):
    estimator = ExcessMapEstimator(0.1 * u.deg, selection_optional=["all"])
    result = estimator.run(simple_dataset)

    assert_allclose(result["counts"].data[0, 10, 10], 162)
    assert_allclose(result["excess"].data[0, 10, 10], 81)
    assert_allclose(result["background"].data[0, 10, 10], 81)
    assert_allclose(result["sqrt_ts"].data[0, 10, 10], 7.910732, atol=1e-5)
    assert_allclose(result["err"].data[0, 10, 10], 12.727922, atol=1e-3)
    assert_allclose(result["errp"].data[0, 10, 10], 13.063328, atol=1e-3)
    assert_allclose(result["errn"].data[0, 10, 10], -12.396716, atol=1e-3)
    assert_allclose(result["ul"].data[0, 10, 10], 107.806275, atol=1e-3)

    simple_dataset.exposure += 1e10 * u.cm**2 * u.s
    axis = simple_dataset.exposure.geom.axes[0]
    simple_dataset.psf = PSFMap.from_gauss(axis, sigma="0.05 deg")

    model = SkyModel(
        PowerLawSpectralModel(amplitude="1e-9 cm-2 s-1 TeV-1"),
        GaussianSpatialModel(lat_0=0.0 * u.deg,
                             lon_0=0.0 * u.deg,
                             sigma=0.1 * u.deg,
                             frame="icrs"),
        name="sky_model",
    )

    simple_dataset.models = [model]
    simple_dataset.npred()

    estimator = ExcessMapEstimator(0.1 * u.deg, selection_optional="all")
    result = estimator.run(simple_dataset)

    assert_allclose(result["excess"].data.sum(), 19733.602, rtol=1e-3)
    assert_allclose(result["background"].data.sum(), 31818.398, rtol=1e-3)
    assert_allclose(result["sqrt_ts"].data[0, 10, 10], 4.217129, rtol=1e-3)
Пример #11
0
def test_npred_psf_after_edisp():
    energy_axis = MapAxis.from_energy_bounds("1 TeV", "10 TeV", nbin=3)
    energy_axis_true = MapAxis.from_energy_bounds(
        "0.8 TeV", "15 TeV", nbin=6, name="energy_true"
    )

    geom = WcsGeom.create(width=4 * u.deg, binsz=0.02, axes=[energy_axis])
    dataset = MapDataset.create(geom=geom, energy_axis_true=energy_axis_true)
    dataset.background.data += 1
    dataset.exposure.data += 1e12
    dataset.mask_safe.data += True
    dataset.psf = PSFMap.from_gauss(
        energy_axis_true=energy_axis_true, sigma=0.2 * u.deg
    )

    model = SkyModel(
        spectral_model=PowerLawSpectralModel(),
        spatial_model=PointSpatialModel(),
        name="test-model",
    )

    model.apply_irf["psf_after_edisp"] = True

    bkg_model = FoVBackgroundModel(dataset_name=dataset.name)
    dataset.models = [bkg_model, model]

    npred = dataset.npred()
    assert_allclose(npred.data.sum(), 129553.858658)
Пример #12
0
def fermi_dataset():
    size = Angle("3 deg", "3.5 deg")
    counts = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-counts-cube.fits.gz")
    counts = counts.cutout(counts.geom.center_skydir, size)

    background = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-background-cube.fits.gz")
    background = background.cutout(background.geom.center_skydir, size)

    exposure = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-exposure-cube.fits.gz")
    exposure = exposure.cutout(exposure.geom.center_skydir, size)

    psfmap = PSFMap.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-psf-cube.fits.gz",
        format="gtpsf")
    edisp = EDispKernelMap.from_diagonal_response(
        energy_axis=counts.geom.axes["energy"],
        energy_axis_true=exposure.geom.axes["energy_true"],
    )

    return MapDataset(
        counts=counts,
        background=background,
        exposure=exposure,
        psf=psfmap,
        name="fermi-3fhl-gc",
        edisp=edisp,
    )
Пример #13
0
def data_prep():
    counts = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-counts-cube.fits.gz")
    background = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-background-cube.fits.gz")

    exposure = Map.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-exposure-cube.fits.gz")
    # unit is not properly stored on the file. We add it manually
    exposure = Map.from_geom(exposure.geom, data=exposure.data, unit="cm2s")

    psfmap = PSFMap.read(
        "$GAMMAPY_DATA/fermi-3fhl-gc/fermi-3fhl-gc-psf-cube.fits.gz",
        format="gtpsf")

    edisp = EDispKernelMap.from_diagonal_response(
        energy_axis=counts.geom.axes["energy"],
        energy_axis_true=exposure.geom.axes["energy_true"],
    )

    dataset = MapDataset(
        counts=counts,
        background=background,
        exposure=exposure,
        psf=psfmap,
        name="fermi-3fhl-gc",
        edisp=edisp,
    )
    return dataset
Пример #14
0
def test_psf_map_read(position):
    position = SkyCoord(position)
    filename = "$GAMMAPY_DATA/fermi_3fhl/fermi_3fhl_psf_gc.fits.gz"
    psf = PSFMap.read(filename, format="gtpsf")

    value = psf.containment(position=position, energy_true=100 * u.GeV, rad=0.1 * u.deg)

    assert_allclose(value, 0.682022, rtol=1e-5)
    assert psf.psf_map.unit == "sr-1"
Пример #15
0
def get_psf():
    filename = (
        "$GAMMAPY_DATA/cta-1dc/caldb/data/cta/1dc/bcf/South_z20_50h/irf_file.fits"
    )
    psf = EnergyDependentMultiGaussPSF.read(filename, hdu="POINT SPREAD FUNCTION")

    table_psf = psf.to_energy_dependent_table_psf(theta=0.5 * u.deg)
    psf_map = PSFMap.from_energy_dependent_table_psf(table_psf)
    return psf_map
Пример #16
0
def test_psf_map_write_gtpsf(tmpdir):
    energy_axis_true = MapAxis.from_energy_bounds(
        "1 TeV", "10 TeV", nbin=3, name="energy_true"
    )
    geom = RegionGeom.create("icrs;circle(0, 0, 0.1)")
    psf = PSFMap.from_gauss(
        energy_axis_true=energy_axis_true, sigma=[0.1, 0.2, 0.3] * u.deg, geom=geom
    )
    psf.exposure_map = Map.from_geom(geom.to_cube([energy_axis_true]), unit="cm2 s")

    filename = tmpdir / "test_psf.fits"
    psf.write(filename, format="gtpsf")

    psf = PSFMap.read(filename, format="gtpsf")

    value = psf.containment_radius(energy_true=energy_axis_true.center, fraction=0.394)

    assert_allclose(value, [0.1, 0.2, 0.3] * u.deg, rtol=1e-5)
    assert psf.psf_map.unit == "sr-1"
Пример #17
0
 def __init__(
     self,
     evt_file="../data/joint-crab/fermi/events.fits.gz",
     exp_file="../data/joint-crab/fermi/exposure_cube.fits.gz",
     psf_file="../data/joint-crab/fermi/psf.fits.gz",
 ):
     # Read data
     self.events = EventList.read(evt_file)
     self.exposure = HpxNDMap.read(exp_file)
     self.exposure.unit = u.Unit("cm2s")  # no unit stored on map...
     self.psf = PSFMap.read(psf_file, format="gtpsf")
Пример #18
0
def test_psf_containment_coords():
    # regression test to check the cooordinate conversion for PSFMap.containment
    psf = PSFMap.read("$GAMMAPY_DATA/cta-1dc-gc/cta-1dc-gc.fits.gz", hdu="PSF")

    position = SkyCoord("266.415d", "-29.006d", frame="icrs")

    radius = psf.containment_radius(energy_true=1 * u.TeV,
                                    fraction=0.99,
                                    position=position)

    assert_allclose(radius, 0.10575 * u.deg, rtol=1e-5)
Пример #19
0
def test_psfmap_to_from_hdulist():
    psfmap = make_test_psfmap(0.15 * u.deg)
    hdulist = psfmap.to_hdulist(psf_hdu="PSF", psf_hdubands="BANDS")
    assert "PSF" in hdulist
    assert "BANDS" in hdulist
    assert "EXPMAP" in hdulist
    assert "BANDSEXP" in hdulist

    new_psfmap = PSFMap.from_hdulist(hdulist, psf_hdu="PSF", psf_hdubands="BANDS")
    assert_allclose(psfmap.psf_map.data, new_psfmap.psf_map.data)
    assert new_psfmap.psf_map.geom == psfmap.psf_map.geom
    assert new_psfmap.exposure_map.geom == psfmap.exposure_map.geom
Пример #20
0
def test_psfmap_to_from_hdulist():
    psfmap = make_test_psfmap(0.15 * u.deg)
    hdulist = psfmap.to_hdulist()
    assert "PSF" in hdulist
    assert "PSF_BANDS" in hdulist
    assert "PSF_EXPOSURE" in hdulist
    assert "PSF_EXPOSURE_BANDS" in hdulist

    new_psfmap = PSFMap.from_hdulist(hdulist)
    assert_allclose(psfmap.psf_map.data, new_psfmap.psf_map.data)
    assert new_psfmap.psf_map.geom == psfmap.psf_map.geom
    assert new_psfmap.exposure_map.geom == psfmap.exposure_map.geom
Пример #21
0
def test_psf_map_from_table_psf(position):
    position = SkyCoord(position)
    filename = "$GAMMAPY_DATA/fermi_3fhl/fermi_3fhl_psf_gc.fits.gz"
    table_psf = EnergyDependentTablePSF.read(filename)
    psf_map = PSFMap.from_energy_dependent_table_psf(table_psf)

    table_psf_new = psf_map.get_energy_dependent_table_psf(position)

    assert_allclose(table_psf_new.data.data, table_psf.data.data)
    assert table_psf_new.data.data.unit == "sr-1"

    assert_allclose(table_psf_new.exposure.value, table_psf.exposure.value)
    assert table_psf_new.exposure.unit == "cm2 s"
Пример #22
0
def make_psf_map(psf, pointing, geom, exposure_map=None):
    """Make a psf map for a single observation

    Expected axes : rad and true energy in this specific order
    The name of the rad MapAxis is expected to be 'rad'

    Parameters
    ----------
    psf : `~gammapy.irf.PSF3D`
        the PSF IRF
    pointing : `~astropy.coordinates.SkyCoord`
        the pointing direction
    geom : `~gammapy.maps.Geom`
        the map geom to be used. It provides the target geometry.
        rad and true energy axes should be given in this specific order.
    exposure_map : `~gammapy.maps.Map`, optional
        the associated exposure map.
        default is None

    Returns
    -------
    psfmap : `~gammapy.cube.PSFMap`
        the resulting PSF map
    """
    energy_axis = geom.get_axis_by_name("energy_true")
    energy = energy_axis.center

    rad_axis = geom.get_axis_by_name("theta")
    rad = rad_axis.center

    # Compute separations with pointing position
    offset = geom.separation(pointing)

    # Compute PSF values
    # TODO: allow broadcasting in PSF3D.evaluate()
    psf_values = psf._interpolate(
        (
            rad[:, np.newaxis, np.newaxis],
            offset,
            energy[:, np.newaxis, np.newaxis, np.newaxis],
        )
    )

    # TODO: this probably does not ensure that probability is properly normalized in the PSFMap
    # Create Map and fill relevant entries
    data = psf_values.to_value("sr-1")
    psfmap = Map.from_geom(geom, data=data, unit="sr-1")
    return PSFMap(psfmap, exposure_map)
Пример #23
0
def test_psf_map_from_gauss_const_sigma():
    energy_axis = MapAxis.from_nodes(
        [1, 3, 10], name="energy_true", interp="log", unit="TeV"
    )
    rad = np.linspace(0, 1.5, 100) * u.deg
    rad_axis = MapAxis.from_nodes(rad, name="rad", unit="deg")

    # with constant sigma
    psfmap = PSFMap.from_gauss(energy_axis, rad_axis, sigma=0.1 * u.deg)
    assert psfmap.psf_map.geom.axes[0] == rad_axis
    assert psfmap.psf_map.geom.axes[1] == energy_axis
    assert psfmap.psf_map.unit == Unit("sr-1")
    assert psfmap.psf_map.data.shape == (3, 100, 1, 2)

    radius = psfmap.containment_radius(energy_true=[1, 3, 10] * u.TeV, fraction=0.394)
    assert_allclose(radius, 0.1 * u.deg, rtol=0.01)
Пример #24
0
def make_psf_map(psf, pointing, geom, exposure_map=None):
    """Make a psf map for a single observation

    Expected axes : rad and true energy in this specific order
    The name of the rad MapAxis is expected to be 'rad'

    Parameters
    ----------
    psf : `~gammapy.irf.PSF3D`
        the PSF IRF
    pointing : `~astropy.coordinates.SkyCoord`
        the pointing direction
    geom : `~gammapy.maps.Geom`
        the map geom to be used. It provides the target geometry.
        rad and true energy axes should be given in this specific order.
    exposure_map : `~gammapy.maps.Map`, optional
        the associated exposure map.
        default is None
    use_region_center: bool
        If geom is a RegionGeom, whether to just
        consider the values at the region center
        or the insted the average over the whole region

    Returns
    -------
    psfmap : `~gammapy.irf.PSFMap`
        the resulting PSF map
    """
    energy_true = geom.axes["energy_true"].center
    rad = geom.axes["rad"].center

    # Compute separations with pointing position
    offset = geom.separation(pointing)

    # Compute PSF values
    psf_values = psf.evaluate(
        energy_true=energy_true[:, np.newaxis, np.newaxis, np.newaxis],
        offset=offset,
        rad=rad[:, np.newaxis, np.newaxis],
    )

    # TODO: this probably does not ensure that probability is properly normalized in the PSFMap
    # Create Map and fill relevant entries
    data = psf_values.to_value("sr-1")
    psfmap = Map.from_geom(geom, data=data, unit="sr-1")
    return PSFMap(psfmap, exposure_map)
Пример #25
0
def fake_dataset():
    axis = MapAxis.from_energy_bounds(0.1, 10, 5, unit="TeV", name="energy")
    axis_true = MapAxis.from_energy_bounds(0.05, 20, 10, unit="TeV", name="energy_true")

    geom = WcsGeom.create(npix=50, binsz=0.02, axes=[axis])
    dataset = MapDataset.create(geom)
    dataset.psf = PSFMap.from_gauss(axis_true, sigma="0.05 deg")
    dataset.mask_safe += np.ones(dataset.data_shape, dtype=bool)
    dataset.background += 1
    dataset.exposure += 1e12 * u.cm ** 2 * u.s

    spatial_model = PointSpatialModel()
    spectral_model = PowerLawSpectralModel(amplitude="1e-10 cm-2s-1TeV-1", index=2)
    model = SkyModel(
        spatial_model=spatial_model, spectral_model=spectral_model, name="source"
    )
    dataset.models = [model]
    dataset.fake(random_state=42)
    return dataset
Пример #26
0
def prepare_dataset():
    energy = MapAxis.from_energy_bounds(0.1,
                                        100,
                                        5,
                                        per_decade=True,
                                        unit="TeV")
    energy_true = MapAxis.from_energy_bounds(0.1,
                                             100,
                                             5,
                                             unit="TeV",
                                             per_decade=True,
                                             name="energy_true")
    geom = WcsGeom.create(npix=500, binsz=0.01, axes=[energy])

    dataset = MapDataset.create(geom, energy_axis_true=energy_true)

    dataset.exposure += "1 m2 s"
    dataset.psf = PSFMap.from_gauss(energy_true)
    dataset.edisp = EDispKernelMap.from_gauss(energy, energy_true, 0.1, 0.)

    return Datasets([dataset])
Пример #27
0
def make_psf_map(psf, pointing, geom, exposure_map=None):
    """Make a psf map for a single observation

    Expected axes : rad and true energy in this specific order
    The name of the rad MapAxis is expected to be 'rad'

    Parameters
    ----------
    psf : `~gammapy.irf.PSF3D`
        the PSF IRF
    pointing : `~astropy.coordinates.SkyCoord`
        the pointing direction
    geom : `~gammapy.maps.Geom`
        the map geom to be used. It provides the target geometry.
        rad and true energy axes should be given in this specific order.
    exposure_map : `~gammapy.maps.Map`, optional
        the associated exposure map.
        default is None

    Returns
    -------
    psfmap : `~gammapy.irf.PSFMap`
        the resulting PSF map
    """
    coords = geom.get_coord(sparse=True)

    # Compute separations with pointing position
    offset = coords.skycoord.separation(pointing)

    # Compute PSF values
    data = psf.evaluate(
        energy_true=coords["energy_true"],
        offset=offset,
        rad=coords["rad"],
    )

    # Create Map and fill relevant entries
    psf_map = Map.from_geom(geom, data=data.value, unit=data.unit)
    psf_map.normalize(axis_name="rad")
    return PSFMap(psf_map, exposure_map)
Пример #28
0
def test_significance_map_estimator_map_dataset_exposure(simple_dataset):
    simple_dataset.exposure += 1e10 * u.cm**2 * u.s
    axis = simple_dataset.exposure.geom.axes[0]
    simple_dataset.psf = PSFMap.from_gauss(axis, sigma="0.05 deg")

    model = SkyModel(
        PowerLawSpectralModel(amplitude="1e-9 cm-2 s-1 TeV-1"),
        GaussianSpatialModel(lat_0=0.0 * u.deg,
                             lon_0=0.0 * u.deg,
                             sigma=0.1 * u.deg,
                             frame="icrs"),
        name="sky_model",
    )

    simple_dataset.models = [model]
    simple_dataset.npred()

    estimator = ExcessMapEstimator(0.1 * u.deg, selection_optional="all")
    result = estimator.run(simple_dataset)

    assert_allclose(result["npred_excess"].data.sum(), 19733.602, rtol=1e-3)
    assert_allclose(result["sqrt_ts"].data[0, 10, 10], 4.217129, rtol=1e-3)
Пример #29
0
"""Plot Fermi PSF."""
from gammapy.irf import PSFMap
from gammapy.maps import MapAxis, WcsGeom

filename = "$GAMMAPY_DATA/fermi_3fhl/fermi_3fhl_psf_gc.fits.gz"
psf = PSFMap.read(filename, format="gtpsf")

axis = MapAxis.from_energy_bounds("10 GeV", "2 TeV", nbin=20, name="energy_true")
geom = WcsGeom.create(npix=50, binsz=0.01, axes=[axis])

# .to_image() computes the exposure weighted mean PSF
kernel = psf.get_psf_kernel(geom=geom).to_image()

kernel.psf_kernel_map.plot()
Пример #30
0
def test_interpolate_map_dataset():
    energy = MapAxis.from_energy_bounds("1 TeV", "300 TeV", nbin=5, name="energy")
    energy_true = MapAxis.from_nodes(np.logspace(-1, 3, 20), name="energy_true", interp="log", unit="TeV")

    # make dummy map IRFs
    geom_allsky = WcsGeom.create(npix=(5, 3), proj="CAR", binsz=60, axes=[energy], skydir=(0, 0))
    geom_allsky_true = geom_allsky.drop('energy').to_cube([energy_true])

    #background
    value = 30
    bkg_map = Map.from_geom(geom_allsky, unit="")
    bkg_map.data = value*np.ones(bkg_map.data.shape)

    #effective area - with a gradient that also depends on energy
    aeff_map = Map.from_geom(geom_allsky_true, unit="cm2 s")
    ra_arr = np.arange(aeff_map.data.shape[1])
    dec_arr = np.arange(aeff_map.data.shape[2])
    for i in np.arange(aeff_map.data.shape[0]):
        aeff_map.data[i, :, :] = (i+1)*10*np.meshgrid(dec_arr, ra_arr)[0]+10*np.meshgrid(dec_arr, ra_arr)[1]+10
    aeff_map.meta["TELESCOP"] = "HAWC"

    #psf map
    width = 0.2*u.deg
    rad_axis = MapAxis.from_nodes(np.linspace(0, 2, 50), name="rad", unit="deg")
    psfMap = PSFMap.from_gauss(energy_true, rad_axis, width)

    #edispmap
    edispmap = EDispKernelMap.from_gauss(energy, energy_true, sigma=0.1, bias=0.0, geom=geom_allsky)

    #events and gti
    nr_ev = 10
    ev_t = Table()
    gti_t = Table()

    ev_t['EVENT_ID'] = np.arange(nr_ev)
    ev_t['TIME'] = nr_ev*[Time('2011-01-01 00:00:00', scale='utc', format='iso')]
    ev_t['RA'] = np.linspace(-1, 1, nr_ev)*u.deg
    ev_t['DEC'] = np.linspace(-1, 1, nr_ev)*u.deg
    ev_t['ENERGY'] = np.logspace(0, 2, nr_ev)*u.TeV

    gti_t['START'] = [Time('2010-12-31 00:00:00', scale='utc', format='iso')]
    gti_t['STOP'] = [Time('2011-01-02 00:00:00', scale='utc', format='iso')]

    events = EventList(ev_t)
    gti = GTI(gti_t)

    #define observation
    obs = Observation(
        obs_id=0,
        obs_info={},
        gti=gti,
        aeff=aeff_map,
        edisp=edispmap,
        psf=psfMap,
        bkg=bkg_map,
        events=events,
        obs_filter=None,
    )

    #define analysis geometry
    geom_target = WcsGeom.create(
        skydir=(0, 0),
        width=(10, 10),
        binsz=0.1*u.deg,
        axes=[energy]
    )

    maker = MapDatasetMaker(selection=["exposure", "counts", "background", "edisp", "psf"])
    dataset = MapDataset.create(geom=geom_target, energy_axis_true=energy_true, name="test")
    dataset = maker.run(dataset, obs)

    # test counts
    assert dataset.counts.data.sum() == nr_ev

    #test background
    coords_bg = {
        'skycoord' : SkyCoord("0 deg", "0 deg"),
        'energy' : energy.center[0]
    }
    assert_allclose(
        dataset.background_model.evaluate().get_by_coord(coords_bg)[0],
        value,
        atol=1e-7)

    #test effective area
    coords_aeff = {
        'skycoord' : SkyCoord("0 deg", "0 deg"),
        'energy_true' : energy_true.center[0]
    }
    assert_allclose(
        aeff_map.get_by_coord(coords_aeff)[0]/dataset.exposure.get_by_coord(coords_aeff)[0],
        1,
        atol=1e-3)

    #test edispmap
    pdfmatrix_preinterp = edispmap.get_edisp_kernel(SkyCoord("0 deg", "0 deg")).pdf_matrix
    pdfmatrix_postinterp = dataset.edisp.get_edisp_kernel(SkyCoord("0 deg", "0 deg")).pdf_matrix
    assert_allclose(pdfmatrix_preinterp, pdfmatrix_postinterp, atol=1e-7)

    #test psfmap
    geom_psf = geom_target.drop('energy').to_cube([energy_true])
    psfkernel_preinterp = psfMap.get_psf_kernel(SkyCoord("0 deg", "0 deg"), geom_psf, max_radius=2*u.deg).data
    psfkernel_postinterp = dataset.psf.get_psf_kernel(SkyCoord("0 deg", "0 deg"), geom_psf, max_radius=2*u.deg).data
    assert_allclose(psfkernel_preinterp, psfkernel_postinterp, atol=1e-4)