Beispiel #1
0
    def _scan_position(self, name, **kwargs):

        saved_state = LikelihoodState(self.like)

        skydir = kwargs.pop('skydir', self.roi[name].skydir)
        scan_cdelt = kwargs.pop('scan_cdelt', 0.02)
        nstep = kwargs.pop('nstep', 5)
        use_cache = kwargs.get('use_cache', True)
        use_pylike = kwargs.get('use_pylike', False)
        optimizer = kwargs.get('optimizer', {})

        # Fit without source
        self.zero_source(name, loglevel=logging.DEBUG)
        fit_output_nosrc = self._fit(loglevel=logging.DEBUG,
                                     **optimizer)
        self.unzero_source(name, loglevel=logging.DEBUG)
        saved_state.restore()
        self.free_norm(name, loglevel=logging.DEBUG)

        lnlmap = WcsNDMap.create(skydir=skydir, binsz=scan_cdelt, npix=(nstep, nstep),
                                 coordsys=wcs_utils.get_coordsys(self.geom.wcs))

        src = self.roi.copy_source(name)

        if use_cache and not use_pylike:
            self._create_srcmap_cache(src.name, src)

        coord = MapCoord.create(lnlmap.geom.get_coord(flat=True),
                                coordsys=lnlmap.geom.coordsys)
        scan_skydir = coord.skycoord.icrs
        for lon, lat, ra, dec in zip(coord.lon, coord.lat,
                                     scan_skydir.ra.deg, scan_skydir.dec.deg):

            spatial_pars = {'ra': ra, 'dec': dec}
            self.set_source_morphology(name,
                                       spatial_pars=spatial_pars,
                                       use_pylike=use_pylike)
            fit_output = self._fit(loglevel=logging.DEBUG,
                                   **optimizer)
            lnlmap.set_by_coord((lon, lat), fit_output['loglike'])

        self.set_source_morphology(name, spatial_pars=src.spatial_pars,
                                   use_pylike=use_pylike)
        saved_state.restore()

        lnlmap.data -= fit_output_nosrc['loglike']
        tsmap = WcsNDMap(lnlmap.geom, 2.0 * lnlmap.data)

        self._clear_srcmap_cache()
        return tsmap, fit_output_nosrc['loglike']
Beispiel #2
0
def test_wcsndmap_reproject_allsky_car():
    geom = WcsGeom.create(binsz=10.0, proj="CAR", coordsys="CEL")
    m = WcsNDMap(geom)
    coords = m.geom.get_coord()
    m.set_by_coord(coords, coords[0].value)

    geom0 = WcsGeom.create(binsz=1.0,
                           proj="CAR",
                           coordsys="CEL",
                           skydir=(180.0, 0.0),
                           width=30.0)
    m0 = m.reproject(geom0, order=1)
    coords0 = m0.geom.get_coord()
    assert_allclose(m0.get_by_coord(coords0), coords0[0].value)

    geom1 = HpxGeom.create(binsz=5.0, coordsys="CEL")
    m1 = m.reproject(geom1, order=1)
    coords1 = m1.geom.get_coord()

    m = (coords1[0] > 10) & (coords1[0] < 350)
    assert_allclose(m1.get_by_coord((coords1[0][m], coords1[1][m])),
                    coords1[0][m])
Beispiel #3
0
def test_wcsndmap_read_write_fgst(tmp_path):
    path = tmp_path / "tmp.fits"

    axis = MapAxis.from_bounds(100.0, 1000.0, 4, name="energy", unit="MeV")
    geom = WcsGeom.create(npix=10,
                          binsz=1.0,
                          proj="AIT",
                          frame="galactic",
                          axes=[axis])

    # Test Counts Cube
    m = WcsNDMap(geom)
    m.write(path, format="fgst-ccube", overwrite=True)
    with fits.open(path, memmap=False) as hdulist:
        assert "EBOUNDS" in hdulist

    m2 = Map.read(path)
    assert m2.geom.axes[0].name == "energy"

    # Test Model Cube
    m.write(path, format="fgst-template", overwrite=True)
    with fits.open(path, memmap=False) as hdulist:
        assert "ENERGIES" in hdulist
Beispiel #4
0
def test_wcsndmap_read_write_fgst(tmpdir):
    filename = str(tmpdir / "map.fits")

    axis = MapAxis.from_bounds(100.0, 1000.0, 4, name="energy", unit="MeV")
    geom = WcsGeom.create(npix=10,
                          binsz=1.0,
                          proj="AIT",
                          coordsys="GAL",
                          axes=[axis])

    # Test Counts Cube
    m = WcsNDMap(geom)
    m.write(filename, conv="fgst-ccube", overwrite=True)
    with fits.open(filename) as h:
        assert "EBOUNDS" in h

    m2 = Map.read(filename)
    assert m2.geom.axes[0].name == "energy"

    # Test Model Cube
    m.write(filename, conv="fgst-template", overwrite=True)
    with fits.open(filename) as h:
        assert "ENERGIES" in h
Beispiel #5
0
# We see that the geometry of the images is completely different, so we need to apply our geometric configuration to the diffuse emission file:

# In[ ]:

coord = maps["counts"].geom.get_coord()

data = diffuse_gal.interp_by_coord(
    {
        "skycoord":
        coord.skycoord,
        "energy":
        coord["energy"] * maps["counts"].geom.get_axis_by_name("energy").unit,
    },
    interp=3,
)
diffuse_galactic = WcsNDMap(maps["counts"].geom, data)
print("Before: \n", diffuse_gal.geom)
print("Now (same as maps): \n", diffuse_galactic.geom)

# In[ ]:

# diffuse_galactic.slice_by_idx({"energy": 0}).plot(add_cbar=True); # this can be used to check image at different energy bins
diffuse = diffuse_galactic.sum_over_axes()
diffuse.smooth(5).plot(stretch="sqrt", add_cbar=True)
print(diffuse)

# We now multiply the exposure for this diffuse emission to subtract the result from the counts along with the background.

# In[ ]:

combination = diffuse * exposure
Beispiel #6
0
def make_map_background_irf(pointing, ontime, bkg, geom, oversampling=None):
    """Compute background map from background IRFs.

    Parameters
    ----------
    pointing : `~gammapy.data.FixedPointingInfo` or `~astropy.coordinates.SkyCoord`
        Observation pointing

        - If a ``FixedPointingInfo`` is passed, FOV coordinates are properly computed.
        - If a ``SkyCoord`` is passed, FOV frame rotation is not taken into account.
    ontime : `~astropy.units.Quantity`
        Observation ontime. i.e. not corrected for deadtime
        see https://gamma-astro-data-formats.readthedocs.io/en/stable/irfs/full_enclosure/bkg/index.html#notes)
    bkg : `~gammapy.irf.Background3D`
        Background rate model
    geom : `~gammapy.maps.WcsGeom`
        Reference geometry
    oversampling: int
        Oversampling factor in energy, used for the background model evaluation.

    Returns
    -------
    background : `~gammapy.maps.WcsNDMap`
        Background predicted counts sky cube in reco energy
    """
    # TODO:
    #  This implementation can be improved in two ways:
    #  1. Create equal time intervals between TSTART and TSTOP and sum up the
    #  background IRF for each interval. This is instead of multiplying by
    #  the total ontime. This then handles the rotation of the FoV.
    #  2. Use the pointing table (does not currently exist in CTA files) to
    #  obtain the RA DEC and time for each interval. This then considers that
    #  the pointing might change slightly over the observation duration

    # Get altaz coords for map
    if oversampling is not None:
        geom = geom.upsample(factor=oversampling, axis="energy")

    map_coord = geom.to_image().get_coord()
    sky_coord = map_coord.skycoord

    if isinstance(pointing, FixedPointingInfo):
        altaz_coord = sky_coord.transform_to(pointing.altaz_frame)

        # Compute FOV coordinates of map relative to pointing
        fov_lon, fov_lat = sky_to_fov(altaz_coord.az, altaz_coord.alt,
                                      pointing.altaz.az, pointing.altaz.alt)
    else:
        # Create OffsetFrame
        frame = SkyOffsetFrame(origin=pointing)
        pseudo_fov_coord = sky_coord.transform_to(frame)
        fov_lon = pseudo_fov_coord.lon
        fov_lat = pseudo_fov_coord.lat

    energies = geom.get_axis_by_name("energy").edges

    bkg_de = bkg.evaluate_integrate(
        fov_lon=fov_lon,
        fov_lat=fov_lat,
        energy_reco=energies[:, np.newaxis, np.newaxis],
    )

    d_omega = geom.to_image().solid_angle()
    data = (bkg_de * d_omega * ontime).to_value("")
    bkg_map = WcsNDMap(geom, data=data)

    if oversampling is not None:
        bkg_map = bkg_map.downsample(factor=oversampling, axis="energy")

    return bkg_map
Beispiel #7
0
def test_plot_grid():
    axis = MapAxis([0, 1, 2], node_type="edges")
    m = WcsNDMap.create(binsz=0.1 * u.deg, width=1 * u.deg, axes=[axis])
    with mpl_plot_check():
        m.plot_grid()
Beispiel #8
0
def test_wcsndmap_read_write(tmp_path, npix, binsz, frame, proj, skydir, axes):
    geom = WcsGeom.create(npix=npix,
                          binsz=binsz,
                          proj=proj,
                          frame=frame,
                          axes=axes)
    path = tmp_path / "tmp.fits"

    m0 = WcsNDMap(geom)
    fill_poisson(m0, mu=0.5)
    m0.write(path, overwrite=True)
    m1 = WcsNDMap.read(path)
    m2 = Map.read(path)
    m3 = Map.read(path, map_type="wcs")
    assert_allclose(m0.data, m1.data)
    assert_allclose(m0.data, m2.data)
    assert_allclose(m0.data, m3.data)

    m0.write(path, sparse=True, overwrite=True)
    m1 = WcsNDMap.read(path)
    m2 = Map.read(path)
    m3 = Map.read(path, map_type="wcs")
    assert_allclose(m0.data, m1.data)
    assert_allclose(m0.data, m2.data)
    assert_allclose(m0.data, m3.data)

    # Specify alternate HDU name for IMAGE and BANDS table
    m0.write(path, hdu="IMAGE", hdu_bands="TEST", overwrite=True)
    m1 = WcsNDMap.read(path)
    m2 = Map.read(path)
    m3 = Map.read(path, map_type="wcs")
Beispiel #9
0
    def _make_tsmap_fast(self, prefix, **kwargs):
        """
        Make a TS map from a GTAnalysis instance.  This is a
        simplified implementation optimized for speed that only fits
        for the source normalization (all background components are
        kept fixed). The spectral/spatial characteristics of the test
        source can be defined with the src_dict argument.  By default
        this method will generate a TS map for a point source with an
        index=2.0 power-law spectrum.

        Parameters
        ----------
        model : dict or `~fermipy.roi_model.Source`
           Dictionary or Source object defining the properties of the
           test source that will be used in the scan.

        """
        loglevel = kwargs.get('loglevel', self.loglevel)

        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        src_dict = {} if src_dict is None else src_dict

        multithread = kwargs.setdefault('multithread', False)
        threshold = kwargs.setdefault('threshold', 1E-2)
        max_kernel_radius = kwargs.get('max_kernel_radius')
        loge_bounds = kwargs.setdefault('loge_bounds', None)
        use_pylike = kwargs.setdefault('use_pylike', True)

        if loge_bounds:
            if len(loge_bounds) != 2:
                raise Exception('Wrong size of loge_bounds array.')
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None else
                              self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None else
                              self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        # Put the test source at the pixel closest to the ROI center
        xpix, ypix = (np.round(
            (self.npix - 1.0) / 2.), np.round((self.npix - 1.0) / 2.))
        cpix = np.array([xpix, ypix])

        map_geom = self._geom.to_image()
        frame = coordsys_to_frame(map_geom.coordsys)
        skydir = SkyCoord(*map_geom.pix_to_coord((cpix[0], cpix[1])),
                          frame=frame,
                          unit='deg')
        skydir = skydir.transform_to('icrs')

        src_dict['ra'] = skydir.ra.deg
        src_dict['dec'] = skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)
        src_dict.setdefault('Prefactor', 1E-13)

        counts = []
        bkg = []
        model = []
        c0_map = []
        eslices = []
        enumbins = []
        model_npred = 0
        for c in self.components:

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            eslice = slice(imin, imax)
            bm = c.model_counts_map(
                exclude=kwargs['exclude']).data.astype('float')[eslice, ...]
            cm = c.counts_map().data.astype('float')[eslice, ...]

            bkg += [bm]
            counts += [cm]
            c0_map += [cash(cm, bm)]
            eslices += [eslice]
            enumbins += [cm.shape[0]]

        self.add_source('tsmap_testsource',
                        src_dict,
                        free=True,
                        init_source=False,
                        use_single_psf=True,
                        use_pylike=use_pylike,
                        loglevel=logging.DEBUG)
        src = self.roi['tsmap_testsource']
        # self.logger.info(str(src_dict))
        modelname = utils.create_model_name(src)
        for c, eslice in zip(self.components, eslices):
            mm = c.model_counts_map('tsmap_testsource').data.astype('float')[
                eslice, ...]
            model_npred += np.sum(mm)
            model += [mm]

        self.delete_source('tsmap_testsource', loglevel=logging.DEBUG)

        for i, mm in enumerate(model):

            dpix = 3
            for j in range(mm.shape[0]):

                ix, iy = np.unravel_index(np.argmax(mm[j, ...]), mm[j,
                                                                    ...].shape)

                mx = mm[j, ix, :] > mm[j, ix, iy] * threshold
                my = mm[j, :, iy] > mm[j, ix, iy] * threshold
                dpix = max(dpix, np.round(np.sum(mx) / 2.))
                dpix = max(dpix, np.round(np.sum(my) / 2.))

            if max_kernel_radius is not None and \
                    dpix > int(max_kernel_radius / self.components[i].binsz):
                dpix = int(max_kernel_radius / self.components[i].binsz)

            xslice = slice(max(int(xpix - dpix), 0),
                           min(int(xpix + dpix + 1), self.npix))
            model[i] = model[i][:, xslice, xslice]

        ts_values = np.zeros((self.npix, self.npix))
        amp_values = np.zeros((self.npix, self.npix))

        wrap = functools.partial(_ts_value_newton,
                                 counts=counts,
                                 bkg=bkg,
                                 model=model,
                                 C_0_map=c0_map)

        if kwargs['map_skydir'] is not None:

            map_offset = wcs_utils.skydir_to_pix(kwargs['map_skydir'],
                                                 map_geom.wcs)

            map_delta = 0.5 * kwargs['map_size'] / self.components[0].binsz
            xmin = max(int(np.ceil(map_offset[1] - map_delta)), 0)
            xmax = min(int(np.floor(map_offset[1] + map_delta)) + 1, self.npix)
            ymin = max(int(np.ceil(map_offset[0] - map_delta)), 0)
            ymax = min(int(np.floor(map_offset[0] + map_delta)) + 1, self.npix)

            xslice = slice(xmin, xmax)
            yslice = slice(ymin, ymax)
            xyrange = [range(xmin, xmax), range(ymin, ymax)]

            wcs = map_geom.wcs.deepcopy()
            npix = (ymax - ymin, xmax - xmin)
            crpix = (map_geom._crpix[0] - ymin, map_geom._crpix[1] - xmin)
            wcs.wcs.crpix[0] -= ymin
            wcs.wcs.crpix[1] -= xmin

            # FIXME: We should implement this with a proper cutout method
            map_geom = WcsGeom(wcs, npix, crpix=crpix)
        else:
            xyrange = [range(self.npix), range(self.npix)]
            xslice = slice(0, self.npix)
            yslice = slice(0, self.npix)

        positions = []
        for i, j in itertools.product(xyrange[0], xyrange[1]):
            p = [[k // 2, i, j] for k in enumbins]
            positions += [p]

        self.logger.log(loglevel, 'Fitting test source.')
        if multithread:
            pool = Pool()
            results = pool.map(wrap, positions)
            pool.close()
            pool.join()
        else:
            results = map(wrap, positions)

        for i, r in enumerate(results):
            ix = positions[i][0][1]
            iy = positions[i][0][2]
            ts_values[ix, iy] = r[0]
            amp_values[ix, iy] = r[1]

        ts_values = ts_values[xslice, yslice]
        amp_values = amp_values[xslice, yslice]

        ts_map = WcsNDMap(map_geom, ts_values)
        sqrt_ts_map = WcsNDMap(map_geom, ts_values**0.5)
        npred_map = WcsNDMap(map_geom, amp_values * model_npred)
        amp_map = WcsNDMap(map_geom, amp_values * src.get_norm())

        o = {
            'name': utils.join_strings([prefix, modelname]),
            'src_dict': copy.deepcopy(src_dict),
            'file': None,
            'ts': ts_map,
            'sqrt_ts': sqrt_ts_map,
            'npred': npred_map,
            'amplitude': amp_map,
            'loglike': -self.like(),
            'config': kwargs
        }

        return o
Beispiel #10
0
    def _make_residual_map_wcs(self, prefix, **kwargs):
        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        exclude = kwargs.setdefault('exclude', None)
        loge_bounds = kwargs.setdefault('loge_bounds', None)
        use_weights = kwargs.setdefault('use_weights', False)

        if loge_bounds:
            if len(loge_bounds) != 2:
                raise Exception('Wrong size of loge_bounds array.')
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None else
                              self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None else
                              self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        # Put the test source at the pixel closest to the ROI center
        xpix, ypix = (np.round(
            (self.npix[0] - 1.0) / 2.), np.round((self.npix[1] - 1.0) / 2.))
        cpix = np.array([xpix, ypix])

        geom = self.geom.to_image()
        skywcs = self.geom.wcs
        skydir = wcs_utils.pix_to_skydir(cpix[0], cpix[1], skywcs)

        if src_dict is None:
            src_dict = {}
        src_dict['ra'] = skydir.ra.deg
        src_dict['dec'] = skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)

        kernel = None

        if src_dict['SpatialModel'] == 'Gaussian':
            kernel = utils.make_gaussian_kernel(src_dict['SpatialWidth'],
                                                cdelt=self.binsz,
                                                npix=101)
            kernel /= np.sum(kernel)
            cpix = [50, 50]

        self.add_source('residmap_testsource',
                        src_dict,
                        free=True,
                        init_source=False,
                        save_source_maps=False)
        src = self.roi.get_source_by_name('residmap_testsource')

        modelname = utils.create_model_name(src)

        mmst = np.zeros(self.npix[::-1])
        cmst = np.zeros(self.npix[::-1])
        emst = np.zeros(self.npix[::-1])

        sm = get_source_kernel(self, 'residmap_testsource', kernel)
        ts = np.zeros(self.npix[::-1])
        sigma = np.zeros(self.npix[::-1])
        excess = np.zeros(self.npix[::-1])

        self.delete_source('residmap_testsource')

        for i, c in enumerate(self.components):

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            mc = c.model_counts_map(exclude=exclude).data.astype('float')
            cc = c.counts_map().data.astype('float')
            ec = np.ones(mc.shape)

            if use_weights:
                wmap = c.weight_map().data
                mask = np.where(wmap > 0, 1., 0.)
            else:
                wmap = None
                mask = None

            ccs = convolve_map(cc,
                               sm[i],
                               cpix,
                               imin=imin,
                               imax=imax,
                               wmap=wmap)
            mcs = convolve_map(mc,
                               sm[i],
                               cpix,
                               imin=imin,
                               imax=imax,
                               wmap=wmap)
            ecs = convolve_map(ec,
                               sm[i],
                               cpix,
                               imin=imin,
                               imax=imax,
                               wmap=wmap)

            cms = np.sum(ccs, axis=0)
            mms = np.sum(mcs, axis=0)
            ems = np.sum(ecs, axis=0)

            cmst += cms
            mmst += mms
            emst += ems

            # cts = 2.0 * (poisson_lnl(cms, cms) - poisson_lnl(cms, mms))
            excess += cms - mms

        ts = 2.0 * (poisson_lnl(cmst, cmst) - poisson_lnl(cmst, mmst))
        sigma = np.sqrt(ts)
        sigma[excess < 0] *= -1
        emst /= np.max(emst)

        sigma_map = WcsNDMap(geom, sigma)
        model_map = WcsNDMap(geom, mmst / emst)
        data_map = WcsNDMap(geom, cmst / emst)
        excess_map = WcsNDMap(geom, excess / emst)

        o = {
            'name': utils.join_strings([prefix, modelname]),
            'projtype': 'WCS',
            'file': None,
            'sigma': sigma_map,
            'model': model_map,
            'data': data_map,
            'excess': excess_map,
            'mask': mask,
            'config': kwargs
        }

        return o
Beispiel #11
0
exposure_hpx.plot();


# In[ ]:


# For exposure, we choose a geometry with node_type='center',
# whereas for counts it was node_type='edge'
axis = MapAxis.from_nodes(
    counts.geom.axes[0].center, name="energy", unit="GeV", interp="log"
)
geom = WcsGeom(wcs=counts.geom.wcs, npix=counts.geom.npix, axes=[axis])

coord = counts.geom.get_coord()
data = exposure_hpx.interp_by_coord(coord)
exposure = WcsNDMap(geom, data, unit=exposure_hpx.unit)
print(exposure.geom)
print(exposure.geom.axes[0])


# In[ ]:


# Exposure is almost constant accross the field of view
exposure.slice_by_idx({"energy": 0}).plot(add_cbar=True);


# In[ ]:


# Exposure varies very little with energy at these high energies
# 
# Exclusion mask currently unused. Remove here or move to later in the tutorial?

# In[ ]:


target_position = SkyCoord(0, 0, unit="deg", frame="galactic")
on_radius = 0.2 * u.deg
on_region = CircleSkyRegion(center=target_position, radius=on_radius)


# In[ ]:


exclusion_mask = geom.to_image().region_mask([on_region], inside=False)
exclusion_mask = WcsNDMap(geom.to_image(), exclusion_mask)
exclusion_mask.plot();


# In[ ]:


get_ipython().run_cell_magic('time', '', 'maker = MapMaker(geom, offset_max="2 deg")\nmaps = maker.run(observations)\nprint(maps.keys())')


# In[ ]:


# The maps are cubes, with an energy axis.
# Let's also make some images:
images = maker.run_images()
Beispiel #13
0

# Define some observation parameters
# we are not simulating many pointings / observations
pointing = SkyCoord(0.2, 0.5, unit="deg", frame="galactic")
livetime = 20 * u.hour

exposure_map = make_map_exposure_true_energy(
    pointing=pointing, livetime=livetime, aeff=aeff, geom=geom
)

evaluator = MapEvaluator(model=compound_model, exposure=exposure_map)


npred = evaluator.compute_npred()
npred_map = WcsNDMap(geom, npred)

fig, ax, cbar = npred_map.sum_over_axes().plot(add_cbar=True)
ax.scatter(
    [lon_0_1, lon_0_2, pointing.galactic.l.degree],
    [lat_0_1, lat_0_2, pointing.galactic.b.degree],
    transform=ax.get_transform("galactic"),
    marker="+",
    color="cyan",
)
# plt.show()
plt.clf()

rng = get_random_state(42)
counts = rng.poisson(npred)
counts_map = WcsNDMap(geom, counts)
Beispiel #14
0
def test_plot():
    m = WcsNDMap.create(binsz=0.1 * u.deg, width=1 * u.deg)
    with mpl_plot_check():
        m.plot(add_cbar=True)
Beispiel #15
0

# Define some observation parameters
# we are not simulating many pointings / observations
pointing = SkyCoord(0.2, 0.5, unit="deg", frame="galactic")
livetime = 20 * u.hour

exposure_map = make_map_exposure_true_energy(
    pointing=pointing, livetime=livetime, aeff=aeff, geom=geom
)

evaluator = MapEvaluator(model=models, exposure=exposure_map)


npred = evaluator.compute_npred()
npred_map = WcsNDMap(geom, npred)

fig, ax, cbar = npred_map.sum_over_axes().plot(add_cbar=True)
ax.scatter(
    [lon_0_1, lon_0_2, pointing.galactic.l.degree],
    [lat_0_1, lat_0_2, pointing.galactic.b.degree],
    transform=ax.get_transform("galactic"),
    marker="+",
    color="cyan",
)
# plt.show()
plt.clf()

rng = get_random_state(42)
counts = rng.poisson(npred)
counts_map = WcsNDMap(geom, counts)
Beispiel #16
0
def test_wcsndmap_read_write(tmpdir, npix, binsz, coordsys, proj, skydir,
                             axes):
    geom = WcsGeom.create(npix=npix,
                          binsz=binsz,
                          proj=proj,
                          coordsys=coordsys,
                          axes=axes)
    filename = str(tmpdir / "map.fits")

    m0 = WcsNDMap(geom)
    fill_poisson(m0, mu=0.5)
    m0.write(filename, overwrite=True)
    m1 = WcsNDMap.read(filename)
    m2 = Map.read(filename)
    m3 = Map.read(filename, map_type="wcs")
    assert_allclose(m0.data, m1.data)
    assert_allclose(m0.data, m2.data)
    assert_allclose(m0.data, m3.data)

    m0.write(filename, sparse=True, overwrite=True)
    m1 = WcsNDMap.read(filename)
    m2 = Map.read(filename)
    m3 = Map.read(filename, map_type="wcs")
    assert_allclose(m0.data, m1.data)
    assert_allclose(m0.data, m2.data)
    assert_allclose(m0.data, m3.data)

    # Specify alternate HDU name for IMAGE and BANDS table
    m0.write(filename, hdu="IMAGE", hdu_bands="TEST", overwrite=True)
    m1 = WcsNDMap.read(filename)
    m2 = Map.read(filename)
    m3 = Map.read(filename, map_type="wcs")
Beispiel #17
0
def test_wcsndmap_set_get_by_coord(npix, binsz, coordsys, proj, skydir, axes):
    geom = WcsGeom.create(npix=npix,
                          binsz=binsz,
                          skydir=skydir,
                          proj=proj,
                          coordsys=coordsys,
                          axes=axes)
    m = WcsNDMap(geom)
    coords = m.geom.get_coord()
    m.set_by_coord(coords, coords[0])
    assert_allclose(coords[0], m.get_by_coord(coords))

    if not geom.is_allsky:
        coords[1][...] = 0.0
        assert_allclose(np.nan * np.ones(coords[0].shape),
                        m.get_by_coord(coords))

    # Test with SkyCoords
    m = WcsNDMap(geom)
    coords = m.geom.get_coord()
    skydir = SkyCoord(coords[0],
                      coords[1],
                      unit="deg",
                      frame=coordsys_to_frame(geom.coordsys))
    skydir_cel = skydir.transform_to("icrs")
    skydir_gal = skydir.transform_to("galactic")

    m.set_by_coord((skydir_gal, ) + tuple(coords[2:]), coords[0])
    assert_allclose(coords[0], m.get_by_coord(coords))
    assert_allclose(
        m.get_by_coord((skydir_cel, ) + tuple(coords[2:])),
        m.get_by_coord((skydir_gal, ) + tuple(coords[2:])),
    )

    # Test with MapCoord
    m = WcsNDMap(geom)
    coords = m.geom.get_coord()
    coords_dict = dict(lon=coords[0], lat=coords[1])
    if axes:
        for i, ax in enumerate(axes):
            coords_dict[ax.name] = coords[i + 2]
    map_coords = MapCoord.create(coords_dict, coordsys=coordsys)
    m.set_by_coord(map_coords, coords[0])
    assert_allclose(coords[0], m.get_by_coord(map_coords))
Beispiel #18
0
    def estimate_maps(self, dataset):
        """Run adaptive smoothing on input Maps.

        Parameters
        ----------
        dataset : `MapDataset`
            Dataset

        Returns
        -------
        images : dict of `~gammapy.maps.WcsNDMap`
            Smoothed images; keys are:
                * 'counts'
                * 'background'
                * 'flux' (optional)
                * 'scales'
                * 'sqrt_ts'.
        """
        dataset_image = dataset.to_image(name=dataset.name)
        dataset_image.models = dataset.models

        # extract 2d arrays
        counts = dataset_image.counts.data[0].astype(float)
        background = dataset_image.npred_background().data[0]

        if isinstance(dataset_image, MapDatasetOnOff):
            background = dataset_image.background.data[0]

        if dataset_image.exposure is not None:
            exposure = estimate_exposure_reco_energy(dataset_image,
                                                     self.spectrum)
        else:
            exposure = None

        pixel_scale = dataset_image.counts.geom.pixel_scales.mean()
        kernels = self.get_kernels(pixel_scale)

        cubes = {}
        cubes["counts"] = scale_cube(counts, kernels)
        cubes["background"] = scale_cube(background, kernels)

        if exposure is not None:
            flux = (dataset_image.counts - background) / exposure
            cubes["flux"] = scale_cube(flux.data[0], kernels)

        cubes["sqrt_ts"] = self._sqrt_ts_cube(cubes, method=self.method)

        smoothed = self._reduce_cubes(cubes, kernels)

        result = {}

        geom = dataset_image.counts.geom

        for name, data in smoothed.items():
            # set remaining pixels with sqrt_ts < threshold to mean value
            if name in ["counts", "background"]:
                mask = np.isnan(data)
                data[mask] = np.mean(locals()[name][mask])
                result[name] = WcsNDMap(geom, data, unit="")
            else:
                unit = "deg" if name == "scale" else ""
                result[name] = WcsNDMap(geom, data, unit=unit)

        if exposure is not None:
            data = smoothed["flux"]
            mask = np.isnan(data)
            data[mask] = np.mean(flux.data[0][mask])
            result["flux"] = WcsNDMap(geom, data, unit=flux.unit)

        return result
"""Example how to compute and plot reflected regions."""
import matplotlib.pyplot as plt
import numpy as np
from astropy.coordinates import SkyCoord, Angle
from regions import CircleSkyRegion
from gammapy.maps import WcsNDMap
from gammapy.background import ReflectedRegionsFinder

# Exclude a rectangular region
exclusion_mask = WcsNDMap.create(npix=(801, 701), binsz=0.01, skydir=(83.6, 23.0))

coords = exclusion_mask.geom.get_coord().skycoord
mask = (Angle("23d") < coords.dec) & (coords.dec < Angle("24d"))
exclusion_mask.data = np.invert(mask)

pos = SkyCoord(83.633, 22.014, unit="deg")
radius = Angle(0.3, "deg")
on_region = CircleSkyRegion(pos, radius)
center = SkyCoord(83.633, 24, unit="deg")

# One can impose a minimal distance between ON region and first reflected regions
finder = ReflectedRegionsFinder(
    region=on_region,
    center=center,
    exclusion_mask=exclusion_mask,
    min_distance_input="0.2 rad",
)
finder.run()

fig1 = plt.figure(1)
finder.plot(fig=fig1)
Beispiel #20
0
profile.scale_to_local_density()

position = SkyCoord(0.0, 0.0, frame="galactic", unit="deg")
geom = WcsGeom.create(binsz=0.05, skydir=position, width=3.0, coordsys="GAL")

# In[ ]:

jfactory = JFactory(geom=geom,
                    profile=profile,
                    distance=profiles.DMProfile.DISTANCE_GC)
jfact = jfactory.compute_jfactor()

# In[ ]:

jfact_map = WcsNDMap(geom=geom, data=jfact.value, unit=jfact.unit)
fig, ax, im = jfact_map.plot(cmap="viridis", norm=LogNorm(), add_cbar=True)
plt.title("J-Factor [{}]".format(jfact_map.unit))

# 1 deg circle usually used in H.E.S.S. analyses
sky_reg = CircleSkyRegion(center=position, radius=1 * u.deg)
pix_reg = sky_reg.to_pixel(wcs=geom.wcs)
pix_reg.plot(ax=ax, facecolor="none", edgecolor="red", label="1 deg circle")
plt.legend()

# In[ ]:

# NOTE: https://arxiv.org/abs/1607.08142 quote 2.67e21 without the +/- 0.3 deg band around the plane
total_jfact = pix_reg.to_mask().multiply(jfact).sum()
print("J-factor in 1 deg circle around GC assuming a "
      "{} is {:.3g}".format(profile.__class__.__name__, total_jfact))
Beispiel #21
0
def test_wcsndmap_crop(npix, binsz, frame, proj, skydir, axes):
    geom = WcsGeom.create(npix=npix, binsz=binsz, proj=proj, frame=frame, axes=axes)
    m = WcsNDMap(geom)
    m.crop(1)
Beispiel #22
0
def test_plot_allsky():
    axis = MapAxis([0, 1], node_type="edges")
    m = WcsNDMap.create(binsz=10 * u.deg, axes=[axis])
    with mpl_plot_check():
        m.plot()
Beispiel #23
0
def test_wcsndmap_upsample(npix, binsz, frame, proj, skydir, axes):
    geom = WcsGeom.create(npix=npix, binsz=binsz, proj=proj, frame=frame, axes=axes)
    m = WcsNDMap(geom, unit="m2")
    m2 = m.upsample(2, preserve_counts=True)
    assert_allclose(np.nansum(m.data), np.nansum(m2.data))
    assert m.unit == m2.unit
npred = dataset.npred()

# In[ ]:

npred.sum_over_axes().plot(add_cbar=True)

# In[ ]:

# This one line is the core of how to simulate data when
# using binned simulation / analysis: you Poisson fluctuate
# npred to obtain simulated observed counts.
# Compute counts as a Poisson fluctuation
rng = np.random.RandomState(seed=42)
counts = rng.poisson(npred.data)
counts_map = WcsNDMap(geom, counts)

# In[ ]:

counts_map.sum_over_axes().plot()

# ## Fit
#
# Now let's analyse the simulated data.
# Here we just fit it again with the same model we had before, but you could do any analysis you like here, e.g. fit a different model, or do a region-based analysis, ...

# In[ ]:

# Define sky model to fit the data
spatial_model = SkyGaussian(lon_0="0.1 deg", lat_0="0.1 deg", sigma="0.5 deg")
spectral_model = PowerLaw(index=2,
Beispiel #25
0
def to_cube(image):
    # introduce a fake enery axis for now
    axis = MapAxis.from_edges([1, 10] * u.TeV, name="energy")
    geom = image.geom.to_cube([axis])
    return WcsNDMap.from_geom(geom=geom, data=image.data)
Beispiel #26
0
def test_wcsndmap_set_get_by_coord(npix, binsz, frame, proj, skydir, axes):
    geom = WcsGeom.create(npix=npix,
                          binsz=binsz,
                          skydir=skydir,
                          proj=proj,
                          frame=frame,
                          axes=axes)
    m = WcsNDMap(geom)
    coords = m.geom.get_coord()
    m.set_by_coord(coords, coords[0])
    assert_allclose(coords[0].value, m.get_by_coord(coords))

    # Test with SkyCoords
    m = WcsNDMap(geom)
    coords = m.geom.get_coord()
    skydir = coords.skycoord
    skydir_cel = skydir.transform_to("icrs")
    skydir_gal = skydir.transform_to("galactic")

    m.set_by_coord((skydir_gal, ) + tuple(coords[2:]), coords[0])
    assert_allclose(coords[0].value, m.get_by_coord(coords))
    assert_allclose(
        m.get_by_coord((skydir_cel, ) + tuple(coords[2:])),
        m.get_by_coord((skydir_gal, ) + tuple(coords[2:])),
    )

    # Test with MapCoord
    m = WcsNDMap(geom)
    coords = m.geom.get_coord()
    coords_dict = dict(lon=coords[0], lat=coords[1])
    if axes:
        for i, ax in enumerate(axes):
            coords_dict[ax.name] = coords[i + 2]
    map_coords = MapCoord.create(coords_dict, frame=frame)
    m.set_by_coord(map_coords, coords[0])
    assert_allclose(coords[0].value, m.get_by_coord(map_coords))
Beispiel #27
0
def make_map():
    return WcsNDMap.create(skydir=config.source_pos,
                           proj="TAN",
                           width=8,
                           binsz=0.05)
Beispiel #28
0
def test_plot_allsky():
    m = WcsNDMap.create(binsz=10 * u.deg)
    with mpl_plot_check():
        m.plot()
Beispiel #29
0
on_ellipse_annulus = EllipseAnnulusSkyRegion(
    center=position,
    inner_width=1.5 * u.deg,
    outer_width=2.5 * u.deg,
    inner_height=3 * u.deg,
    outer_height=4 * u.deg,
    angle=130 * u.deg,
)

another_position = SkyCoord(80.3, 22.0, unit="deg")
on_rectangle = RectangleSkyRegion(center=another_position,
                                  width=2.0 * u.deg,
                                  height=4.0 * u.deg,
                                  angle=50 * u.deg)

# Now we plot those regions. We first create an empty map
empty_map = WcsNDMap.create(skydir=position,
                            width=10 * u.deg,
                            binsz=0.1 * u.deg,
                            proj="TAN")
empty_map.data += 1.0
empty_map.plot(cmap="gray", vmin=0, vmax=1)

# To plot the regions, we convert them to PixelRegion with the map wcs
on_circle.to_pixel(empty_map.geom.wcs).plot()
on_rectangle.to_pixel(empty_map.geom.wcs).plot()
on_ellipse_annulus.to_pixel(empty_map.geom.wcs).plot()

plt.show()
import matplotlib.pyplot as plt
from astropy.coordinates import Angle, SkyCoord
from regions import CircleSkyRegion
from gammapy.makers import ReflectedRegionsFinder
from gammapy.maps import WcsNDMap, RegionGeom

# Exclude a rectangular region
exclusion_mask = WcsNDMap.create(npix=(801, 701),
                                 binsz=0.01,
                                 skydir=(83.6, 23.0))

coords = exclusion_mask.geom.get_coord().skycoord
data = (Angle("23 deg") < coords.dec) & (coords.dec < Angle("24 deg"))
exclusion_mask.data = ~data

pos = SkyCoord(83.633, 22.014, unit="deg")
radius = Angle(0.3, "deg")
on_region = CircleSkyRegion(pos, radius)
center = SkyCoord(83.633, 24, unit="deg")

# One can impose a minimal distance between ON region and first reflected regions
finder = ReflectedRegionsFinder(
    region=on_region,
    center=center,
    exclusion_mask=exclusion_mask,
    min_distance_input="0.2 rad",
)
regions = finder.run()

fig, axes = plt.subplots(
    ncols=3,
Beispiel #31
0
def test_map_fill_events_keyerror(events):
    axis = MapAxis([0, 1, 2], name="nokey")
    m = WcsNDMap.create(binsz=0.1, npix=10, axes=[axis])
    with pytest.raises(KeyError):
        m.fill_events(events)
Beispiel #32
0
    def estimate_maps(self, counts, background, exposure=None):
        """
        Run adaptive smoothing on input Maps.

        Parameters
        ----------
        counts : `~gammapy.maps.Map`
            counts map
        background : `~gammapy.maps.Map`
            estimated background counts map
        exposure : `~gammapy.maps.Map`
            exposure map. If set, it will produce a flux smoothed map.

        Returns
        -------
        images : dict of `~gammapy.maps.WcsNDMap`
            Smoothed images; keys are:
                * 'counts'
                * 'background'
                * 'flux' (optional)
                * 'scales'
                * 'significance'.
        """

        pixel_scale = counts.geom.pixel_scales.mean()
        kernels = self.kernels(pixel_scale)

        cubes = {}
        cubes["counts"] = scale_cube(counts.data, kernels)

        if background is not None:
            cubes["background"] = scale_cube(background.data, kernels)
        else:
            # TODO: Estimate background with asmooth method
            raise ValueError("Background estimation required.")

        if exposure is not None:
            flux = (counts - background) / exposure
            cubes["flux"] = scale_cube(flux.data, kernels)

        cubes["significance"] = self._significance_cube(cubes,
                                                        method=self.method)

        smoothed = self._reduce_cubes(cubes, kernels)

        result = {}

        for key in ["counts", "background", "scale", "significance"]:
            data = smoothed[key]

            # set remaining pixels with significance < threshold to mean value
            if key in ["counts", "background"]:
                mask = np.isnan(data)
                data[mask] = np.mean(locals()[key].data[mask])
                result[key] = WcsNDMap(counts.geom, data, unit=counts.unit)
            else:
                result[key] = WcsNDMap(counts.geom, data, unit="deg")

        if exposure is not None:
            data = smoothed["flux"]
            mask = np.isnan(data)
            data[mask] = np.mean(flux.data[mask])
            result["flux"] = WcsNDMap(counts.geom, data, unit=flux.unit)

        return result
Beispiel #33
0
def simulate_dataset(
    skymodel,
    geom,
    pointing,
    irfs,
    livetime=1 * u.h,
    offset=0 * u.deg,
    max_radius=0.8 * u.deg,
    random_state="random-seed",
):
    """Simulate a 3D dataset.

    Simulate a source defined with a sky model for a given pointing,
    geometry and irfs for a given exposure time.
    This will return a dataset object which includes the counts cube,
    the exposure cube, the psf cube, the background model and the sky model.

    Parameters
    ----------
    skymodel : `~gammapy.modeling.models.SkyModel`
        Background model map
    geom : `~gammapy.maps.WcsGeom`
        Geometry object for the observation
    pointing : `~astropy.coordinates.SkyCoord`
        Pointing position
    irfs : dict
        Irfs used for simulating the observation
    livetime : `~astropy.units.Quantity`
        Livetime exposure of the simulated observation
    offset : `~astropy.units.Quantity`
        Offset from the center of the pointing position.
        This is used for the PSF and Edisp estimation
    max_radius : `~astropy.coordinates.Angle`
        The maximum radius of the PSF kernel.
    random_state: {int, 'random-seed', 'global-rng', `~numpy.random.RandomState`}
        Defines random number generator initialisation.

    Returns
    -------
    dataset : `~gammapy.cube.MapDataset`
        A dataset of the simulated observation.
    """
    background = make_map_background_irf(
        pointing=pointing, ontime=livetime, bkg=irfs["bkg"], geom=geom
    )

    background_model = BackgroundModel(background)

    psf = irfs["psf"].to_energy_dependent_table_psf(theta=offset)
    psf_kernel = PSFKernel.from_table_psf(psf, geom, max_radius=max_radius)

    exposure = make_map_exposure_true_energy(
        pointing=pointing, livetime=livetime, aeff=irfs["aeff"], geom=geom
    )

    if "edisp" in irfs:
        energy = geom.axes[0].edges
        edisp = irfs["edisp"].to_energy_dispersion(offset, e_reco=energy, e_true=energy)
    else:
        edisp = None

    dataset = MapDataset(
        model=skymodel,
        exposure=exposure,
        background_model=background_model,
        psf=psf_kernel,
        edisp=edisp,
    )

    npred_map = dataset.npred()
    rng = get_random_state(random_state)
    counts = rng.poisson(npred_map.data)
    dataset.counts = WcsNDMap(geom, counts)

    return dataset