def test_wcsndmap_fill_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() fill_coords = tuple([np.concatenate((t, t)) for t in coords]) fill_vals = fill_coords[1] m.fill_by_coord(fill_coords, fill_vals) assert_allclose(m.get_by_coord(coords), 2.0 * coords[1]) # 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") fill_coords_cel = (skydir_cel, ) + tuple(coords[2:]) fill_coords_gal = (skydir_gal, ) + tuple(coords[2:]) m.fill_by_coord(fill_coords_cel, coords[1]) m.fill_by_coord(fill_coords_gal, coords[1]) assert_allclose(m.get_by_coord(coords), 2.0 * coords[1])
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))
def test_hpxmap_set_get_by_coord(nside, nested, coordsys, region, axes): m = create_map(nside, nested, coordsys, region, axes) coords = m.geom.get_coord(flat=True) m.set_by_coord(coords, coords[0]) assert_allclose(coords[0], m.get_by_coord(coords)) # Test with SkyCoords m = create_map(nside, nested, coordsys, region, axes) coords = m.geom.get_coord(flat=True) skydir = SkyCoord(coords[0], coords[1], unit="deg", frame=coordsys_to_frame(m.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:])), )
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
def _make_ts_cube(self, prefix, **kwargs): map_skydir = kwargs.get('map_skydir') map_size = kwargs.get('map_size') exclude = kwargs.get('exclude', []) # We take the coordinate system and the bin size from the underlying map skywcs = self._geom.wcs galactic = wcs_utils.is_galactic(skywcs) pixsize = max(np.abs(skywcs.wcs.cdelt)) # If the map_size is not specified we need to find the right number of pixels if map_size is None: npix = max(self._geom.npix)[0] map_size = pixsize * npix else: npix = int(np.round(map_size / pixsize)) saved_state = LikelihoodState(self.like) for ex_src in exclude: self.zero_source(ex_src) if map_skydir is None: # Take the center of the wcs map_geom = self._geom.to_image() frame = coordsys_to_frame(map_geom.coordsys) map_skydir = SkyCoord(*map_geom.pix_to_coord( self._geom.wcs.wcs.crpix), frame=frame, unit='deg') map_skydir = map_skydir.transform_to('icrs') refdir = pyLike.SkyDir(map_skydir.ra.deg, map_skydir.dec.deg) src_dict = copy.deepcopy(kwargs.setdefault('model', {})) src_dict = {} if src_dict is None else src_dict src_dict['ra'] = map_skydir.ra.deg src_dict['dec'] = map_skydir.dec.deg src_dict.setdefault('SpatialModel', 'PointSource') src_dict.setdefault('SpatialWidth', 0.3) src_dict.setdefault('Index', 2.0) src_dict.setdefault('Prefactor', 1.0) src_dict['name'] = 'tscube_testsource' src = Source.create_from_dict(src_dict) if 'Prefactor' in src.spectral_pars: src.spectral_pars['Prefactor']['scale'] = 1.0e-10 modelname = utils.create_model_name(src) pylike_src = self.components[0]._create_source(src) pylike_src.spectrum().normPar().setBounds(0, 1E6) skyproj = pyLike.FitScanner.buildSkyProj(str("AIT"), refdir, pixsize, npix, galactic) optFactory = pyLike.OptimizerFactory_instance() optObject = optFactory.create(str("MINUIT"), self.like.composite) fitScanner = pyLike.FitScanner(self.like.composite, optObject, skyproj, npix, npix) fitScanner.set_quiet(True) fitScanner.setTestSource(pylike_src) self.logger.info("Running tscube") outfile = utils.format_filename(self.config['fileio']['workdir'], 'tscube.fits', prefix=[prefix]) fitScanner.run_tscube(True, kwargs['do_sed'], kwargs['nnorm'], kwargs['norm_sigma'], kwargs['cov_scale_bb'], kwargs['cov_scale'], kwargs['tol'], kwargs['max_iter'], kwargs['tol_type'], kwargs['remake_test_source'], kwargs['st_scan_level'], str(''), kwargs['init_lambda']) self.logger.info("Writing FITS output") fitScanner.writeFitsFile(str(outfile), str("gttscube"), "", False, pyLike.FitScanner.TSMAP_ONLY) saved_state.restore() convert_tscube(str(outfile), str(outfile)) tscube = castro.TSCube.create_from_fits(outfile) ts_map = tscube.tsmap norm_map = tscube.normmap npred_map = copy.deepcopy(norm_map) npred_map.data *= tscube.refSpec.ref_npred.sum() amp_map = copy.deepcopy(norm_map) amp_map.data *= pylike_src.spectrum().normPar().getValue() sqrt_ts_map = copy.deepcopy(ts_map) sqrt_ts_map.data[...] = np.abs(sqrt_ts_map.data)**0.5 o = { 'name': utils.join_strings([prefix, modelname]), 'src_dict': copy.deepcopy(src_dict), 'file': os.path.basename(outfile), 'ts': ts_map, 'sqrt_ts': sqrt_ts_map, 'npred': npred_map, 'amplitude': amp_map, 'config': kwargs, 'tscube': tscube } if not kwargs['write_fits']: os.remove(outfile) o['file'] = None self.logger.info("Done") return o
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