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)
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)
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)
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))
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)
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"
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)