Пример #1
0
def test_excess_map_estimator_map_dataset_on_off_reco_exposure(
    simple_dataset_on_off, ):

    # TODO: this has never worked...
    model = SkyModel(
        PowerLawSpectralModel(amplitude="1e-9 cm-2 s-1TeV-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_on_off.models = [model]

    spectral_model = PowerLawSpectralModel(index=15)
    estimator_mod = ExcessMapEstimator(
        0.11 * u.deg,
        correlate_off=True,
        spectral_model=spectral_model,
    )
    result_mod = estimator_mod.run(simple_dataset_on_off)

    assert result_mod["flux"].unit == "cm-2s-1"
    assert_allclose(result_mod["flux"].data.sum(), 5.254442e-06, rtol=1e-3)

    reco_exposure = estimate_exposure_reco_energy(
        simple_dataset_on_off, spectral_model=spectral_model)
    assert_allclose(reco_exposure.data.sum(), 7.977796e12, rtol=0.001)
Пример #2
0
def test_excess_map_estimator_map_dataset_on_off_with_correlation_model(
    simple_dataset_on_off, ):
    model = SkyModel(
        PowerLawSpectralModel(amplitude="1e-9 cm-2 s-1TeV-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_on_off.models = [model]

    estimator_mod = ExcessMapEstimator(0.11 * u.deg, correlate_off=True)

    result_mod = estimator_mod.run(simple_dataset_on_off)
    assert result_mod["npred"].data.shape == (1, 20, 20)

    assert_allclose(result_mod["sqrt_ts"].data[0, 10, 10], 6.240846, atol=1e-3)

    assert_allclose(result_mod["npred"].data[0, 10, 10], 388)
    assert_allclose(result_mod["npred_excess"].data[0, 10, 10], 148.68057)

    assert result_mod["flux"].unit == "cm-2s-1"
    assert_allclose(result_mod["flux"].data[0, 10, 10],
                    1.486806e-08,
                    rtol=1e-3)
    assert_allclose(result_mod["flux"].data.sum(), 5.254442e-06, rtol=1e-3)
Пример #3
0
    def run(dataset, correlation_radius, sigma, negative):
        estimator_excess = ExcessMapEstimator(
            correlation_radius=correlation_radius,
            n_sigma=1, 
            n_sigma_ul=3,
            selection_optional=None,
            energy_edges=energy_edges, 
        )
        result = estimator_excess.run(dataset)
        
        sources = find_peaks(
            result["sqrt_ts"],
            threshold=sigma,
            min_distance=correlation_radius,
        )
        if negative is True:
            result["sqrt_ts"].data = -result["sqrt_ts"].data
            sources.vstack(
                find_peaks(
                        result["sqrt_ts"],
                        threshold=sigma,
                        min_distance=correlation_radius,
                )
            )

        regions = []
        for source in sources:
            skydir = SkyCoord(source["ra"], source["dec"], unit="deg", frame="icrs")
            if dataset.counts.geom.to_image().contains(skydir):
                regions.append(CircleSkyRegion(skydir, 0.2 * u.deg))
        return dataset.counts.geom.to_image().region_mask(regions=regions, inside=False), result
Пример #4
0
def compute_correlations(stacked_on_off):
    # Using a convolution radius of 0.1 degrees
    estimator = ExcessMapEstimator(0.1 * u.deg)
    lima_maps = estimator.run(stacked_on_off)

    significance_map = lima_maps["sqrt_ts"]
    excess_map = lima_maps.npred_excess
    return significance_map, excess_map
Пример #5
0
def test_incorrect_selection():
    with pytest.raises(ValueError):
        ExcessMapEstimator(0.11 * u.deg, selection_optional=["bad"])

    with pytest.raises(ValueError):
        ExcessMapEstimator(0.11 * u.deg, selection_optional=["ul", "bad"])

    estimator = ExcessMapEstimator(0.11 * u.deg)
    with pytest.raises(ValueError):
        estimator.selection_optional = "bad"
Пример #6
0
def test_significance_map_estimator_map_dataset_on_off(simple_dataset_on_off):
    estimator = ExcessMapEstimator(0.11 * u.deg)
    result = estimator.run(simple_dataset_on_off, steps=["ts"])

    assert_allclose(result["counts"].data[0, 10, 10], 194)
    assert_allclose(result["excess"].data[0, 10, 10], 97)
    assert_allclose(result["background"].data[0, 10, 10], 97)
    assert_allclose(result["significance"].data[0, 10, 10],
                    5.741116,
                    atol=1e-5)
Пример #7
0
def test_significance_map_estimator_map_dataset_on_off(simple_dataset_on_off):
    estimator = ExcessMapEstimator(0.11 * u.deg, selection_optional=None)
    result = estimator.run(simple_dataset_on_off)

    assert_allclose(result["counts"].data[0, 10, 10], 194)
    assert_allclose(result["excess"].data[0, 10, 10], 97)
    assert_allclose(result["background"].data[0, 10, 10], 97)
    assert_allclose(result["significance"].data[0, 10, 10],
                    5.741116,
                    atol=1e-5)

    estimator_image = ExcessMapEstimator(0.11 * u.deg, return_image=True)
    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)
    assert_allclose(result_image["significance"].data[0, 10, 10],
                    5.741116,
                    atol=1e-3)

    mask_fit = Map.from_geom(
        simple_dataset_on_off._geom,
        data=np.ones(simple_dataset_on_off.counts.data.shape, dtype=bool),
    )
    mask_fit.data[:, :, 10] = False
    mask_fit.data[:, 10, :] = False
    simple_dataset_on_off.mask_fit = mask_fit
    estimator_image = ExcessMapEstimator(0.11 * u.deg,
                                         apply_mask_fit=True,
                                         return_image=True)
    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)
    assert_allclose(result_image["significance"].data[0, 10, 10],
                    5.08179,
                    atol=1e-3)
Пример #8
0
def test_significance_map_estimator_map_dataset(simple_dataset):
    estimator = ExcessMapEstimator(0.1 * u.deg)
    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], 122.240837, atol=1e-3)
Пример #9
0
def test_excess_map_estimator_map_dataset_on_off_with_correlation_no_exposure(
    simple_dataset_on_off, ):
    # First without exposure
    simple_dataset_on_off.exposure = None

    estimator = ExcessMapEstimator(0.11 * u.deg,
                                   energy_edges=[0.1, 1, 10] * u.TeV,
                                   correlate_off=True)
    result = estimator.run(simple_dataset_on_off)

    assert result["npred"].data.shape == (2, 20, 20)
    assert_allclose(result["npred"].data[:, 10, 10], 194)
    assert_allclose(result["npred_excess"].data[:, 10, 10], 97)
    assert_allclose(result["sqrt_ts"].data[:, 10, 10], 5.741116, atol=1e-5)
Пример #10
0
def test_excess_map_estimator_map_dataset_on_off_no_correlation(
    simple_dataset_on_off, ):
    # Test with exposure
    estimator_image = ExcessMapEstimator(0.11 * u.deg,
                                         energy_edges=[0.1, 1] * u.TeV,
                                         correlate_off=False)

    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["npred"].data.shape == (1, 20, 20)
    assert_allclose(result_image["npred"].data[0, 10, 10], 194)
    assert_allclose(result_image["npred_excess"].data[0, 10, 10], 97)
    assert_allclose(result_image["sqrt_ts"].data[0, 10, 10],
                    0.780125,
                    atol=1e-3)
    assert_allclose(result_image["flux"].data[:, 10, 10], 9.7e-9, atol=1e-5)
Пример #11
0
def test_compute_lima_on_off_image():
    """
    Test Li & Ma image with snippet from the H.E.S.S. survey data.
    """
    filename = "$GAMMAPY_DATA/tests/unbundled/hess/survey/hess_survey_snippet.fits.gz"
    n_on = Map.read(filename, hdu="ON")
    counts = image_to_cube(n_on, "1 TeV", "100 TeV")
    n_off = Map.read(filename, hdu="OFF")
    counts_off = image_to_cube(n_off, "1 TeV", "100 TeV")
    a_on = Map.read(filename, hdu="ONEXPOSURE")
    acceptance = image_to_cube(a_on, "1 TeV", "100 TeV")
    a_off = Map.read(filename, hdu="OFFEXPOSURE")
    acceptance_off = image_to_cube(a_off, "1 TeV", "100 TeV")
    dataset = MapDatasetOnOff(
        counts=counts,
        counts_off=counts_off,
        acceptance=acceptance,
        acceptance_off=acceptance_off,
    )

    significance = Map.read(filename, hdu="SIGNIFICANCE")
    significance = image_to_cube(significance, "1 TeV", "10 TeV")
    estimator = ExcessMapEstimator("0.1 deg", correlate_off=False)
    results = estimator.run(dataset)

    # Reproduce safe significance threshold from HESS software
    results["sqrt_ts"].data[results["npred"].data < 5] = 0

    # crop the image at the boundaries, because the reference image
    # is cut out from a large map, there is no way to reproduce the
    # result with regular boundary handling
    actual = results["sqrt_ts"].crop((11, 11)).data
    desired = significance.crop((11, 11)).data

    # Set boundary to NaN in reference image
    # The absolute tolerance is low because the method used here is slightly different from the one used in HGPS
    # n_off is convolved as well to ensure the method applies to true ON-OFF datasets
    assert_allclose(actual, desired, atol=0.2, rtol=1e-5)

    actual = np.nan_to_num(results["npred_background"].crop((11, 11)).data)
    background_corr = image_to_cube(
        Map.read(filename, hdu="BACKGROUNDCORRELATED"), "1 TeV", "100 TeV")
    desired = background_corr.crop((11, 11)).data

    # Set boundary to NaN in reference image
    # The absolute tolerance is low because the method used here is slightly different from the one used in HGPS
    # n_off is convolved as well to ensure the method applies to true ON-OFF datasets
    assert_allclose(actual, desired, atol=0.2, rtol=1e-5)
Пример #12
0
def test_compute_lima_image():
    """
    Test Li & Ma image against TS image for Tophat kernel
    """
    filename = "$GAMMAPY_DATA/tests/unbundled/poisson_stats_image/input_all.fits.gz"
    counts = Map.read(filename, hdu="counts")
    counts = image_to_cube(counts, "1 GeV", "100 GeV")
    background = Map.read(filename, hdu="background")
    background = image_to_cube(background, "1 GeV", "100 GeV")
    dataset = MapDataset(counts=counts, background=background)

    estimator = ExcessMapEstimator("0.1 deg")
    result_lima = estimator.run(dataset)

    assert_allclose(result_lima["sqrt_ts"].data[:, 100, 100], 30.814916, atol=1e-3)
    assert_allclose(result_lima["sqrt_ts"].data[:, 1, 1], 0.164, atol=1e-3)
Пример #13
0
def test_compute_lima_image():
    """
    Test Li & Ma image against TS image for Tophat kernel
    """
    filename = "$GAMMAPY_DATA/tests/unbundled/poisson_stats_image/input_all.fits.gz"
    counts = Map.read(filename, hdu="counts")
    counts = image_to_cube(counts, "1 GeV", "100 GeV")
    background = Map.read(filename, hdu="background")
    background = image_to_cube(background, "1 GeV", "100 GeV")
    background_model = BackgroundModel(background)
    dataset = MapDataset(counts=counts)
    background_model.datasets_names = [dataset.name]
    dataset.models = background_model

    estimator = ExcessMapEstimator("0.1 deg", selection_optional=None)
    result_lima = estimator.run(dataset)

    assert_allclose(result_lima["significance"].data[:, 100, 100], 30.814916, atol=1e-3)
    assert_allclose(result_lima["significance"].data[:, 1, 1], 0.164, atol=1e-3)
Пример #14
0
def test_significance_map_estimator_map_dataset_on_off_no_correlation(
        simple_dataset_on_off):
    exposure = simple_dataset_on_off.exposure
    exposure.data += 1e6

    # Test with exposure
    simple_dataset_on_off.exposure = exposure
    estimator_image = ExcessMapEstimator(0.11 * u.deg,
                                         energy_edges=[0.1, 1] * u.TeV,
                                         correlate_off=False)

    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)
    assert_allclose(result_image["counts"].data[0, 10, 10], 194)
    assert_allclose(result_image["excess"].data[0, 10, 10], 97)
    assert_allclose(result_image["background"].data[0, 10, 10], 97)
    assert_allclose(result_image["sqrt_ts"].data[0, 10, 10],
                    0.780125,
                    atol=1e-3)
    assert_allclose(result_image["flux"].data[:, 10, 10], 9.7e-9, atol=1e-5)
Пример #15
0
def plot_residual_distribution(dataset, obs_id, livetime):
    """Plot residual significance distribution"""
    model = dataset.models[1]

    estimator = ExcessMapEstimator(correlation_radius="0.1 deg")

    maps = estimator.run(dataset)
    valid = np.isfinite(maps["sqrt_ts"].data)
    sig_resid = maps["sqrt_ts"].data[valid]

    plt.hist(
        sig_resid,
        density=True,
        alpha=0.5,
        color="red",
        bins=100,
    )

    mu, std = norm.fit(sig_resid)
    # replace with log.info()
    log.info("Fit results: mu = {:.2f}, std = {:.2f}".format(mu, std))
    x = np.linspace(-8, 8, 50)
    p = norm.pdf(x, mu, std)
    plt.plot(
        x,
        p,
        lw=2,
        color="black",
        label="Fit results: mu = {:.2f}, std = {:.2f}".format(mu, std),
    )
    plt.legend()
    plt.xlabel("Significance")
    plt.yscale("log")
    plt.ylim(1e-5, 1)
    xmin, xmax = np.min(sig_resid), np.max(sig_resid)
    plt.xlim(xmin, xmax)

    obs_id = int(obs_id)
    filename = f"residuals-distribution_{obs_id:04d}.png"
    filepath = f"results/models/{model.name}/plots_{livetime.value:.0f}{livetime.unit}/residuals-distribution/{filename}"
    save_figure(filepath)
Пример #16
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)
Пример #17
0
    def get_excess_map(self):
        """Calculate excess map with respect to the current model."""
        excess_settings = self.config.excess_map
        log.info("Computing excess maps.")

        if self.config.datasets.type == "1d":
            raise ValueError("Cannot compute excess map for 1D dataset")

        # Here we could possibly stack the datasets if needed.
        if len(self.datasets) > 1:
            raise ValueError(
                "Datasets must be stacked to compute the excess map")

        energy_edges = self._make_energy_axis(excess_settings.energy_edges)
        if energy_edges is not None:
            energy_edges = energy_edges.edges

        excess_map_estimator = ExcessMapEstimator(
            correlation_radius=excess_settings.correlation_radius,
            energy_edges=energy_edges,
            **excess_settings.parameters)
        self.excess_map = excess_map_estimator.run(self.datasets[0])
Пример #18
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)
Пример #19
0
def test_significance_map_estimator_map_dataset(simple_dataset):
    simple_dataset.exposure = None
    estimator = ExcessMapEstimator(0.1 * u.deg, selection_optional=["all"])
    result = estimator.run(simple_dataset)

    assert_allclose(result["npred"].data[0, 10, 10], 162)
    assert_allclose(result["npred_excess"].data[0, 10, 10], 81)
    assert_allclose(result["npred_background"].data[0, 10, 10], 81)
    assert_allclose(result["sqrt_ts"].data[0, 10, 10], 7.910732, atol=1e-5)

    assert_allclose(result["npred_excess_err"].data[0, 10, 10],
                    12.727922,
                    atol=1e-3)
    assert_allclose(result["npred_excess_errp"].data[0, 10, 10],
                    13.063328,
                    atol=1e-3)
    assert_allclose(result["npred_excess_errn"].data[0, 10, 10],
                    12.396716,
                    atol=1e-3)
    assert_allclose(result["npred_excess_ul"].data[0, 10, 10],
                    107.806275,
                    atol=1e-3)
Пример #20
0
def test_excess_map_estimator_map_dataset_on_off_with_correlation_mask_fit(
    simple_dataset_on_off, ):
    geom = simple_dataset_on_off.counts.geom
    mask_fit = Map.from_geom(geom, data=1, dtype=bool)
    mask_fit.data[:, :, 10] = False
    mask_fit.data[:, 10, :] = False
    simple_dataset_on_off.mask_fit = mask_fit

    estimator_image = ExcessMapEstimator(0.11 * u.deg, correlate_off=True)

    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["npred"].data.shape == (1, 20, 20)

    assert_allclose(result_image["sqrt_ts"].data[0, 10, 10], np.nan, atol=1e-3)
    assert_allclose(result_image["npred"].data[0, 10, 10], np.nan)
    assert_allclose(result_image["npred_excess"].data[0, 10, 10], np.nan)
    assert_allclose(result_image["sqrt_ts"].data[0, 9, 9], 7.186745, atol=1e-3)
    assert_allclose(result_image["npred"].data[0, 9, 9], 304)
    assert_allclose(result_image["npred_excess"].data[0, 9, 9], 152)

    assert result_image["flux"].unit == u.Unit("cm-2s-1")
    assert_allclose(result_image["flux"].data[0, 9, 9],
                    1.190928e-08,
                    rtol=1e-3)
Пример #21
0
def test_significance_map_estimator_incorrect_dataset():
    with pytest.raises(ValueError):
        ExcessMapEstimator("bad")
Пример #22
0
def test_significance_map_estimator_map_dataset_on_off(simple_dataset_on_off):
    estimator = ExcessMapEstimator(
        0.11 * u.deg,
        selection_optional=None,
        e_edges=[0.1 * u.TeV, 1 * u.TeV, 10 * u.TeV],
    )
    result = estimator.run(simple_dataset_on_off)

    assert result["counts"].data.shape == (2, 20, 20)
    assert_allclose(result["counts"].data[:, 10, 10], 194)
    assert_allclose(result["excess"].data[:, 10, 10], 97)
    assert_allclose(result["background"].data[:, 10, 10], 97)
    assert_allclose(result["significance"].data[:, 10, 10], 5.741116, atol=1e-5)

    estimator_image = ExcessMapEstimator(0.11 * u.deg, e_edges=[0.1 * u.TeV, 1 * u.TeV])

    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)
    assert_allclose(result_image["significance"].data[0, 10, 10], 5.741116, atol=1e-3)

    mask_fit = Map.from_geom(
        simple_dataset_on_off._geom,
        data=np.ones(simple_dataset_on_off.counts.data.shape, dtype=bool),
    )
    mask_fit.data[:, :, 10] = False
    mask_fit.data[:, 10, :] = False
    simple_dataset_on_off.mask_fit = mask_fit

    estimator_image = ExcessMapEstimator(0.11 * u.deg, apply_mask_fit=True)

    simple_dataset_on_off.exposure.data = (
        np.ones(simple_dataset_on_off.exposure.data.shape) * 1e6
    )
    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)

    assert_allclose(result_image["significance"].data[0, 10, 10], 7.186745, atol=1e-3)

    assert_allclose(result_image["counts"].data[0, 10, 10], 304)
    assert_allclose(result_image["excess"].data[0, 10, 10], 152)
    assert_allclose(result_image["background"].data[0, 10, 10], 152)

    assert result_image["flux"].unit == u.Unit("cm-2s-1")
    assert_allclose(result_image["flux"].data[0, 10, 10], 7.6e-9, rtol=1e-3)

    # test with an npred()
    simple_dataset_on_off.exposure.data = (
        np.ones(simple_dataset_on_off.exposure.data.shape) * 1e10
    )
    simple_dataset_on_off.psf = None
    model = SkyModel(
        PowerLawSpectralModel(),
        GaussianSpatialModel(
            lat_0=0.0 * u.deg, lon_0=0.0 * u.deg, sigma=0.1 * u.deg, frame="icrs"
        ),
        datasets_names=[simple_dataset_on_off.name],
        name="sky_model",
    )
    simple_dataset_on_off.models.append(model)
    estimator_mod = ExcessMapEstimator(0.11 * u.deg, apply_mask_fit=False)
    result_mod = estimator_mod.run(simple_dataset_on_off)
    assert result_mod["counts"].data.shape == (1, 20, 20)

    assert_allclose(result_mod["significance"].data[0, 10, 10], 8.119164, atol=1e-3)

    assert_allclose(result_mod["counts"].data[0, 10, 10], 388)
    assert_allclose(result_mod["excess"].data[0, 10, 10], 194)
    assert_allclose(result_mod["background"].data[0, 10, 10], 194)

    assert result_mod["flux"].unit == u.Unit("cm-2s-1")
    assert_allclose(result_image["flux"].data[0, 10, 10], 7.6e-9, rtol=1e-3)
Пример #23
0
def test_significance_map_estimator_map_dataset_on_off_with_correlation(
    simple_dataset_on_off, ):
    exposure = simple_dataset_on_off.exposure
    exposure.data += 1e6

    # First without exposure
    simple_dataset_on_off.exposure = None

    estimator = ExcessMapEstimator(0.11 * u.deg,
                                   energy_edges=[0.1, 1, 10] * u.TeV,
                                   correlate_off=True)
    result = estimator.run(simple_dataset_on_off)

    assert result["counts"].data.shape == (2, 20, 20)
    assert_allclose(result["counts"].data[:, 10, 10], 194)
    assert_allclose(result["excess"].data[:, 10, 10], 97)
    assert_allclose(result["background"].data[:, 10, 10], 97)
    assert_allclose(result["sqrt_ts"].data[:, 10, 10], 5.741116, atol=1e-5)
    assert_allclose(result["flux"].data[:, 10, 10], np.nan)

    # Test with exposure
    simple_dataset_on_off.exposure = exposure
    estimator_image = ExcessMapEstimator(0.11 * u.deg,
                                         energy_edges=[0.1, 1] * u.TeV,
                                         correlate_off=True)

    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)
    assert_allclose(result_image["counts"].data[0, 10, 10], 194)
    assert_allclose(result_image["excess"].data[0, 10, 10], 97)
    assert_allclose(result_image["background"].data[0, 10, 10], 97)
    assert_allclose(result_image["sqrt_ts"].data[0, 10, 10],
                    5.741116,
                    atol=1e-3)
    assert_allclose(result_image["flux"].data[:, 10, 10], 9.7e-9, atol=1e-5)

    # Test with mask fit
    mask_fit = Map.from_geom(
        simple_dataset_on_off._geom,
        data=np.ones(simple_dataset_on_off.counts.data.shape, dtype=bool),
    )
    mask_fit.data[:, :, 10] = False
    mask_fit.data[:, 10, :] = False
    simple_dataset_on_off.mask_fit = mask_fit

    estimator_image = ExcessMapEstimator(0.11 * u.deg,
                                         apply_mask_fit=True,
                                         correlate_off=True)

    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)

    assert_allclose(result_image["sqrt_ts"].data[0, 10, 10], np.nan, atol=1e-3)
    assert_allclose(result_image["counts"].data[0, 10, 10], np.nan)
    assert_allclose(result_image["excess"].data[0, 10, 10], np.nan)
    assert_allclose(result_image["background"].data[0, 10, 10], np.nan)
    assert_allclose(result_image["sqrt_ts"].data[0, 9, 9], 7.186745, atol=1e-3)
    assert_allclose(result_image["counts"].data[0, 9, 9], 304)
    assert_allclose(result_image["excess"].data[0, 9, 9], 152)
    assert_allclose(result_image["background"].data[0, 9, 9], 152)

    assert result_image["flux"].unit == u.Unit("cm-2s-1")
    assert_allclose(result_image["flux"].data[0, 9, 9], 1.52e-8, rtol=1e-3)

    simple_dataset_on_off.psf = None

    # TODO: this has never worked...
    model = SkyModel(
        PowerLawSpectralModel(amplitude="1e-9 cm-2 s-1TeV-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_on_off.models = [model]

    estimator_mod = ExcessMapEstimator(0.11 * u.deg,
                                       apply_mask_fit=False,
                                       correlate_off=True)
    result_mod = estimator_mod.run(simple_dataset_on_off)
    assert result_mod["counts"].data.shape == (1, 20, 20)

    assert_allclose(result_mod["sqrt_ts"].data[0, 10, 10], 8.899278, atol=1e-3)

    assert_allclose(result_mod["counts"].data[0, 10, 10], 388)
    assert_allclose(result_mod["excess"].data[0, 10, 10], 190.68057)
    assert_allclose(result_mod["background"].data[0, 10, 10], 197.31943)

    assert result_mod["flux"].unit == "cm-2s-1"
    assert_allclose(result_mod["flux"].data[0, 10, 10],
                    1.906806e-08,
                    rtol=1e-3)
    assert_allclose(result_mod["flux"].data.sum(), 5.920642e-06, rtol=1e-3)

    spectral_model = PowerLawSpectralModel(index=15)
    estimator_mod = ExcessMapEstimator(
        0.11 * u.deg,
        apply_mask_fit=False,
        correlate_off=True,
        spectral_model=spectral_model,
    )
    result_mod = estimator_mod.run(simple_dataset_on_off)

    assert result_mod["flux"].unit == "cm-2s-1"
    assert_allclose(result_mod["flux"].data.sum(), 5.920642e-06, rtol=1e-3)

    reco_exposure = estimate_exposure_reco_energy(
        simple_dataset_on_off, spectral_model=spectral_model)
    assert_allclose(reco_exposure.data.sum(), 7.977796e+12, rtol=0.001)
Пример #24
0
def test_significance_map_estimator_map_dataset_on_off(simple_dataset_on_off):
    exposure = simple_dataset_on_off.exposure
    exposure.data += 1e6

    # First without exposure
    simple_dataset_on_off.exposure = None

    estimator = ExcessMapEstimator(
        0.11 * u.deg,
        selection_optional=None,
        energy_edges=[0.1, 1, 10] * u.TeV,
    )
    result = estimator.run(simple_dataset_on_off)

    assert result["counts"].data.shape == (2, 20, 20)
    assert_allclose(result["counts"].data[:, 10, 10], 194)
    assert_allclose(result["excess"].data[:, 10, 10], 97)
    assert_allclose(result["background"].data[:, 10, 10], 97)
    assert_allclose(result["sqrt_ts"].data[:, 10, 10], 5.741116, atol=1e-5)
    assert_allclose(result["flux"].data[:, 10, 10], np.nan)

    # Test with exposure
    simple_dataset_on_off.exposure = exposure
    estimator_image = ExcessMapEstimator(0.11 * u.deg,
                                         energy_edges=[0.1, 1] * u.TeV)

    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)
    assert_allclose(result_image["counts"].data[0, 10, 10], 194)
    assert_allclose(result_image["excess"].data[0, 10, 10], 97)
    assert_allclose(result_image["background"].data[0, 10, 10], 97)
    assert_allclose(result_image["sqrt_ts"].data[0, 10, 10],
                    5.741116,
                    atol=1e-3)
    assert_allclose(result_image["flux"].data[:, 10, 10], 9.7e-9, atol=1e-5)

    # Test with mask fit
    mask_fit = Map.from_geom(
        simple_dataset_on_off._geom,
        data=np.ones(simple_dataset_on_off.counts.data.shape, dtype=bool),
    )
    mask_fit.data[:, :, 10] = False
    mask_fit.data[:, 10, :] = False
    simple_dataset_on_off.mask_fit = mask_fit

    estimator_image = ExcessMapEstimator(0.11 * u.deg, apply_mask_fit=True)

    result_image = estimator_image.run(simple_dataset_on_off)
    assert result_image["counts"].data.shape == (1, 20, 20)

    assert_allclose(result_image["sqrt_ts"].data[0, 10, 10], np.nan, atol=1e-3)
    assert_allclose(result_image["counts"].data[0, 10, 10], np.nan)
    assert_allclose(result_image["excess"].data[0, 10, 10], np.nan)
    assert_allclose(result_image["background"].data[0, 10, 10], np.nan)
    assert_allclose(result_image["sqrt_ts"].data[0, 9, 9], 7.186745, atol=1e-3)
    assert_allclose(result_image["counts"].data[0, 9, 9], 304)
    assert_allclose(result_image["excess"].data[0, 9, 9], 152)
    assert_allclose(result_image["background"].data[0, 9, 9], 152)

    assert result_image["flux"].unit == u.Unit("cm-2s-1")
    assert_allclose(result_image["flux"].data[0, 9, 9], 1.52e-8, rtol=1e-3)

    simple_dataset_on_off.psf = None

    # TODO: this has never worked...
    model = SkyModel(
        PowerLawSpectralModel(amplitude="1e-9 cm-2 s-1TeV-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_on_off.models = [model]

    estimator_mod = ExcessMapEstimator(0.11 * u.deg, apply_mask_fit=False)
    result_mod = estimator_mod.run(simple_dataset_on_off)
    assert result_mod["counts"].data.shape == (1, 20, 20)

    assert_allclose(result_mod["sqrt_ts"].data[0, 10, 10], 6.240846, atol=1e-3)

    assert_allclose(result_mod["counts"].data[0, 10, 10], 388)
    assert_allclose(result_mod["excess"].data[0, 10, 10], 148.68057)
    assert_allclose(result_mod["background"].data[0, 10, 10], 239.31943)

    assert result_mod["flux"].unit == u.Unit("cm-2s-1")
    assert_allclose(result_mod["flux"].data[0, 10, 10],
                    1.486806e-08,
                    rtol=1e-3)
Пример #25
0
def estimate_significance_luca(
    dataset, 
    first_guess_exclusion,
    correlation_radii,
    energy_edgess,
    n_iter,
    low,
    high,
    negative=False
):    
    for nn in range(n_iter):
        print(f"###########")
        print(nn)
        print(f"###########")

        results = []
        for correlation_radius, energy_edges in zip(correlation_radii, energy_edgess):
            estimator_excess = ExcessMapEstimator(
                correlation_radius=correlation_radius,
                n_sigma=1, 
                n_sigma_ul=3,
                selection_optional=None,
                energy_edges=energy_edges, 
            )
            results.append(estimator_excess.run(dataset))

        def _reproject_exclusion_mask(geom, exclusion):
            """Reproject the exclusion on the dataset geometry"""
            mask_map = Map.from_geom(geom)
            coords = geom.get_coord()
            vals = exclusion.get_by_coord(coords)
            mask_map.data += vals
            return mask_map
        first_guess_exclusion = _reproject_exclusion_mask(dataset.counts.geom, first_guess_exclusion).slice_by_idx({"energy" : 0})

        plt.figure(figsize=(8, 6))
        for correlation_radius, energy_edges, result in zip(correlation_radii, energy_edgess, results):
            (result["sqrt_ts"].slice_by_idx({"energy" : 0})*first_guess_exclusion).plot(add_cbar=True, cmap="coolwarm", vmin=-5, vmax=5)
            plt.title(f"{correlation_radius} {energy_edges}")
            plt.show()
            plt.close()

        exclusion_enlarged = first_guess_exclusion.copy()
        # Enlarge exclusion mask
        for result, radius in zip(results, correlation_radii):
            mask_map_significance = result["sqrt_ts"].copy().slice_by_idx({"energy" : 0})
            mask_map_significance.data = np.nan_to_num(mask_map_significance.data)
            mask_map = mask_map_significance.copy()
            mask_map.data = ~apply_hysteresis_threshold(mask_map_significance.data, low=low, high=high)
            if negative == True:
                mask_map.data *= ~apply_hysteresis_threshold(-mask_map_significance.data, low=low, high=high)
            exclusion_enlarged *= mask_map

        plt.figure(figsize=(8, 6))
        first_guess_exclusion.plot()
        plt.contour(exclusion_enlarged.data, levels=1, colors="r", inewidths=2)
        plt.show()
        plt.close()

        for correlation_radius, energy_edges, result in zip(correlation_radii, energy_edgess, results):
            pretty_plot_1d_significance(result, correlation_radius, energy_edges, exclusion_enlarged)
            
        first_guess_exclusion = exclusion_enlarged
        
    print(f"###########")
    print("Final result")
    print(f"###########")

    for correlation_radius, energy_edges, result in zip(correlation_radii, energy_edgess, results):
        plt.figure(figsize=(8, 6))
        final = (result["sqrt_ts"].slice_by_idx({"energy" : 0}))
        final.plot(add_cbar=True, cmap="coolwarm", vmin=-5, vmax=5)
        cs = plt.contour(final.data, levels=(-15, -10, -7, -5, -3, 3, 5, 7, 10, 15), colors="k")
        plt.clabel(cs, colors="k")
        plt.title(f"{correlation_radius} {energy_edges}")
        plt.show()
        plt.close()