示例#1
0
def test_psf_kernel_to_image():
    sigma1 = 0.5 * u.deg
    sigma2 = 0.2 * u.deg
    binsz = 0.1 * u.deg

    axis = MapAxis.from_energy_bounds(1, 10, 2, unit="TeV", name="energy_true")
    geom = WcsGeom.create(binsz=binsz, npix=50, axes=[axis])

    rad = Angle(np.linspace(0.0, 1.5 * sigma1.to("deg").value, 100), "deg")
    table_psf1 = TablePSF.from_shape(shape="disk", width=sigma1, rad=rad)
    table_psf2 = TablePSF.from_shape(shape="disk", width=sigma2, rad=rad)

    kernel1 = PSFKernel.from_table_psf(table_psf1, geom)
    kernel2 = PSFKernel.from_table_psf(table_psf2, geom)

    kernel1.psf_kernel_map.data[1, :, :] = kernel2.psf_kernel_map.data[1, :, :]

    kernel_image_1 = kernel1.to_image()
    kernel_image_2 = kernel1.to_image(exposure=[1, 2])

    assert_allclose(kernel_image_1.psf_kernel_map.data.sum(), 1.0, atol=1e-5)
    assert_allclose(kernel_image_1.psf_kernel_map.data[0, 25, 25],
                    0.028415,
                    atol=1e-5)
    assert_allclose(kernel_image_1.psf_kernel_map.data[0, 22, 22],
                    0.009806,
                    atol=1e-5)
    assert_allclose(kernel_image_1.psf_kernel_map.data[0, 20, 20],
                    0.0,
                    atol=1e-5)

    assert_allclose(kernel_image_2.psf_kernel_map.data.sum(), 1.0, atol=1e-5)
    assert_allclose(kernel_image_2.psf_kernel_map.data[0, 25, 25],
                    0.03791383,
                    atol=1e-5)
    assert_allclose(kernel_image_2.psf_kernel_map.data[0, 22, 22],
                    0.0079069,
                    atol=1e-5)
    assert_allclose(kernel_image_2.psf_kernel_map.data[0, 20, 20],
                    0.0,
                    atol=1e-5)
示例#2
0
def make_psf_cube(image_size,
                  energy_cube,
                  source_name,
                  center_maps,
                  center,
                  ObsList,
                  outdir,
                  spectral_index=2.3):
    """
    Compute the mean psf for a set of observation for different energy bands
    Parameters
    ----------
    image_size:int, Total number of pixel of the 2D map
    energy: Tuple for the energy axis: (Emin,Emax,nbins)
    source_name: name of the source you want to compute the image
    center_maps: SkyCoord
            center of the images
    center: SkyCoord 
            position where we want to compute the psf
    ObsList: ObservationList to use to compute the psf (could be different that the data_store for G0p9 for the GC for example)
    outdir: directory where the fits image will go
    spectral_index: assumed spectral index to compute the psf

    Returns
    -------

    """
    ref_cube = make_empty_cube(image_size, energy_cube, center_maps)
    header = ref_cube.sky_image_ref.to_image_hdu().header
    energy_bins = ref_cube.energies(mode="edges")
    for i_E, E in enumerate(energy_bins[0:-1]):
        energy_band = Energy(
            [energy_bins[i_E].value, energy_bins[i_E + 1].value],
            energy_bins.unit)
        energy = EnergyBounds.equal_log_spacing(energy_band[0].value,
                                                energy_band[1].value, 100,
                                                energy_band.unit)
        # Here all the observations have a center at less than 2 degrees from the Crab so it will be ok to estimate the mean psf on the Crab source postion (the area is define for offset equal to 2 degrees...)
        psf_energydependent = ObsList.make_mean_psf(center, energy, theta=None)
        try:
            psf_table = psf_energydependent.table_psf_in_energy_band(
                energy_band, spectral_index=spectral_index)
        except:
            psf_table = TablePSF(
                psf_energydependent.offset,
                Quantity(np.zeros(len(psf_energydependent.offset)), u.sr**-1))
        ref_cube.data[i_E, :, :] = fill_acceptance_image(
            header, center_maps, psf_table._offset.to("deg"),
            psf_table._dp_domega,
            psf_table._offset.to("deg")[-1]).data
    ref_cube.write(outdir + "/mean_psf_cube_" + source_name + ".fits",
                   format="fermi-counts")
示例#3
0
    def test_disk():
        width = Angle(2, "deg")
        rad = Angle(np.linspace(0, 2.3, 1000), "deg")
        psf = TablePSF.from_shape(shape="disk", width=width, rad=rad)

        # test containment
        radius = Angle(1, "deg")
        actual = psf.containment(radius)
        desired = (radius / width).to_value("")**2
        assert_allclose(actual, desired, rtol=1e-4)

        # test containment radius
        actual = psf.containment_radius(0.25).deg
        assert_allclose(actual, radius.deg, rtol=1e-4)
示例#4
0
    def test_gauss():
        # Make an example PSF for testing
        width = Angle(0.3, "deg")

        # containment radius for 80% containment
        radius = width * np.sqrt(2 * np.log(5))

        rad = Angle(np.linspace(0, 2.3, 1000), "deg")
        psf = TablePSF.from_shape(shape="gauss", width=width, rad=rad)

        assert_allclose(psf.containment(radius), 0.8, rtol=1e-4)

        desired = radius.to_value("deg")
        actual = psf.containment_radius(0.8).to_value("deg")
        assert_allclose(actual, desired, rtol=1e-4)
示例#5
0
def make_mean_psf_cube(image_size,
                       energy_cube,
                       center_maps,
                       center,
                       ObsList,
                       spectral_index=2.3):
    """
    Compute the mean psf for a set of observation for different energy bands
    Parameters
    ----------
    image_size:int, Total number of pixel of the 2D map
    energy: Tuple for the energy axis: (Emin,Emax,nbins)
    center_maps: SkyCoord
            center of the images
    center: SkyCoord 
            position where we want to compute the psf
    ObsList: ObservationList to use to compute the psf (could be different that the data_store for G0p9 for the GC for example)
    spectral_index: assumed spectral index to compute the psf

    Returns
    -------
    ref_cube : `~gammapy.cube.SkyCube`
             PSF mean cube

    """
    ref_cube = make_empty_cube(image_size, energy_cube, center_maps)
    header = ref_cube.sky_image_ref.to_image_hdu().header
    energy_bins = ref_cube.energies()
    for i_E, E in enumerate(energy_bins[0:-1]):
        energy_band = Energy(
            [energy_bins[i_E].value, energy_bins[i_E + 1].value],
            energy_bins.unit)
        energy = EnergyBounds.equal_log_spacing(energy_band[0].value,
                                                energy_band[1].value, 100,
                                                energy_band.unit)
        psf_energydependent = ObsList.make_psf(center, energy, theta=None)
        try:
            psf_table = psf_energydependent.table_psf_in_energy_band(
                energy_band, spectral_index=spectral_index)
        except:
            psf_table = TablePSF(
                psf_energydependent.offset,
                Quantity(np.zeros(len(psf_energydependent.offset)), u.sr**-1))
        ref_cube.data[i_E, :, :] = fill_acceptance_image(
            header, center_maps, psf_table._offset.to("deg"),
            psf_table._dp_domega,
            psf_table._offset.to("deg")[-1]).data
    return ref_cube
示例#6
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.cube.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(table_psf_to_kernel_map(table_psf, geom, factor))
示例#7
0
def test_table_psf_to_kernel_map():
    sigma = 0.5 * u.deg
    binsz = 0.1 * u.deg
    geom = WcsGeom.create(binsz=binsz, npix=150)

    rad = Angle(np.linspace(0.0, 3 * sigma.to("deg").value, 100), "deg")
    table_psf = TablePSF.from_shape(shape="gauss", width=sigma, rad=rad)
    kernel = PSFKernel.from_table_psf(table_psf, geom)
    kernel_array = kernel.psf_kernel_map.data

    # Is normalization OK?
    assert_allclose(kernel_array.sum(), 1.0, atol=1e-5)

    # maximum at the center of map?
    ind = np.unravel_index(np.argmax(kernel_array, axis=None), kernel_array.shape)
    # absolute tolerance at 0.5 because of even number of pixel here
    assert_allclose(ind, geom.center_pix, atol=0.5)
示例#8
0
def make_psf(energy_band,
             source_name,
             center,
             ObsList,
             outdir,
             spectral_index=2.3):
    """
    Compute the mean psf for a set of observation and a given energy band
    Parameters
    ----------
    energy_band: energy band on which you want to compute the map
    source_name: name of the source you want to compute the image
    center: SkyCoord of the source
    ObsList: ObservationList to use to compute the psf (could be different that the data_store for G0p9 for the GC for example)
    outdir: directory where the fits image will go
    spectral_index: assumed spectral index to compute the psf

    Returns
    -------

    """
    energy = EnergyBounds.equal_log_spacing(energy_band[0].value,
                                            energy_band[1].value, 100,
                                            energy_band.unit)
    # Here all the observations have a center at less than 2 degrees from the Crab so it will be ok to estimate the mean psf on the Crab source postion (the area is define for offset equal to 2 degrees...)
    psf_energydependent = ObsList.make_mean_psf(center, energy, theta=None)
    #import IPython; IPython.embed()
    try:
        psf_table = psf_energydependent.table_psf_in_energy_band(
            energy_band, spectral_index=spectral_index)
    except:
        psf_table = TablePSF(
            psf_energydependent.offset,
            Quantity(np.zeros(len(psf_energydependent.offset)), u.sr**-1))
    Table_psf = Table()
    c1 = Column(psf_table._dp_domega,
                name='psf_value',
                unit=psf_table._dp_domega.unit)
    c2 = Column(psf_table._offset, name='theta', unit=psf_table._offset.unit)
    Table_psf.add_column(c1)
    Table_psf.add_column(c2)
    filename_psf = outdir + "/psf_table_" + source_name + "_" + str(
        energy_band[0].value) + '_' + str(energy_band[1].value) + ".fits"
    Table_psf.write(filename_psf, overwrite=True)
示例#9
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"
示例#10
0
    def test_disk():
        width = Angle(2, "deg")
        rad = Angle(np.linspace(0, 2.3, 1000), "deg")
        psf = TablePSF.from_shape(shape="disk", width=width, rad=rad)

        # test containment
        radius = Angle(1, "deg")
        actual = psf.containment(radius)
        desired = (radius / width).to_value("")**2
        assert_allclose(actual, desired, rtol=1e-4)

        # test containment radius
        actual = psf.containment_radius(0.25).deg
        assert_allclose(actual, radius.deg, rtol=1e-4)

        # test info
        info = psf.info()
        assert info.find("integral") == 58

        # test broaden
        psf.broaden(2, normalize=True)
        actual = psf.containment_radius(0.25).deg
        assert_allclose(actual, 2 * radius.deg, rtol=1e-4)