def stage0(**kwargs): ps = PlotSequence('cfht') decals = CfhtDecals() B = decals.get_bricks() print('Bricks:') B.about() ra, dec = 190.0, 11.0 #bands = 'ugri' bands = 'gri' B.cut(np.argsort(degrees_between(ra, dec, B.ra, B.dec))) print('Nearest bricks:', B.ra[:5], B.dec[:5], B.brickid[:5]) brick = B[0] pixscale = 0.186 #W,H = 1024,1024 #W,H = 2048,2048 #W,H = 3600,3600 W, H = 4800, 4800 targetwcs = wcs_for_brick(brick, pixscale=pixscale, W=W, H=H) ccdfn = 'cfht-ccds.fits' if os.path.exists(ccdfn): T = fits_table(ccdfn) else: T = get_ccd_list() T.writeto(ccdfn) print(len(T), 'CCDs') T.cut(ccds_touching_wcs(targetwcs, T)) print(len(T), 'CCDs touching brick') T.cut(np.array([b in bands for b in T.filter])) print(len(T), 'in bands', bands) ims = [] for t in T: im = CfhtImage(t) # magzp = hdr['PHOT_C'] + 2.5 * np.log10(hdr['EXPTIME']) # fwhm = t.seeing / (pixscale * 3600) # print '-> FWHM', fwhm, 'pix' im.seeing = t.seeing im.pixscale = t.pixscale print('seeing', t.seeing) print('pixscale', im.pixscale * 3600, 'arcsec/pix') im.run_calibs(t.ra, t.dec, im.pixscale, W=t.width, H=t.height) ims.append(im) # Read images, clip to ROI targetrd = np.array([ targetwcs.pixelxy2radec(x, y) for x, y in [(1, 1), (W, 1), (W, H), (1, H), (1, 1)] ]) keepims = [] tims = [] for im in ims: print() print('Reading expnum', im.expnum, 'name', im.extname, 'band', im.band, 'exptime', im.exptime) band = im.band wcs = im.read_wcs() imh, imw = wcs.imageh, wcs.imagew imgpoly = [(1, 1), (1, imh), (imw, imh), (imw, 1)] ok, tx, ty = wcs.radec2pixelxy(targetrd[:-1, 0], targetrd[:-1, 1]) tpoly = zip(tx, ty) clip = clip_polygon(imgpoly, tpoly) clip = np.array(clip) #print 'Clip', clip if len(clip) == 0: continue x0, y0 = np.floor(clip.min(axis=0)).astype(int) x1, y1 = np.ceil(clip.max(axis=0)).astype(int) slc = slice(y0, y1 + 1), slice(x0, x1 + 1) ## FIXME -- it seems I got lucky and the cross product is ## negative == clockwise, as required by clip_polygon. One ## could check this and reverse the polygon vertex order. # dx0,dy0 = tx[1]-tx[0], ty[1]-ty[0] # dx1,dy1 = tx[2]-tx[1], ty[2]-ty[1] # cross = dx0*dy1 - dx1*dy0 # print 'Cross:', cross print('Image slice: x [%i,%i], y [%i,%i]' % (x0, x1, y0, y1)) print('Reading image from', im.imgfn, 'HDU', im.hdu) img, imghdr = im.read_image(header=True, slice=slc) goodpix = (img != 0) print('Number of pixels == 0:', np.sum(img == 0)) print('Number of pixels != 0:', np.sum(goodpix)) if np.sum(goodpix) == 0: continue # print 'Image shape', img.shape print('Image range', img.min(), img.max()) print('Goodpix image range:', (img[goodpix]).min(), (img[goodpix]).max()) if img[goodpix].min() == img[goodpix].max(): print('No dynamic range in image') continue # print 'Reading invvar from', im.wtfn, 'HDU', im.hdu # invvar = im.read_invvar(slice=slc) # # print 'Invvar shape', invvar.shape # # print 'Invvar range:', invvar.min(), invvar.max() # invvar[goodpix == 0] = 0. # if np.all(invvar == 0.): # print 'Skipping zero-invvar image' # continue # assert(np.all(np.isfinite(img))) # assert(np.all(np.isfinite(invvar))) # assert(not(np.all(invvar == 0.))) # # Estimate per-pixel noise via Blanton's 5-pixel MAD # slice1 = (slice(0,-5,10),slice(0,-5,10)) # slice2 = (slice(5,None,10),slice(5,None,10)) # # print 'sliced shapes:', img[slice1].shape, img[slice2].shape # # print 'good shape:', (goodpix[slice1] * goodpix[slice2]).shape # # print 'good values:', np.unique(goodpix[slice1] * goodpix[slice2]) # # print 'sliced[good] shapes:', (img[slice1] - img[slice2])[goodpix[slice1] * goodpix[slice2]].shape # mad = np.median(np.abs(img[slice1] - img[slice2])[goodpix[slice1] * goodpix[slice2]].ravel()) # sig1 = 1.4826 * mad / np.sqrt(2.) # print 'MAD sig1:', sig1 # # invvar was 1 or 0 # invvar *= (1./(sig1**2)) # medsky = np.median(img[goodpix]) # Read full image for sig1 and sky estimate fullimg = im.read_image() fullgood = (fullimg != 0) # Estimate per-pixel noise via Blanton's 5-pixel MAD slice1 = (slice(0, -5, 10), slice(0, -5, 10)) slice2 = (slice(5, None, 10), slice(5, None, 10)) mad = np.median( np.abs(fullimg[slice1] - fullimg[slice2])[fullgood[slice1] * fullgood[slice2]].ravel()) sig1 = 1.4826 * mad / np.sqrt(2.) print('MAD sig1:', sig1) medsky = np.median(fullimg[fullgood]) invvar = np.zeros_like(img) invvar[goodpix] = 1. / sig1**2 # Median-smooth sky subtraction plt.clf() dimshow(np.round((img - medsky) / sig1), vmin=-3, vmax=5) plt.title('Scalar median: %s' % im.name) ps.savefig() # medsky = np.zeros_like(img) # # astrometry.util.util # median_smooth(img, np.logical_not(goodpix), 256, medsky) fullmed = np.zeros_like(fullimg) median_smooth(fullimg - medsky, np.logical_not(fullgood), 256, fullmed) fullmed += medsky medimg = fullmed[slc] plt.clf() dimshow(np.round((img - medimg) / sig1), vmin=-3, vmax=5) plt.title('Median filtered: %s' % im.name) ps.savefig() #print 'Subtracting median:', medsky #img -= medsky img -= medimg primhdr = im.read_image_primary_header() magzp = decals.get_zeropoint_for(im) print('magzp', magzp) zpscale = NanoMaggies.zeropointToScale(magzp) print('zpscale', zpscale) # Scale images to Nanomaggies img /= zpscale sig1 /= zpscale invvar *= zpscale**2 orig_zpscale = zpscale zpscale = 1. assert (np.sum(invvar > 0) > 0) print('After scaling:') print('sig1', sig1) print('invvar range', invvar.min(), invvar.max()) print('image range', img.min(), img.max()) assert (np.all(np.isfinite(img))) assert (np.all(np.isfinite(invvar))) assert (np.isfinite(sig1)) plt.clf() lo, hi = -5 * sig1, 10 * sig1 n, b, p = plt.hist(img[goodpix].ravel(), 100, range=(lo, hi), histtype='step', color='k') xx = np.linspace(lo, hi, 200) plt.plot(xx, max(n) * np.exp(-xx**2 / (2. * sig1**2)), 'r-') plt.xlim(lo, hi) plt.title('Pixel histogram: %s' % im.name) ps.savefig() twcs = ConstantFitsWcs(wcs) if x0 or y0: twcs.setX0Y0(x0, y0) info = im.get_image_info() fullh, fullw = info['dims'] # read fit PsfEx model psfex = PsfEx.fromFits(im.psffitfn) print('Read', psfex) # HACK -- highly approximate PSF here! #psf_fwhm = imghdr['FWHM'] #psf_fwhm = im.seeing psf_fwhm = im.seeing / (im.pixscale * 3600) print('PSF FWHM', psf_fwhm, 'pixels') psf_sigma = psf_fwhm / 2.35 psf = NCircularGaussianPSF([psf_sigma], [1.]) print('img type', img.dtype) tim = Image(img, invvar=invvar, wcs=twcs, psf=psf, photocal=LinearPhotoCal(zpscale, band=band), sky=ConstantSky(0.), name=im.name + ' ' + band) tim.zr = [-3. * sig1, 10. * sig1] tim.sig1 = sig1 tim.band = band tim.psf_fwhm = psf_fwhm tim.psf_sigma = psf_sigma tim.sip_wcs = wcs tim.x0, tim.y0 = int(x0), int(y0) tim.psfex = psfex tim.imobj = im mn, mx = tim.zr tim.ima = dict(interpolation='nearest', origin='lower', cmap='gray', vmin=mn, vmax=mx) tims.append(tim) keepims.append(im) ims = keepims print('Computing resampling...') # save resampling params for tim in tims: wcs = tim.sip_wcs subh, subw = tim.shape subwcs = wcs.get_subimage(tim.x0, tim.y0, subw, subh) tim.subwcs = subwcs try: Yo, Xo, Yi, Xi, rims = resample_with_wcs(targetwcs, subwcs, [], 2) except OverlapError: print('No overlap') continue if len(Yo) == 0: continue tim.resamp = (Yo, Xo, Yi, Xi) print('Creating coadds...') # Produce per-band coadds, for plots coimgs = [] cons = [] for ib, band in enumerate(bands): coimg = np.zeros((H, W), np.float32) con = np.zeros((H, W), np.uint8) for tim in tims: if tim.band != band: continue (Yo, Xo, Yi, Xi) = tim.resamp if len(Yo) == 0: continue nn = (tim.getInvvar()[Yi, Xi] > 0) coimg[Yo, Xo] += tim.getImage()[Yi, Xi] * nn con[Yo, Xo] += nn # print # print 'tim', tim.name # print 'number of resampled pix:', len(Yo) # reim = np.zeros_like(coimg) # ren = np.zeros_like(coimg) # reim[Yo,Xo] = tim.getImage()[Yi,Xi] * nn # ren[Yo,Xo] = nn # print 'number of resampled pix with positive invvar:', ren.sum() # plt.clf() # plt.subplot(2,2,1) # mn,mx = [np.percentile(reim[ren>0], p) for p in [25,95]] # print 'Percentiles:', mn,mx # dimshow(reim, vmin=mn, vmax=mx) # plt.colorbar() # plt.subplot(2,2,2) # dimshow(con) # plt.colorbar() # plt.subplot(2,2,3) # dimshow(reim, vmin=tim.zr[0], vmax=tim.zr[1]) # plt.colorbar() # plt.subplot(2,2,4) # plt.hist(reim.ravel(), 100, histtype='step', color='b') # plt.hist(tim.getImage().ravel(), 100, histtype='step', color='r') # plt.suptitle('%s: %s' % (band, tim.name)) # ps.savefig() coimg /= np.maximum(con, 1) coimgs.append(coimg) cons.append(con) plt.clf() dimshow(get_rgb(coimgs, bands)) ps.savefig() plt.clf() for i, b in enumerate(bands): plt.subplot(2, 2, i + 1) dimshow(cons[i], ticks=False) plt.title('%s band' % b) plt.colorbar() plt.suptitle('Number of exposures') ps.savefig() print('Grabbing SDSS sources...') bandlist = [b for b in bands] cat, T = get_sdss_sources(bandlist, targetwcs) # record coordinates in target brick image ok, T.tx, T.ty = targetwcs.radec2pixelxy(T.ra, T.dec) T.tx -= 1 T.ty -= 1 T.itx = np.clip(np.round(T.tx).astype(int), 0, W - 1) T.ity = np.clip(np.round(T.ty).astype(int), 0, H - 1) plt.clf() dimshow(get_rgb(coimgs, bands)) ax = plt.axis() plt.plot(T.tx, T.ty, 'o', mec=green, mfc='none', ms=10, mew=1.5) plt.axis(ax) plt.title('SDSS sources') ps.savefig() print('Detmaps...') # Render the detection maps detmaps = dict([(b, np.zeros((H, W), np.float32)) for b in bands]) detivs = dict([(b, np.zeros((H, W), np.float32)) for b in bands]) for tim in tims: iv = tim.getInvvar() psfnorm = 1. / (2. * np.sqrt(np.pi) * tim.psf_sigma) detim = tim.getImage().copy() detim[iv == 0] = 0. detim = gaussian_filter(detim, tim.psf_sigma) / psfnorm**2 detsig1 = tim.sig1 / psfnorm subh, subw = tim.shape detiv = np.zeros((subh, subw), np.float32) + (1. / detsig1**2) detiv[iv == 0] = 0. (Yo, Xo, Yi, Xi) = tim.resamp detmaps[tim.band][Yo, Xo] += detiv[Yi, Xi] * detim[Yi, Xi] detivs[tim.band][Yo, Xo] += detiv[Yi, Xi] rtn = dict() for k in [ 'T', 'coimgs', 'cons', 'detmaps', 'detivs', 'targetrd', 'pixscale', 'targetwcs', 'W', 'H', 'bands', 'tims', 'ps', 'brick', 'cat' ]: rtn[k] = locals()[k] return rtn
def stage2(cat=None, variances=None, T=None, bands=None, ps=None, targetwcs=None, **kwargs): print('kwargs:', kwargs.keys()) #print 'variances:', variances from desi_common import prepare_fits_catalog TT = T.copy() hdr = None fs = None T2, hdr = prepare_fits_catalog(cat, 1. / np.array(variances), TT, hdr, bands, fs) T2.about() T2.writeto('cfht.fits') ccmap = dict(g='g', r='r', i='m') bandlist = [b for b in bands] scat, S = get_sdss_sources(bandlist, targetwcs) S.about() I, J, d = match_radec(T2.ra, T2.dec, S.ra, S.dec, 1. / 3600.) M = fits_table() M.ra = S.ra[J] M.dec = S.dec[J] M.cfhtI = I for band in bands: mag = T2.get('decam_%s_mag' % band)[I] sflux = np.array([s.getBrightness().getBand(band) for s in scat])[J] smag = NanoMaggies.nanomaggiesToMag(sflux) M.set('mag_%s' % band, mag) M.set('smag_%s' % band, smag) cc = ccmap[band] plt.clf() plt.subplot(2, 1, 1) plt.plot(smag, mag, '.', color=cc, alpha=0.5) lo, hi = 16, 24 plt.plot([lo, hi], [lo, hi], 'k-') plt.xlabel('SDSS mag') plt.ylabel('CFHT mag') plt.axis([lo, hi, lo, hi]) plt.subplot(2, 1, 2) plt.plot(smag, mag - smag, '.', color=cc, alpha=0.5) lo, hi = 16, 24 plt.plot([lo, hi], [0, 0], 'k-') plt.xlabel('SDSS mag') plt.ylabel('CFHT - SDSS mag') plt.axis([lo, hi, -1, 1]) plt.suptitle('%s band' % band) ps.savefig() M.writeto('cfht-matched.fits') plt.clf() lp, lt = [], [] for band in bands: sn = T2.get('decam_%s_nanomaggies' % band) * np.sqrt( T2.get('decam_%s_nanomaggies_invvar' % band)) #mag = T2.get('decam_%s_mag_corr' % band) mag = T2.get('decam_%s_mag' % band) print('band', band) print('Mags:', mag) print('SN:', sn) cc = ccmap[band] p = plt.semilogy(mag, sn, '.', color=cc, alpha=0.5) lp.append(p[0]) lt.append('%s band' % band) plt.xlabel('mag') plt.ylabel('Flux Signal-to-Noise') tt = [1, 2, 3, 4, 5, 10, 20, 30, 40, 50] plt.yticks(tt, ['%i' % t for t in tt]) plt.axhline(5., color='k') #plt.axis([21, 26, 1, 20]) plt.legend(lp, lt, loc='upper right') plt.title('CFHT depth') ps.savefig() # ['tims', 'cons', 'pixscale', 'H', 'coimgs', 'detmaps', 'W', 'brick', 'detivs', 'targetrd'] return dict(T2=T2, M=M, tims=None, detmaps=None, detivs=None, cons=None, coimgs=None)
def main(): decals = Decals() catpattern = 'pipebrick-cats/tractor-phot-b%06i.fits' ra, dec = 242, 7 # Region-of-interest, in pixels: x0, x1, y0, y1 #roi = None roi = [500, 1000, 500, 1000] if roi is not None: x0, x1, y0, y1 = roi #expnum = 346623 #ccdname = 'N12' #chips = decals.find_ccds(expnum=expnum, extname=ccdname) #print 'Found', len(chips), 'chips for expnum', expnum, 'extname', ccdname #if len(chips) != 1: #return False chips = decals.get_ccds() D = np.argsort(np.hypot(chips.ra - ra, chips.dec - dec)) print('Closest chip:', chips[D[0]]) chips = [chips[D[0]]] im = DecamImage(decals, chips[0]) print('Image:', im) targetwcs = Sip(im.wcsfn) if roi is not None: targetwcs = targetwcs.get_subimage(x0, y0, x1 - x0, y1 - y0) r0, r1, d0, d1 = targetwcs.radec_bounds() # ~ 30-pixel margin margin = 2e-3 if r0 > r1: # RA wrap-around TT = [ brick_catalog_for_radec_box(ra, rb, d0 - margin, d1 + margin, decals, catpattern) for (ra, rb) in [(0, r1 + margin), (r0 - margin, 360.)] ] T = merge_tables(TT) T._header = TT[0]._header else: T = brick_catalog_for_radec_box(r0 - margin, r1 + margin, d0 - margin, d1 + margin, decals, catpattern) print('Got', len(T), 'catalog entries within range') cat = read_fits_catalog(T, T._header) print('Got', len(cat), 'catalog objects') print('Switching ellipse parameterizations') switch_to_soft_ellipses(cat) keepcat = [] for src in cat: if not np.all(np.isfinite(src.getParams())): print('Src has infinite params:', src) continue if isinstance(src, FixedCompositeGalaxy): f = src.fracDev.getClippedValue() if f == 0.: src = ExpGalaxy(src.pos, src.brightness, src.shapeExp) elif f == 1.: src = DevGalaxy(src.pos, src.brightness, src.shapeDev) keepcat.append(src) cat = keepcat slc = None if roi is not None: slc = slice(y0, y1), slice(x0, x1) tim = im.get_tractor_image(slc=slc) print('Got', tim) tim.psfex.fitSavedData(*tim.psfex.splinedata) tim.psfex.radius = 20 tim.psf = CachingPsfEx.fromPsfEx(tim.psfex) tractor = Tractor([tim], cat) print('Created', tractor) mod = tractor.getModelImage(0) plt.clf() dimshow(tim.getImage(), **tim.ima) plt.title('Image') plt.savefig('1.png') plt.clf() dimshow(mod, **tim.ima) plt.title('Model') plt.savefig('2.png') ok, x, y = targetwcs.radec2pixelxy([src.getPosition().ra for src in cat], [src.getPosition().dec for src in cat]) ax = plt.axis() plt.plot(x, y, 'rx') #plt.savefig('3.png') plt.axis(ax) plt.title('Sources') plt.savefig('3.png') bands = [im.band] import runbrick runbrick.photoobjdir = '.' scat, T = get_sdss_sources(bands, targetwcs, local=False) print('Got', len(scat), 'SDSS sources in bounds') stractor = Tractor([tim], scat) print('Created', stractor) smod = stractor.getModelImage(0) plt.clf() dimshow(smod, **tim.ima) plt.title('SDSS model') plt.savefig('4.png')
def stage2(cat=None, variances=None, T=None, bands=None, ps=None, targetwcs=None, **kwargs): print 'kwargs:', kwargs.keys() #print 'variances:', variances from desi_common import prepare_fits_catalog TT = T.copy() hdr = None fs = None T2,hdr = prepare_fits_catalog(cat, 1./np.array(variances), TT, hdr, bands, fs) T2.about() T2.writeto('cfht.fits') ccmap = dict(g='g', r='r', i='m') bandlist = [b for b in bands] scat,S = get_sdss_sources(bandlist, targetwcs) S.about() I,J,d = match_radec(T2.ra, T2.dec, S.ra, S.dec, 1./3600.) M = fits_table() M.ra = S.ra[J] M.dec = S.dec[J] M.cfhtI = I for band in bands: mag = T2.get('decam_%s_mag' % band)[I] sflux = np.array([s.getBrightness().getBand(band) for s in scat])[J] smag = NanoMaggies.nanomaggiesToMag(sflux) M.set('mag_%s' % band, mag) M.set('smag_%s' % band, smag) cc = ccmap[band] plt.clf() plt.subplot(2,1,1) plt.plot(smag, mag, '.', color=cc, alpha=0.5) lo,hi = 16,24 plt.plot([lo,hi],[lo,hi], 'k-') plt.xlabel('SDSS mag') plt.ylabel('CFHT mag') plt.axis([lo,hi,lo,hi]) plt.subplot(2,1,2) plt.plot(smag, mag - smag, '.', color=cc, alpha=0.5) lo,hi = 16,24 plt.plot([lo,hi],[0, 0], 'k-') plt.xlabel('SDSS mag') plt.ylabel('CFHT - SDSS mag') plt.axis([lo,hi,-1,1]) plt.suptitle('%s band' % band) ps.savefig() M.writeto('cfht-matched.fits') plt.clf() lp,lt = [],[] for band in bands: sn = T2.get('decam_%s_nanomaggies' % band) * np.sqrt(T2.get('decam_%s_nanomaggies_invvar' % band)) #mag = T2.get('decam_%s_mag_corr' % band) mag = T2.get('decam_%s_mag' % band) print 'band', band print 'Mags:', mag print 'SN:', sn cc = ccmap[band] p = plt.semilogy(mag, sn, '.', color=cc, alpha=0.5) lp.append(p[0]) lt.append('%s band' % band) plt.xlabel('mag') plt.ylabel('Flux Signal-to-Noise') tt = [1,2,3,4,5,10,20,30,40,50] plt.yticks(tt, ['%i' % t for t in tt]) plt.axhline(5., color='k') #plt.axis([21, 26, 1, 20]) plt.legend(lp, lt, loc='upper right') plt.title('CFHT depth') ps.savefig() # ['tims', 'cons', 'pixscale', 'H', 'coimgs', 'detmaps', 'W', 'brick', 'detivs', 'targetrd'] return dict(T2=T2, M=M, tims=None, detmaps=None, detivs=None, cons=None, coimgs=None)
def stage0(**kwargs): ps = PlotSequence('cfht') decals = CfhtDecals() B = decals.get_bricks() print 'Bricks:' B.about() ra,dec = 190.0, 11.0 #bands = 'ugri' bands = 'gri' B.cut(np.argsort(degrees_between(ra, dec, B.ra, B.dec))) print 'Nearest bricks:', B.ra[:5], B.dec[:5], B.brickid[:5] brick = B[0] pixscale = 0.186 #W,H = 1024,1024 #W,H = 2048,2048 #W,H = 3600,3600 W,H = 4800,4800 targetwcs = wcs_for_brick(brick, pixscale=pixscale, W=W, H=H) ccdfn = 'cfht-ccds.fits' if os.path.exists(ccdfn): T = fits_table(ccdfn) else: T = get_ccd_list() T.writeto(ccdfn) print len(T), 'CCDs' T.cut(ccds_touching_wcs(targetwcs, T)) print len(T), 'CCDs touching brick' T.cut(np.array([b in bands for b in T.filter])) print len(T), 'in bands', bands ims = [] for t in T: im = CfhtImage(t) # magzp = hdr['PHOT_C'] + 2.5 * np.log10(hdr['EXPTIME']) # fwhm = t.seeing / (pixscale * 3600) # print '-> FWHM', fwhm, 'pix' im.seeing = t.seeing im.pixscale = t.pixscale print 'seeing', t.seeing print 'pixscale', im.pixscale*3600, 'arcsec/pix' im.run_calibs(t.ra, t.dec, im.pixscale, W=t.width, H=t.height) ims.append(im) # Read images, clip to ROI targetrd = np.array([targetwcs.pixelxy2radec(x,y) for x,y in [(1,1),(W,1),(W,H),(1,H),(1,1)]]) keepims = [] tims = [] for im in ims: print print 'Reading expnum', im.expnum, 'name', im.extname, 'band', im.band, 'exptime', im.exptime band = im.band wcs = im.read_wcs() imh,imw = wcs.imageh,wcs.imagew imgpoly = [(1,1),(1,imh),(imw,imh),(imw,1)] ok,tx,ty = wcs.radec2pixelxy(targetrd[:-1,0], targetrd[:-1,1]) tpoly = zip(tx,ty) clip = clip_polygon(imgpoly, tpoly) clip = np.array(clip) #print 'Clip', clip if len(clip) == 0: continue x0,y0 = np.floor(clip.min(axis=0)).astype(int) x1,y1 = np.ceil (clip.max(axis=0)).astype(int) slc = slice(y0,y1+1), slice(x0,x1+1) ## FIXME -- it seems I got lucky and the cross product is ## negative == clockwise, as required by clip_polygon. One ## could check this and reverse the polygon vertex order. # dx0,dy0 = tx[1]-tx[0], ty[1]-ty[0] # dx1,dy1 = tx[2]-tx[1], ty[2]-ty[1] # cross = dx0*dy1 - dx1*dy0 # print 'Cross:', cross print 'Image slice: x [%i,%i], y [%i,%i]' % (x0,x1, y0,y1) print 'Reading image from', im.imgfn, 'HDU', im.hdu img,imghdr = im.read_image(header=True, slice=slc) goodpix = (img != 0) print 'Number of pixels == 0:', np.sum(img == 0) print 'Number of pixels != 0:', np.sum(goodpix) if np.sum(goodpix) == 0: continue # print 'Image shape', img.shape print 'Image range', img.min(), img.max() print 'Goodpix image range:', (img[goodpix]).min(), (img[goodpix]).max() if img[goodpix].min() == img[goodpix].max(): print 'No dynamic range in image' continue # print 'Reading invvar from', im.wtfn, 'HDU', im.hdu # invvar = im.read_invvar(slice=slc) # # print 'Invvar shape', invvar.shape # # print 'Invvar range:', invvar.min(), invvar.max() # invvar[goodpix == 0] = 0. # if np.all(invvar == 0.): # print 'Skipping zero-invvar image' # continue # assert(np.all(np.isfinite(img))) # assert(np.all(np.isfinite(invvar))) # assert(not(np.all(invvar == 0.))) # # Estimate per-pixel noise via Blanton's 5-pixel MAD # slice1 = (slice(0,-5,10),slice(0,-5,10)) # slice2 = (slice(5,None,10),slice(5,None,10)) # # print 'sliced shapes:', img[slice1].shape, img[slice2].shape # # print 'good shape:', (goodpix[slice1] * goodpix[slice2]).shape # # print 'good values:', np.unique(goodpix[slice1] * goodpix[slice2]) # # print 'sliced[good] shapes:', (img[slice1] - img[slice2])[goodpix[slice1] * goodpix[slice2]].shape # mad = np.median(np.abs(img[slice1] - img[slice2])[goodpix[slice1] * goodpix[slice2]].ravel()) # sig1 = 1.4826 * mad / np.sqrt(2.) # print 'MAD sig1:', sig1 # # invvar was 1 or 0 # invvar *= (1./(sig1**2)) # medsky = np.median(img[goodpix]) # Read full image for sig1 and sky estimate fullimg = im.read_image() fullgood = (fullimg != 0) # Estimate per-pixel noise via Blanton's 5-pixel MAD slice1 = (slice(0,-5,10),slice(0,-5,10)) slice2 = (slice(5,None,10),slice(5,None,10)) mad = np.median(np.abs(fullimg[slice1] - fullimg[slice2])[fullgood[slice1] * fullgood[slice2]].ravel()) sig1 = 1.4826 * mad / np.sqrt(2.) print 'MAD sig1:', sig1 medsky = np.median(fullimg[fullgood]) invvar = np.zeros_like(img) invvar[goodpix] = 1./sig1**2 # Median-smooth sky subtraction plt.clf() dimshow(np.round((img-medsky) / sig1), vmin=-3, vmax=5) plt.title('Scalar median: %s' % im.name) ps.savefig() # medsky = np.zeros_like(img) # # astrometry.util.util # median_smooth(img, np.logical_not(goodpix), 256, medsky) fullmed = np.zeros_like(fullimg) median_smooth(fullimg - medsky, np.logical_not(fullgood), 256, fullmed) fullmed += medsky medimg = fullmed[slc] plt.clf() dimshow(np.round((img - medimg) / sig1), vmin=-3, vmax=5) plt.title('Median filtered: %s' % im.name) ps.savefig() #print 'Subtracting median:', medsky #img -= medsky img -= medimg primhdr = im.read_image_primary_header() magzp = decals.get_zeropoint_for(im) print 'magzp', magzp zpscale = NanoMaggies.zeropointToScale(magzp) print 'zpscale', zpscale # Scale images to Nanomaggies img /= zpscale sig1 /= zpscale invvar *= zpscale**2 orig_zpscale = zpscale zpscale = 1. assert(np.sum(invvar > 0) > 0) print 'After scaling:' print 'sig1', sig1 print 'invvar range', invvar.min(), invvar.max() print 'image range', img.min(), img.max() assert(np.all(np.isfinite(img))) assert(np.all(np.isfinite(invvar))) assert(np.isfinite(sig1)) plt.clf() lo,hi = -5*sig1, 10*sig1 n,b,p = plt.hist(img[goodpix].ravel(), 100, range=(lo,hi), histtype='step', color='k') xx = np.linspace(lo, hi, 200) plt.plot(xx, max(n)*np.exp(-xx**2 / (2.*sig1**2)), 'r-') plt.xlim(lo,hi) plt.title('Pixel histogram: %s' % im.name) ps.savefig() twcs = ConstantFitsWcs(wcs) if x0 or y0: twcs.setX0Y0(x0,y0) info = im.get_image_info() fullh,fullw = info['dims'] # read fit PsfEx model psfex = PsfEx.fromFits(im.psffitfn) print 'Read', psfex # HACK -- highly approximate PSF here! #psf_fwhm = imghdr['FWHM'] #psf_fwhm = im.seeing psf_fwhm = im.seeing / (im.pixscale * 3600) print 'PSF FWHM', psf_fwhm, 'pixels' psf_sigma = psf_fwhm / 2.35 psf = NCircularGaussianPSF([psf_sigma],[1.]) print 'img type', img.dtype tim = Image(img, invvar=invvar, wcs=twcs, psf=psf, photocal=LinearPhotoCal(zpscale, band=band), sky=ConstantSky(0.), name=im.name + ' ' + band) tim.zr = [-3. * sig1, 10. * sig1] tim.sig1 = sig1 tim.band = band tim.psf_fwhm = psf_fwhm tim.psf_sigma = psf_sigma tim.sip_wcs = wcs tim.x0,tim.y0 = int(x0),int(y0) tim.psfex = psfex tim.imobj = im mn,mx = tim.zr tim.ima = dict(interpolation='nearest', origin='lower', cmap='gray', vmin=mn, vmax=mx) tims.append(tim) keepims.append(im) ims = keepims print 'Computing resampling...' # save resampling params for tim in tims: wcs = tim.sip_wcs subh,subw = tim.shape subwcs = wcs.get_subimage(tim.x0, tim.y0, subw, subh) tim.subwcs = subwcs try: Yo,Xo,Yi,Xi,rims = resample_with_wcs(targetwcs, subwcs, [], 2) except OverlapError: print 'No overlap' continue if len(Yo) == 0: continue tim.resamp = (Yo,Xo,Yi,Xi) print 'Creating coadds...' # Produce per-band coadds, for plots coimgs = [] cons = [] for ib,band in enumerate(bands): coimg = np.zeros((H,W), np.float32) con = np.zeros((H,W), np.uint8) for tim in tims: if tim.band != band: continue (Yo,Xo,Yi,Xi) = tim.resamp if len(Yo) == 0: continue nn = (tim.getInvvar()[Yi,Xi] > 0) coimg[Yo,Xo] += tim.getImage ()[Yi,Xi] * nn con [Yo,Xo] += nn # print # print 'tim', tim.name # print 'number of resampled pix:', len(Yo) # reim = np.zeros_like(coimg) # ren = np.zeros_like(coimg) # reim[Yo,Xo] = tim.getImage()[Yi,Xi] * nn # ren[Yo,Xo] = nn # print 'number of resampled pix with positive invvar:', ren.sum() # plt.clf() # plt.subplot(2,2,1) # mn,mx = [np.percentile(reim[ren>0], p) for p in [25,95]] # print 'Percentiles:', mn,mx # dimshow(reim, vmin=mn, vmax=mx) # plt.colorbar() # plt.subplot(2,2,2) # dimshow(con) # plt.colorbar() # plt.subplot(2,2,3) # dimshow(reim, vmin=tim.zr[0], vmax=tim.zr[1]) # plt.colorbar() # plt.subplot(2,2,4) # plt.hist(reim.ravel(), 100, histtype='step', color='b') # plt.hist(tim.getImage().ravel(), 100, histtype='step', color='r') # plt.suptitle('%s: %s' % (band, tim.name)) # ps.savefig() coimg /= np.maximum(con,1) coimgs.append(coimg) cons .append(con) plt.clf() dimshow(get_rgb(coimgs, bands)) ps.savefig() plt.clf() for i,b in enumerate(bands): plt.subplot(2,2,i+1) dimshow(cons[i], ticks=False) plt.title('%s band' % b) plt.colorbar() plt.suptitle('Number of exposures') ps.savefig() print 'Grabbing SDSS sources...' bandlist = [b for b in bands] cat,T = get_sdss_sources(bandlist, targetwcs) # record coordinates in target brick image ok,T.tx,T.ty = targetwcs.radec2pixelxy(T.ra, T.dec) T.tx -= 1 T.ty -= 1 T.itx = np.clip(np.round(T.tx).astype(int), 0, W-1) T.ity = np.clip(np.round(T.ty).astype(int), 0, H-1) plt.clf() dimshow(get_rgb(coimgs, bands)) ax = plt.axis() plt.plot(T.tx, T.ty, 'o', mec=green, mfc='none', ms=10, mew=1.5) plt.axis(ax) plt.title('SDSS sources') ps.savefig() print 'Detmaps...' # Render the detection maps detmaps = dict([(b, np.zeros((H,W), np.float32)) for b in bands]) detivs = dict([(b, np.zeros((H,W), np.float32)) for b in bands]) for tim in tims: iv = tim.getInvvar() psfnorm = 1./(2. * np.sqrt(np.pi) * tim.psf_sigma) detim = tim.getImage().copy() detim[iv == 0] = 0. detim = gaussian_filter(detim, tim.psf_sigma) / psfnorm**2 detsig1 = tim.sig1 / psfnorm subh,subw = tim.shape detiv = np.zeros((subh,subw), np.float32) + (1. / detsig1**2) detiv[iv == 0] = 0. (Yo,Xo,Yi,Xi) = tim.resamp detmaps[tim.band][Yo,Xo] += detiv[Yi,Xi] * detim[Yi,Xi] detivs [tim.band][Yo,Xo] += detiv[Yi,Xi] rtn = dict() for k in ['T', 'coimgs', 'cons', 'detmaps', 'detivs', 'targetrd', 'pixscale', 'targetwcs', 'W','H', 'bands', 'tims', 'ps', 'brick', 'cat']: rtn[k] = locals()[k] return rtn
def main(): decals = Decals() catpattern = 'pipebrick-cats/tractor-phot-b%06i.fits' ra,dec = 242, 7 # Region-of-interest, in pixels: x0, x1, y0, y1 #roi = None roi = [500, 1000, 500, 1000] if roi is not None: x0,x1,y0,y1 = roi #expnum = 346623 #ccdname = 'N12' #chips = decals.find_ccds(expnum=expnum, extname=ccdname) #print 'Found', len(chips), 'chips for expnum', expnum, 'extname', ccdname #if len(chips) != 1: #return False chips = decals.get_ccds() D = np.argsort(np.hypot(chips.ra - ra, chips.dec - dec)) print('Closest chip:', chips[D[0]]) chips = [chips[D[0]]] im = DecamImage(decals, chips[0]) print('Image:', im) targetwcs = Sip(im.wcsfn) if roi is not None: targetwcs = targetwcs.get_subimage(x0, y0, x1-x0, y1-y0) r0,r1,d0,d1 = targetwcs.radec_bounds() # ~ 30-pixel margin margin = 2e-3 if r0 > r1: # RA wrap-around TT = [brick_catalog_for_radec_box(ra,rb, d0-margin,d1+margin, decals, catpattern) for (ra,rb) in [(0, r1+margin), (r0-margin, 360.)]] T = merge_tables(TT) T._header = TT[0]._header else: T = brick_catalog_for_radec_box(r0-margin,r1+margin,d0-margin, d1+margin, decals, catpattern) print('Got', len(T), 'catalog entries within range') cat = read_fits_catalog(T, T._header) print('Got', len(cat), 'catalog objects') print('Switching ellipse parameterizations') switch_to_soft_ellipses(cat) keepcat = [] for src in cat: if not np.all(np.isfinite(src.getParams())): print('Src has infinite params:', src) continue if isinstance(src, FixedCompositeGalaxy): f = src.fracDev.getClippedValue() if f == 0.: src = ExpGalaxy(src.pos, src.brightness, src.shapeExp) elif f == 1.: src = DevGalaxy(src.pos, src.brightness, src.shapeDev) keepcat.append(src) cat = keepcat slc = None if roi is not None: slc = slice(y0,y1), slice(x0,x1) tim = im.get_tractor_image(slc=slc) print('Got', tim) tim.psfex.fitSavedData(*tim.psfex.splinedata) tim.psfex.radius = 20 tim.psf = CachingPsfEx.fromPsfEx(tim.psfex) tractor = Tractor([tim], cat) print('Created', tractor) mod = tractor.getModelImage(0) plt.clf() dimshow(tim.getImage(), **tim.ima) plt.title('Image') plt.savefig('1.png') plt.clf() dimshow(mod, **tim.ima) plt.title('Model') plt.savefig('2.png') ok,x,y = targetwcs.radec2pixelxy([src.getPosition().ra for src in cat], [src.getPosition().dec for src in cat]) ax = plt.axis() plt.plot(x, y, 'rx') #plt.savefig('3.png') plt.axis(ax) plt.title('Sources') plt.savefig('3.png') bands = [im.band] import runbrick runbrick.photoobjdir = '.' scat,T = get_sdss_sources(bands, targetwcs, local=False) print('Got', len(scat), 'SDSS sources in bounds') stractor = Tractor([tim], scat) print('Created', stractor) smod = stractor.getModelImage(0) plt.clf() dimshow(smod, **tim.ima) plt.title('SDSS model') plt.savefig('4.png')