def _cone(config, source, nest=True): # cone geometry stuff: get corresponding pixels and center vector l, b, radius = source.l, source.b, config.radius cart = lambda l, b: healpy.dir2vec(l, b, lonlat=True) conepix = healpy.query_disc(config.nside, cart(l, b), np.radians(radius), nest=nest) center = healpy.dir2vec(l, b, lonlat=True) return center, conepix
def _load_photon_data(self, filename, gti): """Read in, process a file generated by binned_data.ConvertFT1.time_record return DataFrame with times, band id, distance from center parameters: filename : file name gti : GTI object for filtering data returns: DataFrame with columns: band : from input, energy and event type time : Mission Elapsed Time in MJD (double) radius : radial distance from input position (deg, float32) """ l,b,radius = self.l, self.b, self.radius if self.verbose>2: print(f'loading file {filename}') with open(filename,'rb') as f: d = pickle.load( f ,encoding='latin1') tstart = d['tstart'] if self.mjd_range is not None and MJD(tstart) > self.mjd_range[1]: return None df = pd.DataFrame(d['timerec']) # cartesian vector from l,b for healpy stuff cart = lambda l,b: healpy.dir2vec(l,b, lonlat=True) # use query_disc to get photons within given radius of position center = healpy.dir2vec(l,b, lonlat=True) #cart(l,b) ipix = healpy.query_disc(self.nside, cart(l,b), np.radians(radius), nest=False) incone = np.isin(df.hpindex, ipix) # times: convert to double, add to start, convert to MJD t = MJD(np.array(df.time[incone],float)+tstart) in_gti = gti(t) if np.sum(in_gti)==0: return None # generate radial distance from center from position hpindex = df.hpindex[incone][in_gti] ll,bb = healpy.pix2ang(self.nside, hpindex, nest=False, lonlat=True) t2 = np.array(np.sqrt((1.-np.dot(center, cart(ll,bb)))*2), np.float32) out_df = pd.DataFrame(np.rec.fromarrays( [df.band[incone][in_gti], t[in_gti], hpindex, np.degrees(t2)], names='band time pixel radius'.split())) return out_df
def min_sso_dist(el, azmin, azmax, sso_el1, sso_az1, sso_el2, sso_az2): """Return a rough minimum angular distance between the bore sight and a solar system object""" sso_vec1 = hp.dir2vec(sso_az1, sso_el1, lonlat=True) sso_vec2 = hp.dir2vec(sso_az2, sso_el2, lonlat=True) az1 = azmin az2 = azmax if az2 < az1: az2 += 360 n = 100 az = np.linspace(az1, az2, n) el = np.ones(n) * el vec = hp.dir2vec(az, el, lonlat=True) dist1 = np.degrees(np.arccos(np.dot(sso_vec1, vec))) dist2 = np.degrees(np.arccos(np.dot(sso_vec2, vec))) return min(np.amin(dist1), np.amin(dist2))
def label_visits(visits, wfd_footprint, nside=64): # Set up DD names. d = set() for p in visits['note'].unique(): if p.startswith('DD'): d.add(define_ddname(p)) # Define dictionary of proposal tags. propTags = {'Other': 0, 'WFD': 1} for i, field in enumerate(d): propTags[field] = i + 2 # Identify Healpixels associated with each visit. vec = hp.dir2vec(visits['fieldRA'], visits['fieldDec'], lonlat=True) vec = vec.swapaxes(0, 1) radius = np.radians(1.75) # fov radius #pointings = [] propId = np.zeros(len(visits), int) for i, (v, note) in enumerate(zip(vec, visits['note'])): # Identify the healpixels which would be inside this pointing pointing_healpix = hp.query_disc(nside, v, radius, inclusive=False) # This can be useful for debugging/plotting #pointings.append(pointing_healpix) # The wfd_footprint consists of values of 0/1 if out/in WFD footprint in_wfd = wfd_footprint[pointing_healpix].sum() # So in_wfd = the number of healpixels which were in the WFD footprint # .. in the # in / total # > limit (0.4) then "yes" it's in WFD propId[i] = np.where(in_wfd / len(pointing_healpix) > 0.4, propTags['WFD'], 0) # BUT override - if the visit was taken for DD, use that flag instead. if note.startswith('DD'): propId[i] = propTags[define_ddname(note)] return visits, propTags, propId
def __init__(self, outdir, nside, roi_nside=12, **kwargs): self.subdirfun = Band(nside).dir disc_info = kwargs.pop('disc_info', ()) # allow arbitraty disk, rather than just within a ROI active boundary if disc_info: l, b, r = disc_info vec = healpy.dir2vec(l, b, lonlat=True) index_list = healpy.query_disc(nside=nside, vec=vec, radius=np.radians(r), nest=False) self.pos_list = [self.subdirfun(int(i)) for i in index_list] else: self.index_table = make_index_table(roi_nside, nside) self.skyfuns = kwargs.pop( 'skyfuns', ( ( ResidualTS, 'ts', dict(photon_index=2.3), ), (KdeMap, 'kde', dict()), ), ) self.subdirs = [ os.path.join(outdir, name + '_table_%d' % nside) for s, name, kw in self.skyfuns ] for subdir in self.subdirs: if not os.path.exists(subdir): os.makedirs(subdir)
def TopHatSmooth(nside, origMap, radius, average=False): pixelList = [] dsum = 0.0 newmap = np.zeros(len(origMap)) # Loop over all pixels for ipix in range(0, len(origMap)): theta, phi = H.pix2ang(nside, ipix) center = H.dir2vec(theta, phi) # Grab pixels with given angular radius of ith pixel pixelList = H.query_disc(nside, center, radius) #Sum up pixels in the angular cap; set value of ith pixel to this sum dsum = 0. nsum = 0. for jpix in pixelList: if origMap[jpix] != H.UNSEEN: dsum += origMap[jpix] nsum += 1.0 if average and nsum > 0: newmap[ipix] = dsum / nsum # set to average else: newmap[ipix] = dsum return newmap
def cosdist_vec(self, vec, timestamps, full_output=False): """ Return the cosine of the angular distance between the target and pointing direction """ if timestamps[0] > self.time[-1] or timestamps[-1] < self.time[0]: raise Exception( 'There is no overlap in the stored and provided time stamps.') tol = 3600. ind = np.logical_and(self.time >= timestamps[0] - tol, self.time <= timestamps[-1] + tol) planettime = self.time[ind] planetglon_temp = self.glon[ind] planetglat_temp = self.glat[ind] planetglon = np.interp(timestamps, planettime, planetglon_temp) planetglat = np.interp(timestamps, planettime, planetglat_temp) planetvec = hp.dir2vec(planetglon, planetglat, lonlat=True) cosdist = np.sum(vec * planetvec, axis=0) if full_output: return cosdist, planetvec else: return cosdist
def generate_point_set(self) -> Tuple[np.ndarray, np.ndarray]: rng = np.random.default_rng(self.seed) lon = 360 * rng.random(size=self.resolution) - 180 uniform = rng.random(size=self.resolution) lat = np.arcsin(2 * uniform - 1) * 180 / np.pi vec = hp.dir2vec(theta=lon, phi=lat, lonlat=True) dir = hp.vec2dir(vec, lonlat=self.lonlat) return vec, dir
def generate_point_set(self) -> Tuple[np.ndarray, np.ndarray]: step = np.arange(self.resolution) phi = step * self.golden_angle phi = Angle(phi * u.rad).wrap_at(2 * np.pi * u.rad) theta = np.arccos(1 - (2 * step / self.resolution)) vec = hp.dir2vec(theta=theta, phi=phi, lonlat=False) dir = hp.vec2dir(vec, lonlat=self.lonlat) return vec, dir
def get_tiling(lon0, lat0, dlon, dlat): rot = hp.rotator.Rotator(rot=(0., -lat0, -lon0), eulertype='Y', deg=True).mat x = hp.dir2vec(dlon, dlat, lonlat=True) if hasattr(dlon, '__len__') and (len(x.shape) == 1): x.shape = (3, 1) y = np.einsum('ij,jn', rot, x) lonlat = hp.vec2dir(y, lonlat=True) return lonlat
def A_wrt_dir(map1, direction, LMAX, LMIN=2, deg=90.): """ get the Cl power asymmetry wrt to the direction specified """ if len(direction) == 2: direction = hp.dir2vec(direction[0], direction[1], lonlat=True) Clsp, Clsm = get_hem_Cls(map1, direction, LMAX, deg) return weightedA(Clsp[LMIN:], Clsm[LMIN:])
def get_tiling(lon0, lat0, dlon, dlat): rot = hp.rotator.Rotator(rot=(0., -lat0, -lon0), eulertype='Y', deg=True).mat x = hp.dir2vec(dlon, dlat, lonlat=True) if hasattr(dlon, '__len__') and (len(x.shape) == 1): x.shape = (3,1) y = np.einsum('ij,jn', rot, x) lonlat = hp.vec2dir(y, lonlat=True) return lonlat
def solid_angle(self): sd = self.skydir try: nside = self.cband.nside() npix = len( healpy.query_disc(nside, healpy.dir2vec(sd.l(), sd.b(), lonlat=True), self.radius_in_rad)) return npix * self.pixel_area except ValueError: return np.pi * self.radius_in_rad**2
def RADECToPatch(nside, RA, DEC=None, nest=False, lonlat=True, invRotMat=np.diag(np.ones(3))): if DEC is None: DEC = RA[1] RA = RA[0] uXYZ = hp.dir2vec(RA, DEC, lonlat=lonlat) uXYZ = invRotMat.dot(uXYZ) patch = hp.vec2pix(nside, uXYZ[0], uXYZ[1], uXYZ[2], nest=nest) return patch
def radec_to_vec(ra, dec): assert 0 <= ra <= 360 assert -90 <= dec <= 90 # Healpix uses the convention -180 - 180 for longitude, instead # we get RA between 0 and 360, so we need to wrap wrap_angle = 180.0 lon = np.mod(ra - wrap_angle, 360.0) - (360.0 - wrap_angle) vec = hp.dir2vec(lon, dec, lonlat=True) return vec
def initialize(self, force=False): if self.setup and not force: return self.setup = True #set up the spatial model self.dmodel = self.source.dmodel[self.band.event_type] self.dmodel.load() self.energy = self.band.energy self.dmodel.setEnergy(self.band.energy) roi_index = skymaps.Band(12).index(self.roicenter) self._keyword_check(roi_index) if getattr(self, 'preconvolved', False): #print 'Using preconvolved' c = self.roicenter cv = healpy.dir2vec(c.l(), c.b(), lonlat=True) hplist = healpy.query_disc(self.dmodel.nside, cv, self.band.radius_in_rad) smband = skymaps.Band(self.dmodel.nside) assert smband.index( self.roicenter ) in hplist, 'Problem HEALPix indexing, ROI center not consistent?' if self.dmodel.hdulist[1].header.get('TUNIT1', None) == 'photons': #must rescale from photons/pixel to density: photons/Mev/Sr scale_factor = (self.band.emax - self.band.emin) * smband.pixelArea() else: scale_factor = 1 dirs = map(self.dmodel.dirfun, hplist) self.evalpoints = lambda dirs: np.array(map( self.dmodel, dirs)) * self.corr / scale_factor self.ap_average = self.evalpoints(dirs).mean() # **** scale by years **** self.ap_average *= self.years / 10. else: self.create_grid() # will raise exception if no overlap grid = self.grid inside = grid.dists < self.band.radius_in_rad self.ap_average = grid.cvals[inside].mean() self.evalpoints = lambda dirs: grid(dirs, grid.cvals) self.delta_e = self.band.emax - self.band.emin self.factor = self.ap_average * self.band.solid_angle * self.delta_e if self.band.has_pixels: self.pixel_values = self.evalpoints( self.band.wsdl) * self.band.pixel_area * self.delta_e self.evaluate()
def cosdist(self, theta, phi, timestamps): """ Return the cosine of the angular distance between the target and pointing direction (theta, phi) Inputs are in radians. """ if theta.ptp() > np.pi or phi.ptp() > 4 * np.pi: print('WARNING: theta and/or phi have large scatter. ' 'They are expected to be in radians.') vec = hp.dir2vec(theta, phi) cosdist = self.cosdist_vec(vec, timestamps) return cosdist
def make_weights(self, ): if self.verbose > 0: print 'Generating pixels with weights for {} energies'.format( len(self.energy_bins)) # direection of source source_dir = self.source.skydir source_index = self.roi.sources.selected_source_index def weight(band, skydir): f = band.fluxes(skydir) # fluxes for all sources at the position return f[source_index] / sum(f) # use query_disc to get NEST pixel numbers within given radius of position # order them for easier search later l, b = source_dir.l(), source_dir.b() center = healpy.dir2vec(l, b, lonlat=True) pix_nest = np.sort( healpy.query_disc(self.nside, center, np.radians(self.radius), nest=True)) # convert to skydirs using pointlike code, which assumes RING bdir = Band(self.nside).dir pix_ring = healpy.nest2ring(self.nside, pix_nest) pixel_dirs = map(bdir, pix_ring) # and get distances pixel_dist = np.array(map(source_dir.difference, pixel_dirs)) if self.verbose > 0: print 'Using {} nside={} pixels. distance range {:.2f} to {:.2f} deg'.format( len(pix_nest), self.nside, np.degrees(pixel_dist.min()), np.degrees(pixel_dist.max())) # now loop over the bands and all pixels wt_dict = dict() for band in self.roi: # loop over BandLike objects ie = np.searchsorted(self.energy_bins, band.band.energy) - 1 band_id = 2 * ie + band.band.event_type if self.verbose > 1: print '{}'.format(band_id), wt_dict[band_id] = np.array( [weight(band, pd) for pd in pixel_dirs]).astype(np.float32) if self.verbose > 1: print return pix_nest, wt_dict
def load_photon_data(table, tstart): """For a given month table, select photons in cone, add tstart to times, return DataFrame with band, time, pixel, radius """ allpix = np.array(table.column('nest_index')) def cone_select(allpix, conepix, shift=None): """Fast cone selection using NEST and shift """ if shift is None: return np.isin(allpix, conepix) assert self.nest, 'Expect pixels to use NEST indexing' a = np.right_shift(allpix, shift) c = np.unique(np.right_shift(conepix, shift)) return np.isin(a,c) # a selection of all those in an outer cone incone = cone_select(allpix, conepix, 13) # times: convert to double, add to start, convert to MJD time = MJD(np.array(table['time'],float)[incone]+tstart) in_gti = self.gti(time) if np.sum(in_gti)==0: print(f'WARNING: no photons for month {month}!') pixincone = allpix[incone][in_gti] # distance from center for all accepted photons ll,bb = healpy.pix2ang(self.nside, pixincone, nest=self.nest, lonlat=True) cart = lambda l,b: healpy.dir2vec(l,b, lonlat=True) t2 = np.degrees(np.array(np.sqrt((1.-np.dot(center, cart(ll,bb)))*2), np.float32)) # assemble the DataFrame, remove those outside the radius out_df = pd.DataFrame(np.rec.fromarrays( [np.array(table['band'])[incone][in_gti], time[in_gti], pixincone, t2], names='band time pixel radius'.split())) # apply final selection for radius and energy range if band_limits is None: return out_df.query(f'radius<{radius}') return out_df.query(f'radius<{radius} & {band_limits[0]} < band < {band_limits[1]}')
def hp_in_cap(nside, radecrad, inclusive=True, fact=4): """Determine which HEALPixels touch an RA, Dec, radius cap. Parameters ---------- nside : :class:`int` (NESTED) HEALPixel nside. radecrad : :class:`list`, defaults to `None` 3-entry list of coordinates [ra, dec, radius] forming a cap or "circle" on the sky. ra, dec and radius are all in degrees. inclusive : :class:`bool`, optional, defaults to ``True`` see documentation for `healpy.query_disc()`. fact : :class:`int`, optional defaults to 4 see documentation for `healpy.query_disc()`. Returns ------- :class:`list` A list of HEALPixels at the passed `nside` that touch the cap. Notes ----- - Just syntactic sugar around `healpy.query_disc()`. """ ra, dec, radius = radecrad # ADM RA/Dec to co-latitude/longitude, everything to radians. theta, phi, rad = np.radians(90. - dec), np.radians(ra), np.radians(radius) # ADM convert the colatitudes to Cartesian vectors remembering to # ADM transpose to pass the array to query_disc in the correct order. vec = hp.dir2vec(theta, phi).T # ADM determine the pixels that touch the box. pixnum = hp.query_disc(nside, vec, rad, inclusive=inclusive, fact=fact, nest=True) return pixnum
def select(self, l, b, radius=5, nside=1024): """create DataFrame with times, band id, distance from center parameters: l,b : position in Galactic radius : cone radius, deg nside : for healpy returns: DataFrame with columns: band : from input, energy and event type time : Mission Elapsed Time in s. (double) delta : distance from input position (deg, float32) """ df = self.df cart = lambda l, b: healpy.dir2vec(l, b, lonlat=True) # use query_disc to get photons within given radius of position center = cart(l, b) ipix = healpy.query_disc(nside, cart(l, b), np.radians(radius), nest=False) incone = np.isin(self.df.hpindex, ipix) # times: convert to double, add to start t = np.array(df.time[incone], float) + self.tstart # convert position info to just distance from center ll, bb = healpy.pix2ang(nside, self.df.hpindex[incone], nest=False, lonlat=True) t2 = np.array(np.sqrt((1. - np.dot(center, cart(ll, bb))) * 2), np.float32) return pd.DataFrame( np.rec.fromarrays( [df.band[incone], t, np.degrees(t2)], names='band time delta'.split()))
def radii2mask(nside, centers, radii, inclusive=True, fact=4, ordering='ring'): """ Gives an array of pixels included in a list of centers and a radius. Arguments: nside (int): Nside of the map. centers (tuple of two np.arrays): The theta, phi coordinates of the centers. radii (np.array of same size as the arrays in centers): The radii, in radians, of the circles around the centers that we want to mask. inclusive (bool): If False, mask the exact set of pixels whose pixel centers lie within the disk; if True, mask all pixels that overlap with the disk, perhaps a few more. fact (integer): Only used when inclusive=True. The overlapping test will be done at the resolution fact*nside. ordering (string): 'ring' or 'nested'. Returns: Array of booleans where the specified circles are masked out. """ centers_vecs = healpy.dir2vec(centers, lonlat=True) mask = np.ones(12 * nside**2, dtype=np.bool) num = 0 if ordering == 'ring': nest = False elif ordering == 'nested': nest = True for center, radius in zip(centers_vecs.transpose(), radii): if radius == 0: continue mask[healpy.query_disc(nside, center, radius, inclusive=inclusive, fact=fact, nest=nest)] = 0 return mask
def initialize(self, force=False): if self.setup or force: return self.setup = True #set up the spatial model self.dmodel = self.source.dmodel[self.band.event_type] self.dmodel.load() self.energy = self.band.energy self.dmodel.setEnergy(self.band.energy) roi_index = skymaps.Band(12).index(self.roicenter) self._keyword_check(roi_index) if getattr(self, 'preconvolved', False): #print 'Using preconvolved' c = self.roicenter cv = healpy.dir2vec(c.l(), c.b(), lonlat=True) hplist = healpy.query_disc(self.dmodel.nside, cv, self.band.radius_in_rad) assert skymaps.Band(self.dmodel.nside).index( self.roicenter) in hplist dirs = map(self.dmodel.dirfun, hplist) self.evalpoints = lambda dirs: np.array(map(self.dmodel, dirs) ) * self.corr self.ap_average = self.evalpoints(dirs).mean() else: self.create_grid() # will raise exception if no overlap grid = self.grid inside = grid.dists < self.band.radius_in_rad self.ap_average = grid.cvals[inside].mean() self.evalpoints = lambda dirs: grid(dirs, grid.cvals) self.delta_e = self.band.emax - self.band.emin self.factor = self.ap_average * self.band.solid_angle * self.delta_e if self.band.has_pixels: self.pixel_values = self.evalpoints( self.band.wsdl) * self.band.pixel_area * self.delta_e self.evaluate()
def radec_to_vec(ra, dec): assert 0 <= ra <= 360 assert -90 <= dec <= 90 # Healpix uses the convention -180 - 180 for longitude, instead # we get RA between 0 and 360, so we need to wrap wrap_angle = 180.0 lon = np.mod(ra - wrap_angle, 360.0) - (360.0 - wrap_angle) vec = hp.dir2vec(lon, dec, lonlat=True) return vec # def pixid_to_radec(nside, pixid, nest=False): # # theta, phi = hp.pix2ang(nside, pixid, nest=nest, lonlat=False) # # ra = np.rad2deg(phi) # dec = np.rad2deg(0.5 * np.pi - theta) # # return ra, dec
def hp_in_box(nside, radecbox, inclusive=True, fact=4): """Determine which HEALPixels touch an RA, Dec box. Parameters ---------- nside : :class:`int` (NESTED) HEALPixel nside. radecbox : :class:`list` 4-entry list of coordinates [ramin, ramax, decmin, decmax] forming the edges of a box in RA/Dec (degrees). inclusive : :class:`bool`, optional, defaults to ``True`` see documentation for `healpy.query_polygon()`. fact : :class:`int`, optional defaults to 4 see documentation for `healpy.query_polygon()`. Returns ------- :class:`list` HEALPixels at the passed `nside` that touch the RA/Dec box. Notes ----- - Uses `healpy.query_polygon()` to retrieve the RA geodesics and then :func:`hp_in_dec_range()` to limit by Dec. - When the RA range exceeds 180o, `healpy.query_polygon()` defines the range as that with the smallest area (i.e the box can wrap-around in RA). To avoid any ambiguity, this function will only limit by the passed Decs in such cases. - Only strictly correct for Decs from -90+1e-5(o) to 90-1e5(o). """ ramin, ramax, decmin, decmax = radecbox # ADM area enclosed isn't well-defined if RA covers more than 180o. if np.abs(ramax - ramin) <= 180.: # ADM retrieve RA range. The 1e-5 prevents edge effects near poles. npole, spole = 90 - 1e-5, -90 + 1e-5 # ADM convert RA/Dec to co-latitude and longitude in radians. rapairs = np.array([ramin, ramin, ramax, ramax]) decpairs = np.array([spole, npole, npole, spole]) thetapairs, phipairs = np.radians(90. - decpairs), np.radians(rapairs) # ADM convert to Cartesian vectors remembering to transpose # ADM to pass the array to query_polygon in the correct order. vecs = hp.dir2vec(thetapairs, phipairs).T # ADM determine the pixels that touch the RA range. pixra = hp.query_polygon(nside, vecs, inclusive=inclusive, fact=fact, nest=True) else: log.warning( 'Max RA ({}) and Min RA ({}) separated by > 180o...'.format( ramax, ramin)) log.warning('...will only limit to passed Declinations'.format(nside)) pixra = np.arange(hp.nside2npix(nside)) # ADM determine the pixels that touch the Dec range. pixdec = hp_in_dec_range(nside, decmin, decmax, inclusive=inclusive) # ADM return the pixels in the box. pixnum = list(set(pixra).intersection(set(pixdec))) return pixnum
from matplotlib import pyplot # *** import numpy as np fontsize = 20 matplotlib.rcParams.update({'font.size': fontsize}) #%% """ STEP 2: Angular distances """ # Virgo cluster::: lon = 283.8 lat = 74.4 vec = hp.dir2vec(lon, phi=lat, lonlat=True) # Distance from Virgo to Coma::: lon_c = 235.1 lat_c = 73.0 vec_c = hp.dir2vec(lon_c, phi=lat_c, lonlat=True) distance = hp.rotator.angdist(vec, vec_c, lonlat=True) print('Distance: ', distance) #%% """ STEP 3: Rotation """
def _process_data(self, dummy1, dummy2): import pyarrow.parquet as pq # cone geometry stuff: get corresponding pixels and center vector l,b,radius = self.l, self.b, self.radius cart = lambda l,b: healpy.dir2vec(l,b, lonlat=True) conepix = healpy.query_disc(self.nside, cart(l,b), np.radians(radius), nest=self.nest) center = healpy.dir2vec(l,b, lonlat=True) ebins = self.energy_edges ecenters = np.sqrt(ebins[:-1]*ebins[1:]); band_limits = 2*np.searchsorted(ecenters, self.energy_range) if self.energy_range is not None else None def load_photon_data(table, tstart): """For a given month table, select photons in cone, add tstart to times, return DataFrame with band, time, pixel, radius """ allpix = np.array(table.column('nest_index')) def cone_select(allpix, conepix, shift=None): """Fast cone selection using NEST and shift """ if shift is None: return np.isin(allpix, conepix) assert self.nest, 'Expect pixels to use NEST indexing' a = np.right_shift(allpix, shift) c = np.unique(np.right_shift(conepix, shift)) return np.isin(a,c) # a selection of all those in an outer cone incone = cone_select(allpix, conepix, 13) # times: convert to double, add to start, convert to MJD time = MJD(np.array(table['time'],float)[incone]+tstart) in_gti = self.gti(time) if np.sum(in_gti)==0: print(f'WARNING: no photons for month {month}!') pixincone = allpix[incone][in_gti] # distance from center for all accepted photons ll,bb = healpy.pix2ang(self.nside, pixincone, nest=self.nest, lonlat=True) cart = lambda l,b: healpy.dir2vec(l,b, lonlat=True) t2 = np.degrees(np.array(np.sqrt((1.-np.dot(center, cart(ll,bb)))*2), np.float32)) # assemble the DataFrame, remove those outside the radius out_df = pd.DataFrame(np.rec.fromarrays( [np.array(table['band'])[incone][in_gti], time[in_gti], pixincone, t2], names='band time pixel radius'.split())) # apply final selection for radius and energy range if band_limits is None: return out_df.query(f'radius<{radius}') return out_df.query(f'radius<{radius} & {band_limits[0]} < band < {band_limits[1]}') # get the monthly-partitioned dataset and tstart values dataset = self.photon_data_source['dataset'] tstart_dict= self.photon_data_source['tstart_dict'] months = tstart_dict.keys() if self.verbose>0: print(f'Loading data from {len(months)} months from Arrow dataset {dataset}\n', end='') dflist=[] for month in months: table= pq.read_table(dataset, filters=[f'month == {month}'.split()]) tstart = tstart_dict[month] d = load_photon_data(table, tstart) if d is not None: dflist.append(d) if self.verbose>1: print('.', end='') else: if self.verbose>1: print('x', end='') continue assert len(dflist)>0, '\nNo photon data found?' df = pd.concat(dflist, ignore_index=True) if self.verbose>0: emin,emax = self.energy_range or (self.energy_edges[0],self.energy_edges[-1]) print(f'\n\tSelected {len(df)} photons within {self.radius}'\ f' deg of ({self.l:.2f},{self.b:.2f})') print(f'\tEnergies: {emin:.1f}-{emax:.0f} MeV') ta,tb = df.iloc[0].time, df.iloc[-1].time print(f'\tDates: {UTC(ta):16} - {UTC(tb)}'\ f'\n\tMJD : {ta:<16.1f} - {tb:<16.1f}') return df
for OPENING_ANGLE in [20, 40, 60]: hit = hp.ma(np.zeros(hp.nside2npix(NSIDE))) for day in range(1, 31): # In[6]: print(day) pointing = pd.read_hdf("zenith_pointing_%s.h5" % LOCATION.lower(), "data")["2015-08-%02d" % day] # I can define `z` as the axis of the telescope, `x` as defining the plane of the direction of view and `y` as the vector of polarization sensitivity for a fixed altitiude mount. # In[7]: vec = hp.dir2vec( np.degrees(pointing.ra_zenith_rad), np.degrees(pointing.dec_zenith_rad), lonlat=True).T # In[8]: vec_north = hp.dir2vec( np.degrees(pointing.ra_north_rad), np.degrees(pointing.dec_north_rad), lonlat=True).T # In[9]: x = np.array([1,0,0]) y = np.array([0,1,0]) z = np.array([0,0,1])
def qdisk(nside, glon, glat, radius): return healpy.query_disc(nside, healpy.dir2vec(glon, glat, lonlat=True), np.radians(radius))
""" STEP 3: Angles <--> Vec """ theta = np.deg2rad(45.) # rad phi = np.deg2rad(30.) # rad vec = hp.ang2vec(theta,phi) vec print('(theta,phi) = (',theta,',',phi,') --> (x,y,z)=', vec) theta_phi = hp.vec2ang(vec) theta_phi print('(x,y,z)=', vec,' --> (theta,phi) = (',theta_phi,')') hp.dir2vec(theta, phi=phi) #%% """ STEP 4: Angles <--> Vec ::OR:: Dir <--> Vec """ # vec2dir and dir2vec are very similar to vec2ang and ang2vec # Which are the difference??? # Create a theta,phi list: nside = 64 npix = hp.nside2npix(nside) pixels = np.arange(npix) theta_phi = hp.pix2ang(nside, pixels)
a2, b2 = (0. - 0.2) / 0.12, (1 - 0.2) / 0.12 a3, b3 = (0 - 10.97) / 3.80, (25. - 10.97) / 3.8 a4, b4 = (0 - 2.84) / 1.3, (8 - 2.84) / 1.3 E = float(sys.argv[1]) lon = float(sys.argv[2]) lat = float(sys.argv[3]) s1 = int(sys.argv[4]) s2 = int(sys.argv[5]) s3 = int(sys.argv[6]) pid = -crp.nucleusId(1, 1) sun = crp.Vector3d(-8.5, 0, 0) * crp.kpc E = E * crp.EeV nhat = hp.dir2vec(lon, lat, lonlat=True) direc = crp.Vector3d() direc.setXYZ(nhat[0], nhat[1], nhat[2]) ps = crp.ParticleState(pid, E, sun, direc) cr = crp.Candidate(ps) sim = crp.ModuleList() sim.add(crp.Redshift()) sim.add(crp.PhotoPionProduction(crp.CMB)) sim.add(crp.PhotoPionProduction(crp.IRB)) sim.add(crp.PhotoDisintegration(crp.CMB)) sim.add(crp.PhotoDisintegration(crp.IRB)) sim.add(crp.NuclearDecay()) sim.add(crp.ElectronPairProduction(crp.CMB)) sim.add(crp.ElectronPairProduction(crp.IRB)) np.random.seed(s1)
def __init__(self, names=['hard', 'flat', 'soft', 'peaked', 'psr'], outdir='.', tname='all', nside=nside, roi_nside=12, fill=np.nan, disc=()): """ combine the tables generarated at each ROI names : names to give the columns, nside : nside parameter that the table was generated with, default 512 (or 256) tname : name of the table, default 'all' fill : scalar, defaul NaN Use to fill missing tables, if any (warning issued) disc : tuple of (l,b,r) to specify a disc """ self.names = names folder = '%s_table_%d' % (tname, nside) if os.path.exists('%s.zip' % folder): z = zipfile.ZipFile('%s.zip' % folder) files = sorted(z.namelist()) # skip folder? opener = z.open else: if not os.path.exists(folder): raise Exception('Did not find zip file %s.zip or folder %s' % (folder, folder)) opener = open files = sorted(glob.glob(os.path.join(outdir, folder, '*.pickle'))) nf = len(files) assert nf > 0, 'no pickle files found in %s' % os.path.join( outdir, folder) if nf < 1728: print 'warning: missing %d files in folder %s_table; will fill with %s' % ( (1728 - nf), tname, fill) mvec = np.zeros((12 * nside**2, len(names))) mvec.fill(fill) pklist = [pickle.load(opener(f)) for f in files] if disc: # special for a single disc -- kluge a special inndex_table l, b, r = disc vec = healpy.dir2vec(l, b, lonlat=True) index_table = [ healpy.query_disc(nside=nside, vec=vec, radius=np.radians(r), nest=False) ] i12 = [0] else: index_table = make_index_table(roi_nside, nside) i12 = [int(f[-11:-7]) for f in files] for index, pk in zip(i12, pklist): indeces = index_table[index] for i, v in enumerate(pk): mvec[indeces[i]] = v bad = sum(mvec == fill) if np.any(bad) > 0: print 'WARNING: %d pixels not filled in table %s' % (bad, tname) else: print 'Table "{}" Filled with columns {}'.format(tname, names) self.mvec = mvec