def __init__(self, scan, wgeo): # Build the pointing interpolator self.trans = TransformPos2Pix(scan, wgeo.gwcs) self.poly = pmat.PolyInterpol(self.trans, scan.boresight, scan.offsets) # Build the pixel shift information. This assumes ces-like scans in equ-like systems self.sdir = pmat.get_scan_dir(scan.boresight[:, 1]) self.period = pmat.get_scan_period(scan.boresight[:, 1], scan.srate) self.wgeo = wgeo self.nphi = int(np.abs(360. / wgeo.gwcs.wcs.cdelt[0])) self.core = pmat.get_core(wgeo.dtype) self.scan = scan
def __init__(self, scan, wgeo): # Build the pointing interpolator self.trans = TransformPos2Pix(scan, wgeo.gwcs) self.poly = pmat.PolyInterpol(self.trans, scan.boresight, scan.offsets) # Build the pixel shift information. This assumes ces-like scans in equ-like systems self.sdir = pmat.get_scan_dir(scan.boresight[:,1]) self.period = pmat.get_scan_period(scan.boresight[:,1], scan.srate) self.wgeo = wgeo self.nphi = int(np.abs(360./wgeo.gwcs.wcs.cdelt[0])) self.core = pmat.get_core(wgeo.dtype) self.scan = scan
def build_workspace_geometry(wid, bore, point_offset, global_wcs, site=None, tagger=None, padding=100, max_ra_width=2.5 * utils.degree, ncomp=3, dtype=np.float64): if tagger is None: tagger = WorkspaceTagger() if isinstance(wid, basestring): wid = tagger.analyze(wid) if not valid_az_range(wid[0], wid[1]): raise WorkspaceError("Azimuth crosses north/south") trans = TransformPos2Pospix(global_wcs, site=site) az1, az2, el, ra1 = wid # Extract the workspace definition of the tag name ra_ref = ra1 + tagger.ra_step / 2 # We want ra(dec) for up- and down-sweeps for the middle of # the workspace. First find a t that will result in a sweep # that crosses through the middle of the workspace. foc_offset = np.mean(point_offset, 0) t0 = utils.ctime2mjd(bore[0, 0]) t_ref = find_t_giving_ra(az1 + foc_offset[0], el + foc_offset[1], ra_ref, site=site, t0=t0) # We also need the corners of the full workspace area. t1 = find_t_giving_ra(az1 + foc_offset[0], el + foc_offset[1], ra1, site=site, t0=t0) t2 = find_t_giving_ra(az1 + foc_offset[0], el + foc_offset[1], ra1 + tagger.ra_step + max_ra_width, site=site, t0=t0) #print "t1", t1, "t2", t2 #print "az1", az1/utils.degree, "az2", az2/utils.degree #print "ra", ra1/utils.degree, (ra1+tagger.ra_step+max_ra_width)/utils.degree bore_box_hor = np.array([[t1, az1, el], [t2, az2, el]]) bore_corners_hor = utils.box2corners(bore_box_hor) work_corners_hor = bore_corners_hor[None, :, :] + ( point_offset[:, [0, 0, 1]] * [0, 1, 1])[:, None, :] work_corners_hor = work_corners_hor.T.reshape(3, -1) work_corners = trans(work_corners_hor[1:], time=work_corners_hor[0]) ixcorn, iycorn = np.round(work_corners[2:]).astype(int) iybox = np.array([np.min(iycorn) - padding, np.max(iycorn) + 1 + padding]) # Generate an up and down sweep srate = get_srate(bore[0]) period = pmat.get_scan_period(bore[1], srate) dmjd = period / 2. / 24 / 3600 xshifts = [] yshifts = [] work_dazs = [] nwxs, nwys = [], [] for si, (afrom, ato) in enumerate([[az1, az2], [az2, az1]]): sweep = generate_sweep_by_dec_pix( [[t_ref, afrom + foc_offset[0], el + foc_offset[1]], [t_ref + dmjd, ato + foc_offset[0], el + foc_offset[1]]], iybox, trans) # Get the shift in ra pix per dec pix. At this point, # the shifts are just relative to the lowest-dec pixel xshift = np.round(sweep[5] - sweep[5, 0, None]).astype(int) # Get the shift in dec pix per dec pix. These tell us where # each working pixel starts as a function of normal dec pixel. # For example [0,1,3,6] would mean that the work to normal pixel # mapping is [0,1,1,2,2,2]. This is done to make dwdec/daz approximately # constant daz = np.abs(sweep[1, 1:] - sweep[1, :-1]) daz_ratio = np.maximum(1, daz / np.min(daz[1:-1])) yshift = np.round(utils.cumsum(daz_ratio, endpoint=True)).astype(int) yshift -= yshift[0] # Now that we have the x and y mapping, we can determine the # bounds of our workspace by transforming the corners of our # input coordinates. #print "iyc", iycorn-iybox[0] #print "ixc", ixcorn #for i in np.argsort(iycorn): # print "A %6d %6d" % (iycorn[i], ixcorn[i]) #print "min(ixc)", np.min(ixcorn) #print "max(ixc)", np.max(ixcorn) #print "xshift", xshift[iycorn-iybox[0]] wycorn = ixcorn - xshift[iycorn - iybox[0]] #print "wycorn", wycorn #print "min(wyc)", np.min(wycorn) #print "max(wyc)", np.max(wycorn) # Modify the shifts so that any scan in this workspace is always transformed # to valid positions. wx and wy are transposed relative to x and y. # Padding is needed because of the rounding involved in recovering the # az and el from the wid. xshift += np.min(wycorn) xshift -= padding wycorn2 = ixcorn - xshift[iycorn - iybox[0]] #print "wycorn2", wycorn2 #print "min(wyc2)", np.min(wycorn2) #print "max(wyc2)", np.max(wycorn2) #sys.stdout.flush() nwy = np.max(wycorn) - np.min(wycorn) + 1 + 2 * padding nwx = yshift[-1] + 1 # Get the average azimuth spacing in wx work_daz = (sweep[1, -1] - sweep[1, 0]) / (yshift[-1] - yshift[0]) print work_daz / utils.degree # And collect so we can pass them to the Workspace construtor later xshifts.append(xshift) yshifts.append(yshift) nwxs.append(nwx) nwys.append(nwy) work_dazs.append(work_daz) # The shifts from each sweep are guaranteed to have the same length, # since they are based on the same iybox. nwx = np.max(nwxs) # To translate the noise properties, we need a mapping from the x and t # fourier spaces. For this we need the azimuth scanning speed. scan_speed = 2 * (az2 - az1) / period work_daz = np.mean(work_dazs) wgeo = WorkspaceGeometry(nwys, nwx, xshifts, yshifts, iybox[0], scan_speed, work_daz, global_wcs, ncomp=ncomp, dtype=dtype) return wgeo
ok = True nbox = [ndet, 11] err = np.max(np.abs(pos_exact - pos_inter) / errlim[:, None]) * acc err2 = np.max(np.std(pos_exact - pos_inter, 1) / errlim) * acc # Set up arrays map = map_orig.copy() tod = np.arange(tod.size, dtype=dtype).reshape(tod.shape) * 1e-8 # Precompute pixels if necessary tpre = 0 if ipname == "fast": pix = np.zeros([ndet, nsamp], np.int32) phase = np.zeros([ndet, nsamp, 2], dtype) sdir = pmat.get_scan_dir(bore[:, 1]) period = pmat.get_scan_period(bore[:, 1], srate) wbox, wshift = pmat.build_work_shift(transfun, wibox, period) t1 = time.time() core.pmat_map_get_pix_poly_shift(pix.T, phase.T, bore.T, hwp.T, det_comps.T, poly.coeffs.T, sdir, wbox.T, wshift.T) t2 = time.time() tpre = t2 - t1 t1 = time.time() times = np.zeros(5, dtype=ptype) iptoks = ipname.split("_") for i in range(args.ntime): if ipname == "fast": core.pmat_map_use_pix_shift(dir, tod.T, 1, map.T, 1, pix.T, phase.T, wbox.T, wshift.T, nphi,
def build_workspace_geometry(wid, bore, point_offset, global_wcs, site=None, tagger=None, padding=100, max_ra_width=2.5*utils.degree, ncomp=3, dtype=np.float64): if tagger is None: tagger = WorkspaceTagger() if isinstance(wid, basestring): wid = tagger.analyze(wid) if not valid_az_range(wid[0], wid[1]): raise WorkspaceError("Azimuth crosses north/south") trans = TransformPos2Pospix(global_wcs, site=site) az1, az2, el, ra1 = wid # Extract the workspace definition of the tag name ra_ref = ra1 + tagger.ra_step/2 # We want ra(dec) for up- and down-sweeps for the middle of # the workspace. First find a t that will result in a sweep # that crosses through the middle of the workspace. foc_offset = np.mean(point_offset,0) t0 = utils.ctime2mjd(bore[0,0]) t_ref = find_t_giving_ra(az1+foc_offset[0], el+foc_offset[1], ra_ref, site=site, t0=t0) # We also need the corners of the full workspace area. t1 = find_t_giving_ra(az1+foc_offset[0], el+foc_offset[1], ra1, site=site, t0=t0) t2 = find_t_giving_ra(az1+foc_offset[0], el+foc_offset[1], ra1+tagger.ra_step+max_ra_width, site=site, t0=t0) #print "t1", t1, "t2", t2 #print "az1", az1/utils.degree, "az2", az2/utils.degree #print "ra", ra1/utils.degree, (ra1+tagger.ra_step+max_ra_width)/utils.degree bore_box_hor = np.array([[t1,az1,el],[t2,az2,el]]) bore_corners_hor = utils.box2corners(bore_box_hor) work_corners_hor = bore_corners_hor[None,:,:] + (point_offset[:,[0,0,1]] * [0,1,1])[:,None,:] work_corners_hor = work_corners_hor.T.reshape(3,-1) work_corners = trans(work_corners_hor[1:], time=work_corners_hor[0]) ixcorn, iycorn = np.round(work_corners[2:]).astype(int) iybox = np.array([np.min(iycorn)-padding,np.max(iycorn)+1+padding]) # Generate an up and down sweep srate = get_srate(bore[0]) period = pmat.get_scan_period(bore[1], srate) dmjd = period/2./24/3600 xshifts = [] yshifts = [] work_dazs = [] nwxs, nwys = [], [] for si, (afrom,ato) in enumerate([[az1,az2],[az2,az1]]): sweep = generate_sweep_by_dec_pix( [[ t_ref, afrom+foc_offset[0],el+foc_offset[1]], [t_ref+dmjd,ato +foc_offset[0],el+foc_offset[1]] ],iybox,trans) # Get the shift in ra pix per dec pix. At this point, # the shifts are just relative to the lowest-dec pixel xshift = np.round(sweep[5]-sweep[5,0,None]).astype(int) # Get the shift in dec pix per dec pix. These tell us where # each working pixel starts as a function of normal dec pixel. # For example [0,1,3,6] would mean that the work to normal pixel # mapping is [0,1,1,2,2,2]. This is done to make dwdec/daz approximately # constant daz = np.abs(sweep[1,1:]-sweep[1,:-1]) daz_ratio = np.maximum(1,daz/np.min(daz[1:-1])) yshift = np.round(utils.cumsum(daz_ratio, endpoint=True)).astype(int) yshift -= yshift[0] # Now that we have the x and y mapping, we can determine the # bounds of our workspace by transforming the corners of our # input coordinates. #print "iyc", iycorn-iybox[0] #print "ixc", ixcorn #for i in np.argsort(iycorn): # print "A %6d %6d" % (iycorn[i], ixcorn[i]) #print "min(ixc)", np.min(ixcorn) #print "max(ixc)", np.max(ixcorn) #print "xshift", xshift[iycorn-iybox[0]] wycorn = ixcorn - xshift[iycorn-iybox[0]] #print "wycorn", wycorn #print "min(wyc)", np.min(wycorn) #print "max(wyc)", np.max(wycorn) # Modify the shifts so that any scan in this workspace is always transformed # to valid positions. wx and wy are transposed relative to x and y. # Padding is needed because of the rounding involved in recovering the # az and el from the wid. xshift += np.min(wycorn) xshift -= padding wycorn2= ixcorn - xshift[iycorn-iybox[0]] #print "wycorn2", wycorn2 #print "min(wyc2)", np.min(wycorn2) #print "max(wyc2)", np.max(wycorn2) #sys.stdout.flush() nwy = np.max(wycorn)-np.min(wycorn)+1 + 2*padding nwx = yshift[-1]+1 # Get the average azimuth spacing in wx work_daz = (sweep[1,-1]-sweep[1,0])/(yshift[-1]-yshift[0]) print work_daz/utils.degree # And collect so we can pass them to the Workspace construtor later xshifts.append(xshift) yshifts.append(yshift) nwxs.append(nwx) nwys.append(nwy) work_dazs.append(work_daz) # The shifts from each sweep are guaranteed to have the same length, # since they are based on the same iybox. nwx = np.max(nwxs) # To translate the noise properties, we need a mapping from the x and t # fourier spaces. For this we need the azimuth scanning speed. scan_speed = 2*(az2-az1)/period work_daz = np.mean(work_dazs) wgeo = WorkspaceGeometry(nwys, nwx, xshifts, yshifts, iybox[0], scan_speed, work_daz, global_wcs, ncomp=ncomp, dtype=dtype) return wgeo
ok = True nbox = [ndet, 11] err = np.max(np.abs(pos_exact-pos_inter)/errlim[:,None])*acc err2 = np.max(np.std(pos_exact-pos_inter,1)/errlim)*acc # Set up arrays map = map_orig.copy() tod = np.arange(tod.size,dtype=dtype).reshape(tod.shape)*1e-8 # Precompute pixels if necessary tpre = 0 if ipname == "fast": pix = np.zeros([ndet,nsamp],np.int32) phase = np.zeros([ndet,nsamp,2],dtype) sdir = pmat.get_scan_dir(bore[:,1]) period = pmat.get_scan_period(bore[:,1], srate) wbox, wshift = pmat.build_work_shift(transfun, wibox, period) t1 = time.time() core.pmat_map_get_pix_poly_shift(pix.T, phase.T, bore.T, hwp.T, det_comps.T, poly.coeffs.T, sdir, wbox.T, wshift.T) t2 = time.time() tpre = t2-t1 t1 = time.time() times = np.zeros(5, dtype=ptype) iptoks = ipname.split("_") for i in range(args.ntime): if ipname == "fast": core.pmat_map_use_pix_shift(dir, tod.T, 1, map.T, 1, pix.T, phase.T, wbox.T, wshift.T, nphi, times) elif iptoks[0] == "std": pmet = {"bi":1,"gr":2}[iptoks[1]]