def calc_offset_upos(pattern, offset_array, offset_det, site, area, U): """Compute how the detectors are offset from the array midpoint in unskewd pixel units. All angles are in radians.""" ref_hor = np.array([pattern[0],np.mean(pattern[1:3])]) + offset_array det_hor = ref_hor[:,None] + offset_det.T # Transform to celestial coordinates ref_cel = coordinates.transform("hor","cel", ref_hor[::-1], time=ref_time, site=site)[::-1] det_cel = coordinates.transform("hor","cel", det_hor[::-1], time=ref_time, site=site)[::-1] # RA is ambiguous because we don't know the time properly ra0 = np.mean(area.box(),0)[1] det_cel[1] += ra0 - ref_cel[1] ref_cel[1] = ra0 # And convert into pixels ref_pix = area.sky2pix(ref_cel) det_pix = area.sky2pix(det_cel) # Unskew these to get pixels in the coordinate system # the noise model lives in ref_upix = U.apply_pix(ref_pix) det_upix = U.apply_pix(det_pix) # And express that as positions in this new coordinate system ref_upos = enmap.pix2sky(U.ushape, U.uwcs, ref_upix) det_upos = enmap.pix2sky(U.ushape, U.uwcs, det_upix) # And finally record the offset of each detector from the reference point offset_upos = det_upos - ref_upos[:,None] return offset_upos
def calc_offset_upos(pattern, offset_array, offset_det, site, area, U): """Compute how the detectors are offset from the array midpoint in unskewd pixel units. All angles are in radians.""" ref_hor = np.array([pattern[0], np.mean(pattern[1:3])]) + offset_array det_hor = ref_hor[:, None] + offset_det.T # Transform to celestial coordinates ref_cel = coordinates.transform("hor", "cel", ref_hor[::-1], time=ref_time, site=site)[::-1] det_cel = coordinates.transform("hor", "cel", det_hor[::-1], time=ref_time, site=site)[::-1] # RA is ambiguous because we don't know the time properly ra0 = np.mean(area.box(), 0)[1] det_cel[1] += ra0 - ref_cel[1] ref_cel[1] = ra0 # And convert into pixels ref_pix = area.sky2pix(ref_cel) det_pix = area.sky2pix(det_cel) # Unskew these to get pixels in the coordinate system # the noise model lives in ref_upix = U.apply_pix(ref_pix) det_upix = U.apply_pix(det_pix) # And express that as positions in this new coordinate system ref_upos = enmap.pix2sky(U.ushape, U.uwcs, ref_upix) det_upos = enmap.pix2sky(U.ushape, U.uwcs, det_upix) # And finally record the offset of each detector from the reference point offset_upos = det_upos - ref_upos[:, None] return offset_upos
def make_projectable_map_cyl(map, verbose=False): """Given an enmap in a cylindrical projection, return a map with the same pixelization, but extended to cover a whole band in phi around the sky. Also returns the slice required to recover the input map from the output map.""" # First check if we need flipping. Sharp wants theta,phi increasing, # which means dec decreasing and ra increasing. flipx = map.wcs.wcs.cdelt[0] < 0 flipy = map.wcs.wcs.cdelt[1] > 0 if flipx: map = map[..., :, ::-1] if flipy: map = map[..., ::-1, :] # Then check if the map satisfies the lat-ring requirements ny, nx = map.shape[-2:] vy, vx = enmap.pix2sky(map.shape, map.wcs, [np.arange(ny), np.zeros(ny)]) hy, hx = enmap.pix2sky(map.shape, map.wcs, [np.zeros(nx), np.arange(nx)]) dx = hx[1:] - hx[:-1] dx = dx[np.isfinite(dx)] # Handle overextended coordinates if not np.allclose(dx, dx[0]): raise ShapeError("Map must have constant phi spacing") nphi = utils.nint(2 * np.pi / dx[0]) if not np.allclose(2 * np.pi / nphi, dx[0]): raise ShapeError("Pixels must evenly circumference") if not np.allclose(vx, vx[0]): raise ShapeError( "Different phi0 per row indicates non-cylindrical enmap") phi0 = vx[0] # Make a map with the same geometry covering a whole band around the sky # We can do this simply by extending it in the positive pixel dimension. oshape = map.shape[:-1] + (nphi, ) owcs = map.wcs # Our input map could in theory cover multiple copies of the sky, which # would require us to copy out multiple slices. nslice = (nx + nphi - 1) // nphi islice, oslice = [], [] def negnone(x): return x if x >= 0 else None for i in range(nslice): # i1:i2 is the range of pixels in the original map to use i1, i2 = i * nphi, min((i + 1) * nphi, nx) islice.append((Ellipsis, slice(i1, i2))) # yslice and xslice give the range of pixels in our temporary map to use. # This is 0:(i2-i1) if we're not flipping, but if we flip we count from # the opposite direction: nx-1:nx-1-(i2-i1):-1 yslice = slice(-1, None, -1) if flipy else slice(None) xslice = slice(nx - 1, negnone(nx - 1 - (i2 - i1)), -1) if flipx else slice(0, i2 - i1) oslice.append((Ellipsis, yslice, xslice)) if verbose: print "Allocating shape %s dtype %s intermediate map" % ( str(oshape), np.dtype(map.dtype).char) return enmap.empty(oshape, owcs, dtype=map.dtype), islice, oslice
def get_rotated_pixels(shape_source, wcs_source, shape_target, wcs_target, inverse=False): """ Given a source geometry (shape_source,wcs_source) return the pixel positions in the target geometry (shape_target,wcs_target) if the source geometry were rotated such that its center lies on the center of the target geometry. WARNING: Only currently tested for a rotation along declination from one CAR geometry to another CAR geometry. """ from enlib import coordinates # what are the center coordinates of each geometris center_source = enmap.pix2sky(shape_source, wcs_source, (shape_source[0] / 2., shape_source[1] / 2.)) center_target = enmap.pix2sky(shape_target, wcs_target, (shape_target[0] / 2., shape_target[1] / 2.)) decs, ras = center_source dect, rat = center_target # what are the angle coordinates of each pixel in the target geometry pos_target = enmap.posmap(shape_target, wcs_target) lra = pos_target[1, :, :].ravel() ldec = pos_target[0, :, :].ravel() del pos_target # recenter the angle coordinates of the target from the target center to the source center if inverse: newcoord = coordinates.decenter((lra, ldec), (rat, dect, ras, decs)) else: newcoord = coordinates.recenter((lra, ldec), (rat, dect, ras, decs)) del lra del ldec # reshape these new coordinates into enmap-friendly form new_pos = np.empty((2, shape_target[0], shape_target[1])) new_pos[0, :, :] = newcoord[1, :].reshape(shape_target) new_pos[1, :, :] = newcoord[0, :].reshape(shape_target) del newcoord # translate these new coordinates to pixel positions in the target geometry based on the source's wcs pix_new = enmap.sky2pix(shape_source, wcs_source, new_pos) return pix_new
def __init__(self, shape, wcs, pattern, offset, site, pad=2.0 * utils.degree): """This unskew operation assumes that equal spacing in dec corresponds to equal spacing in time, and that shifts in RA can be done in units of whole pixels. This is an approximation relative to UnskewCurved, but it is several times faster, uses less memory, and causes less smoothing.""" ndec, nra = shape[-2:] info = calc_az_sweep(pattern, offset, site, pad=pad) sweep_ra, sweep_dec = info.sweep_cel # For each pixel in dec (that we hit for this scanning pattern), we # want to know how far we have been displaced in ra. # First get the dec of each pixel center. ysweep, xsweep = enmap.sky2pix(shape, wcs, [sweep_dec, sweep_ra]) y1 = max(int(np.min(ysweep)), 0) y2 = min(int(np.max(ysweep)) + 1, shape[-2]) # Make fft-friendly ny = y2 - y1 ny2 = fft.fft_len(ny, "above", [2, 3, 5, 7]) y1 = max(y1 - (ny2 - ny) / 2, 0) y2 = min(y1 + ny2, shape[-2]) y = np.arange(y1, y2) dec, _ = enmap.pix2sky(shape, wcs, [y, y * 0]) # Then interpolate the ra values corresponding to those decs. # InterpolatedUnivariateSpline broken. Returns nan even when # interpolating. So we will use UnivariateSpline spline = scipy.interpolate.UnivariateSpline(sweep_dec, sweep_ra) ra = spline(dec) dra = ra - ra[len(ra) / 2] y, x = np.round(enmap.sky2pix(shape, wcs, [dec, ra])) dx = x - x[len(x) / 2] # It's also useful to be able to go from normal map index to # position in y and dx inv_y = np.zeros(shape[-2], dtype=int) - 1 inv_y[y.astype(int)] = np.arange(len(y)) # Compute the azimuth step size based on the total azimuth sweep. daz = (pattern[2] - pattern[1] + 2 * pad) / len(y) # Build the geometry of the unskewed system ushape, uwcs = enmap.geometry(pos=[0, 0], shape=[len(y), shape[-1]], res=[daz, enmap.pixshape(shape, wcs)[1]], proj="car") # And store the result self.y = y.astype(int) self.dx = np.round(dx).astype(int) self.dx_raw = dx self.inv_y = inv_y self.ushape = ushape self.uwcs = uwcs
def __init__(self, shape, wcs, pattern, offset, site, pad=2.0*utils.degree): """This unskew operation assumes that equal spacing in dec corresponds to equal spacing in time, and that shifts in RA can be done in units of whole pixels. This is an approximation relative to UnskewCurved, but it is several times faster, uses less memory, and causes less smoothing.""" ndec, nra = shape[-2:] info = calc_az_sweep(pattern, offset, site, pad=pad) sweep_ra, sweep_dec = info.sweep_cel # For each pixel in dec (that we hit for this scanning pattern), we # want to know how far we have been displaced in ra. # First get the dec of each pixel center. ysweep, xsweep = enmap.sky2pix(shape, wcs, [sweep_dec,sweep_ra]) y1 = max(int(np.min(ysweep)),0) y2 = min(int(np.max(ysweep))+1,shape[-2]) # Make fft-friendly ny = y2-y1 ny2 = fft.fft_len(ny, "above", [2,3,5,7]) y1 = max(y1-(ny2-ny)/2,0) y2 = min(y1+ny2,shape[-2]) y = np.arange(y1,y2) dec, _ = enmap.pix2sky(shape, wcs, [y,y*0]) # Then interpolate the ra values corresponding to those decs. # InterpolatedUnivariateSpline broken. Returns nan even when # interpolating. So we will use UnivariateSpline spline = scipy.interpolate.UnivariateSpline(sweep_dec, sweep_ra) ra = spline(dec) dra = ra - ra[len(ra)/2] y, x = np.round(enmap.sky2pix(shape, wcs, [dec,ra])) dx = x-x[len(x)/2] # It's also useful to be able to go from normal map index to # position in y and dx inv_y = np.zeros(shape[-2],dtype=int)-1 inv_y[y.astype(int)]= np.arange(len(y)) # Compute the azimuth step size based on the total azimuth sweep. daz = (pattern[2]-pattern[1]+2*pad)/len(y) # Build the geometry of the unskewed system ushape, uwcs = enmap.geometry(pos=[0,0], shape=[len(y),shape[-1]], res=[daz,enmap.pixshape(shape,wcs)[1]], proj="car") # And store the result self.y = y.astype(int) self.dx = np.round(dx).astype(int) self.dx_raw = dx self.inv_y = inv_y self.ushape = ushape self.uwcs = uwcs
def __init__(self, shape, wcs, hp_coords="galactic"): """ shape -- 2-tuple (Ny,Nx) wcs -- enmap wcs object in equatorial coordinates hp_coords -- "galactic" to perform a coordinate transform, "fk5","j2000" or "equatorial" otherwise """ from astropy.coordinates import SkyCoord import astropy.units as u self.wcs = wcs self.shape = shape Ny, Nx = shape inds = np.indices([Nx, Ny]) self.x = inds[0].ravel() self.y = inds[1].ravel() # Not as slow as you'd expect posmap = enmap.pix2sky(shape, wcs, np.vstack( (self.y, self.x))) * 180. / np.pi ph = posmap[1, :] th = posmap[0, :] eq_coords = ['fk5', 'j2000', 'equatorial'] gal_coords = ['galactic'] if hp_coords.lower() not in eq_coords: # This is still the slowest part. If there are faster coord transform libraries, let me know! assert hp_coords.lower() in gal_coords gc = SkyCoord(ra=ph * u.degree, dec=th * u.degree, frame='fk5') gc = gc.transform_to('galactic') self.phOut = gc.l.deg self.thOut = gc.b.deg else: self.thOut = th self.phOut = ph self.phOut *= np.pi / 180 self.thOut = 90. - self.thOut #polar angle is 0 at north pole self.thOut *= np.pi / 180
def sim_points(shape, wcs, info): # Simulate the point amplitudes N = enmap.area(shape, wcs) * info.density*(180/np.pi)**2 n = N*(info.minamp/info.amp)**(info.alpha+1) amps = info.minamp*np.random.uniform(0,1,n)**(1/(info.alpha+1)) amps = np.maximum(-100*np.abs(info.amp),np.minimum(100*np.abs(info.amp), amps)) # Simulate the polarization psi = np.random.uniform(0,np.pi,n) amps = amps[None,:] * np.array([psi*0+1,np.cos(2*psi)*info.pol,np.sin(2*psi)*info.pol]) # Simulate positions uniformly in pixels ipos = np.array([np.random.uniform(0,shape[-2],n),np.random.uniform(0,shape[-1],n)]) pos = enmap.pix2sky(wcs, ipos) # Draw the points on a canvas using convolution. This requires all points # to have integer pixel positions and the same radius. rawmap = np.zeros(shape) for i in range(shape[0]): rawmap[i][tuple(ipos.astype(int))] = amps[i] l = np.sum(enmap.lmap(shape,wcs)**2,0)**0.5 kernel = np.exp(-0.5*l**2*info.rad**2) # actually perform the convolution pmap = enmap.ifft(enmap.fft(rawmap)*kernel[None]).real print np.max(pmap), np.min(pmap) return pmap
for i in range(comm.rank, len(tyx), comm.size): y, x = tyx[i] if debug_tile is not None and not (y == debug_tile[0] and x == debug_tile[1]): continue prefix = args.odir + "/" if args.cont and os.path.isfile(prefix + "catalogue.fits"): if verbosity >= 1: print "%3d skipping %3d %3d (already done)" % (comm.rank, y, x) continue if verbosity >= 1: print "%3d processing %3d %3d" % (comm.rank, y, x) sys.stdout.flush() t1 = time.time() tpos = np.array(tyx[i]) pbox = np.array([tpos*tshape,np.minimum((tpos+1)*tshape,shape[-2:])]) box = enmap.pix2sky(shape, wcs, pbox.T).T try: info = eval_tile(mapinfo, box, signals, verbosity=verbosity) output_tile(prefix, [y,x], info) #except (np.linalg.LinAlgError, MemoryError) as e: except Exception as e: print "%3d error while processing %3d %3d: '%s'. Skipping" % (comm.rank, y, x, e.message) continue t2 = time.time() if verbosity >= 1: print "%3d processed %3d %3d in %7.1f max-mem %7.3f" % (comm.rank, y, x, t2-t1, memory.max()/1024.**3) else: # Single arbitrary tile if not overlaps_any(bounds, boxes): if verbosity >= 1: print "No data in selected region"
} ofile_div = args.odir + "/div_padtile/tile%(y)03d_%(x)03d.fits" % { "y": y, "x": x } utils.mkdir(os.path.dirname(ofile_map)) utils.mkdir(os.path.dirname(ofile_div)) if args.cont and os.path.isfile(ofile_map): print("%3d skipping %3d %3d (already done)" % (comm.rank, y, x)) continue print("%3d processing %3d %3d" % (comm.rank, y, x)) tpos = np.array(tyx[i]) pbox = np.array( [tpos * tshape, np.minimum((tpos + 1) * tshape, shape[-2:])]) box = enmap.pix2sky(shape, wcs, pbox.T).T res = get_coadded_tile(mapinfo, box, obeam=obeam, ncomp=args.ncomp, verbose=args.verbose) if res is None: res = jointmap.make_dummy_tile((args.ncomp, ) + shape[-2:], wcs, box, pad=pad, dtype=dtype) enmap.write_map(ofile_map, res.map) enmap.write_map(ofile_div, res.div) else: # Single arbitrary tile
def chunked_pix2sky(x): pix = enmap.pix2sky(shape, wcs, x) return pix
import multiprocessing # number of coordinates to transform N = 96000013 # this should be obtained using multiprocessing.get_cpu_count() Njobs = 12 th = np.random.uniform(0, 90, N) phi = np.random.uniform(0, 90, N) shape, wcs = enmap.rect_geometry(100., 0.5) coords = np.array([th, phi]) with bench.show("serial"): pix = enmap.pix2sky(shape, wcs, coords) def chunks(l, n): """Yield successive n-sized chunks from l.""" for i in range(0, l.shape[-1], n): yield l[:, i:i + n] size_chunks = int(ceil(coords.shape[1] * 1. / Njobs)) # print coords.shape # for i,x in enumerate(chunks(coords,size_chunks)): # print i, x.shape # sys.exit()