def makemap(band,skypos,trange,skyrange,response=False,verbose=0,detsize=1.1): imsz = gxt.deg2pix(skypos,skyrange) photons = np.array(gQuery.getArray(gQuery.skyrect(band, skypos[0],skypos[1],trange[0],trange[1],skyrange[0],skyrange[1]), verbose=verbose),dtype='float64') try: events = {'t':photons[:,0 ]/tscale,'ra':photons[:,1],'dec':photons[:,2], 'xi':photons[:,3],'eta':photons[:,4], 'x':photons[:,5], 'y':photons[:,6]} except IndexError: if verbose>2: print 'No events found at {s} +/- {r} in {t}.'.format( s=skypos,r=skyrange,t=trange) return np.zeros(imsz) # Trim the data on detsize col, row = ct.xieta2colrow(events['xi'],events['eta'],band) ix = np.where((1.25/800.)*mc.distance(col,row,400,400)<=detsize) n = len(ix[0]) m = len(col) #print 'With detsize {d} using {n} of {m} data.'.format(d=detsize,n=n,m=m) if n == 0: return np.zeros(imsz) for k in events.keys(): events[k] = events[k][ix] events = ct.hashresponse(band,events) wcs = define_wcs(skypos,skyrange,width=False,height=False) coo = zip(events['ra'],events['dec']) foc = wcs.sip_pix2foc(wcs.wcs_world2pix(coo,1),1) weights = 1./events['response'] if response else None H,xedges,yedges=np.histogram2d(foc[:,1]-0.5,foc[:,0]-0.5,bins=imsz, range=([ [0,imsz[0]],[0,imsz[1]] ]),weights=weights) return H
def integrate_map(band,skypos,tranges,skyrange,width=False,height=False, verbose=0,memlight=False,hdu=False,retries=20,response=False, detsize=1.1): """ Integrate an image over some number of time ranges. Use a reduced memory optimization (at the expense of more web queries) if requested. """ imsz = gxt.deg2pix(skypos,skyrange) img = np.zeros(imsz) for trange in tranges: # If memlight is requested, break the integration into # smaller chunks. # FIXME: memlight gives slightly wrong answers right now # This is probably due to a quirk of SQL, per issue #140. # Deprecating memlight until this can be resolved. step = memlight if memlight else trange[1]-trange[0] for i in np.arange(trange[0],trange[1],step): t0,t1=i,i+step if verbose: mc.print_inline('Coadding '+str(t0)+' to '+str(t1)) img += makemap(band,skypos,[t0,t1],skyrange,response=response, verbose=verbose,detsize=detsize) if response: # This is an intensity map. img /= dbt.compute_exptime(band,trange,skypos=skypos, verbose=verbose) return img
def sigmaclip_bg(data,radius,annulus,skypos,maxiter=10,sigmaclip=3., gausslim=50.,verbose=0,pixsz=0.000416666666666667): """Produce an estimate of background counts within an aperture (radius) using a sigma clipping method for extracting the background from an annulus. This attempts to reproduce the calcuations of the backcalc() function in mapaps/poissonbg.c of the mission pipeline. (Probably written by Ted Wyder.) """ # FIXME: Does not apply response! # This cut is now handled by the ugly loop below, which barely dodges a # conceptula issue about fractional pixels... #ix = np.where((d>annulus[0]) & (d<annulus[1])) imsz=gxt.deg2pix(skypos,[annulus[1]*2,annulus[1]*2]) wcs=define_wcs(skypos,[annulus[1]*2,annulus[1]*2]) foc_ra,foc_dec=wcs.sip_pix2foc(wcs.wcs_world2pix(data['ra'],data['dec'],1),1) H,xedges,yedges=np.histogram2d(foc_ra-0.5,foc_dec-0.5,bins=imsz, range=([ [0,imsz[0]],[0,imsz[1]]])) # Convert Gaussian sigma to a probability problim = 0.5*scipy.special.erfc(sigmaclip/np.sqrt(2.0)) # Mask out non-annulus regions... there's probalby a more pythonic way bgimg=np.copy(H) for i in range(H.shape[0]): for j in range(H.shape[1]): # Add a little buffer to account for pixel widths? # FIXME? including everything within the annulus... # if (mc.distance(H.shape[0]/2.,H.shape[1]/2.,i,j)<annulus[0]/pixsz or if mc.distance(H.shape[0]/2.,H.shape[1]/2.,i,j)>annulus[1]/pixsz:#): bgimg[i,j]=-1 ix=np.where(bgimg>=0) m,s=bgimg[ix].mean(),bgimg[ix].std() d = 1. for i in range(maxiter): if d<=10e-5 or m<2: continue if m>=gausslim: # Mask anything outside of 3 sigma from the mean (of unmasked data) klim=m+sigmaclip*np.sqrt(m)#s klo=m-sigmaclip*np.sqrt(m)#s if verbose: print 'Gaussian cut: {klo} to {klim}'.format(klo=klo,klim=klim) else: klim = scipy.special.gammainccinv(m,problim) klo = -1 # None if verbose: print 'Poisson cut: {klo} to {klim}'.format(klo=klo,klim=klim) ix = np.where((bgimg>=klim) | (bgimg<=klo)) bgimg[ix]=-1 ix=np.where(bgimg>=0) d = np.abs((bgimg[ix].mean()-m)/m)# - 1) m,s=bgimg[ix].mean(),bgimg[ix].std() ix = np.where(bgimg>=0) return mc.area(radius)*bgimg[ix].mean()/mc.area(pixsz)
def rrhr(band,skypos,tranges,skyrange,width=False,height=False,stepsz=1., verbose=0,calpath='../cal/',tscale=1000.,response=True,hdu=False, retries=20): """Generate a high resolution relative response (rrhr) map.""" imsz = gxt.deg2pix(skypos,skyrange) # TODO the if width / height flat = get_fits_data(flat_filename(band,calpath),verbose=verbose) flatinfo = get_fits_header(flat_filename(band,calpath)) npixx,npixy = flat.shape fltsz = flat.shape pixsz = flatinfo['CDELT2'] detsize = 1.25 # Rotate the flat into the correct orientation to start. flat = np.flipud(np.rot90(flat)) # NOTE: This upsample interpolation is done _last_ in the canonical # pipeline as part of the poissonbg.c routine. # The interpolation function is "congrid" in the same file. # TODO: Should this be first order interpolation? (i.e. bilinear) hrflat = scipy.ndimage.interpolation.zoom(flat,4.,order=0,prefilter=False) img = np.zeros(hrflat.shape)[ hrflat.shape[0]/2.-imsz[0]/2.:hrflat.shape[0]/2.+imsz[0]/2., hrflat.shape[1]/2.-imsz[1]/2.:hrflat.shape[1]/2+imsz[1]/2.] for trange in tranges: t0,t1=trange entries = gQuery.getArray(gQuery.aspect(t0,t1),retries=retries) n = len(entries) asptime = np.float64(np.array(entries)[:,2])/tscale aspra = np.float32(np.array(entries)[:,3]) aspdec = np.float32(np.array(entries)[:,4]) asptwist= np.float32(np.array(entries)[:,5]) aspflags= np.float32(np.array(entries)[:,6]) asptwist= np.float32(np.array(entries)[:,9]) aspra0 = np.zeros(n)+skypos[0] aspdec0 = np.zeros(n)+skypos[1] xi_vec, eta_vec = gnomonic.gnomfwd_simple( aspra,aspdec,aspra0,aspdec0,-asptwist,1.0/36000.,0.) col = 4.*( ((( xi_vec/36000.)/(detsize/2.)*(detsize/(fltsz[0]*pixsz)) + 1.)/2. * fltsz[0]) - (fltsz[0]/2.) ) row = 4.*( (((eta_vec/36000.)/(detsize/2.)*(detsize/(fltsz[1]*pixsz)) + 1.)/2. * fltsz[1]) - (fltsz[1]/2.) ) vectors = rotvec(np.array([col,row]),-asptwist) for i in range(n): if verbose>1: print_inline('Stamping '+str(asptime[i])) # FIXME: Clean this mess up a little just for clarity. img += scipy.ndimage.interpolation.shift(scipy.ndimage.interpolation.rotate(hrflat,-asptwist[i],reshape=False,order=0,prefilter=False),[vectors[1,i],vectors[0,i]],order=0,prefilter=False)[hrflat.shape[0]/2.-imsz[0]/2.:hrflat.shape[0]/2.+imsz[0]/2.,hrflat.shape[1]/2.-imsz[1]/2.:hrflat.shape[1]/2+imsz[1]/2.]*dbt.compute_exptime(band,[asptime[i],asptime[i]+1],verbose=verbose,retries=retries)*gxt.compute_flat_scale(asptime[i]+0.5,band,verbose=0) return img
def define_wcs(skypos,skyrange,width=False,height=False,verbose=0, pixsz=0.000416666666666667): """Define the world coordinate system (WCS).""" if verbose: print_inline('Defining World Coordinate System (WCS).') wcs = pywcs.WCS(naxis=2) # NAXIS = 2 imsz = gxt.deg2pix(skypos,skyrange) wcs.wcs.cdelt = np.array([-pixsz,pixsz]) wcs.wcs.ctype = ['RA---TAN','DEC--TAN'] wcs.wcs.crpix = [(imsz[1]/2.)+0.5,(imsz[0]/2.)+0.5] wcs.wcs.crval = skypos return wcs
def makemap(band,skypos,trange,skyrange,response=False,verbose=0): imsz = gxt.deg2pix(skypos,skyrange) photons = np.array(gQuery.getArray(gQuery.skyrect(band, skypos[0],skypos[1],trange[0],trange[1],skyrange[0],skyrange[1]), verbose=verbose),dtype='float64') events = {'t':photons[:,0 ]/tscale, 'ra':photons[:,1], 'dec':photons[:,2], 'xi':photons[:,3],'eta':photons[:,4], 'x':photons[:,5], 'y':photons[:,6]} if len(events['t'])==0: return np.zeros(imsz) events = ct.hashresponse(band,events) wcs = define_wcs(skypos,skyrange,width=False,height=False) coo = zip(events['ra'],events['dec']) foc = wcs.sip_pix2foc(wcs.wcs_world2pix(coo,1),1) weights = 1./events['response'] if response else None H,xedges,yedges=np.histogram2d(foc[:,1]-0.5,foc[:,0]-0.5,bins=imsz, range=([ [0,imsz[0]],[0,imsz[1]] ]),weights=weights) return H
def countmap(band,skypos,tranges,skyrange,width=False,height=False, verbose=0,tscale=1000.,memlight=False,hdu=False,retries=20): """Create a count (cnt) map.""" imsz = gxt.deg2pix(skypos,skyrange) count = np.zeros(imsz) for trange in tranges: # If memlight is requested, break the integration into # smaller chunks. step = memlight if memlight else trange[1]-trange[0] for i in np.arange(trange[0],trange[1],step): t0,t1=i,i+step if verbose: print_inline('Coadding '+str(t0)+' to '+str(t1)) events = gQuery.getArray(gQuery.rect(band,skypos[0],skypos[1],t0,t1, skyrange[0],skyrange[1]), verbose=verbose,retries=retries) # Check that there is actually data here. if not events: if verbose>1: print "No data in "+str([t0,t1]) continue times = np.array(events,dtype='float64')[:,0 ]/tscale coo = np.array(events,dtype='float64')[:,1:] # If there's no data, return a blank image. if len(coo)==0: if verbose: print 'No data in this frame: '+str([t0,t1]) continue # Define World Coordinate System (WCS) wcs = define_wcs(skypos,skyrange,width=False,height=False) # Map the sky coordinates onto the focal plane foc = wcs.sip_pix2foc(wcs.wcs_world2pix(coo,1),1) # Bin the events into actual image pixels H,xedges,yedges=np.histogram2d(foc[:,1]-0.5,foc[:,0]-0.5, bins=imsz,range=([ [0,imsz[0]],[0,imsz[1]] ])) count += H return count
def test_deg2pix_pole(self): skypos,skyrange=[90.,90.],[1.,1.] pix = gt.deg2pix(skypos,skyrange) self.assertAlmostEqual(pix[0],2400.) self.assertAlmostEqual(pix[1],21.)
def test_deg2pix_equator(self): skypos,skyrange=[0.,0.],[1.,1.] pix = gt.deg2pix(skypos,skyrange) self.assertAlmostEqual(pix[0],2400.) self.assertAlmostEqual(pix[1],2400.)