def _meisner_psf_models(): global plotslice # Meisner's PSF models # for band in [4]: for band in [1, 2, 3, 4]: print() print('W%i' % band) print() #pix = fitsio.read('wise-psf-avg-pix.fits', ext=band-1) pix = fitsio.read('wise-psf-avg-pix-bright.fits', ext=band - 1) fit = fits_table('wise-psf-avg.fits', hdu=band) #fit = fits_table('psf-allwise-con3.fits', hdu=band) scale = 1. print('Pix shape', pix.shape) h, w = pix.shape xx, yy = np.meshgrid(np.arange(w), np.arange(h)) cx, cy = np.sum(xx * pix) / np.sum(pix), np.sum(yy * pix) / np.sum(pix) print('Centroid:', cx, cy) #S = 100 S = h / 2 slc = slice(h / 2 - S, h / 2 + S + 1), slice(w / 2 - S, w / 2 + S + 1) plotss = 30 plotslice = slice(S - plotss, -(S - plotss)), slice(S - plotss, -(S - plotss)) opix = pix print('Original pixels sum:', opix.sum()) pix /= pix.sum() pix = pix[slc] print('Sliced pix sum', pix.sum()) psf = GaussianMixturePSF(fit.amp, fit.mean * scale, fit.var * scale**2) psfmodel = psf.getPointSourcePatch(0., 0., radius=h / 2) mod = psfmodel.patch print('Orig mod sum', mod.sum()) mod = mod[slc] print('Sliced mod sum', mod.sum()) print('Amps:', np.sum(psf.mog.amp)) _plot_psf(pix, mod, psf) plt.suptitle('W%i: Orig' % band) ps.savefig() # Lanczos sub-sample if band == 4: lpix = _lanczos_subsample(opix, 2) pix = lpix h, w = pix.shape #S = 140 slc = slice(h / 2 - S, h / 2 + S + 1), slice(w / 2 - S, w / 2 + S + 1) print('Resampled pix sum', pix.sum()) pix = pix[slc] print('sliced pix sum', pix.sum()) psf = GaussianMixturePSF(fit.amp, fit.mean * scale, fit.var * scale**2) psfmodel = psf.getPointSourcePatch(0., 0., radius=h / 2) mod = psfmodel.patch print('Scaled mod sum', mod.sum()) mod = mod[slc] print('Sliced mod sum', mod.sum()) _plot_psf(pix, mod, psf) plt.suptitle('W%i: Scaled' % band) ps.savefig() plotslice = slice(S - plotss, -(S - plotss)), slice(S - plotss, -(S - plotss)) psfx = GaussianMixturePSF.fromStamp(pix, P0=(fit.amp, fit.mean * scale, fit.var * scale**2)) psfmodel = psfx.getPointSourcePatch(0., 0., radius=h / 2) mod = psfmodel.patch print('From stamp: mod sum', mod.sum()) mod = mod[slc] print('Sliced mod sum:', mod.sum()) _plot_psf(pix, mod, psfx) plt.suptitle('W%i: fromStamp: %g = %s, res %.3f' % (band, np.sum(psfx.mog.amp), ','.join( ['%.3f' % a for a in psfx.mog.amp]), np.sum(pix - mod))) ps.savefig() print('Stamp-Fit PSF params:', psfx) # class MyGaussianMixturePSF(GaussianMixturePSF): # def getLogPrior(self): # if np.any(self.mog.amp < 0.): # return -np.inf # for k in range(self.mog.K): # if np.linalg.det(self.mog.var[k]) <= 0: # return -np.inf # return 0 # # @property # def amp(self): # return self.mog.amp # # mypsf = MyGaussianMixturePSF(psfx.mog.amp, psfx.mog.mean, psfx.mog.var) # mypsf.radius = sh/2 sh, sw = pix.shape # Initialize from original fit params psfx = psf # Try concentric gaussian PSF sigmas = [] for k in range(psfx.mog.K): v = psfx.mog.var[k, :, :] sigmas.append(np.sqrt(np.sqrt(np.abs(v[0, 0] * v[1, 1])))) print('Initializing concentric Gaussian PSF with sigmas', sigmas) gpsf = NCircularGaussianPSF(sigmas, psfx.mog.amp) gpsf.radius = sh / 2 mypsf = gpsf tim = Image(data=pix, invvar=1e6 * np.ones_like(pix), psf=mypsf) tim.modelMinval = 1e-16 # xx,yy = np.meshgrid(np.arange(sw), np.arange(sh)) # cx,cy = np.sum(xx*pix)/np.sum(pix), np.sum(yy*pix)/np.sum(pix) # print 'Centroid:', cx,cy # print 'Pix midpoint:', sw/2, sh/2 cx, cy = sw / 2, sh / 2 src = PointSource(PixPos(cx, cy), Flux(1.0)) tractor = Tractor([tim], [src]) tim.freezeAllBut('psf') # tractor.freezeParam('catalog') src.freezeAllBut('pos') # src.freezeAllBut('brightness') # tractor.freezeParam('images') # tractor.optimize_forced_photometry() # tractor.thawParam('images') # print 'Source flux after forced-photom fit:', src.getBrightness() print('Optimizing Params:') tractor.printThawedParams() for i in range(200): #dlnp,X,alpha = tractor.optimize(damp=0.1) dlnp, X, alpha = tractor.optimize(damp=1) print(i, 'dlnp %.3g' % dlnp, 'psf', gpsf) if dlnp < 1e-6: break tractor.freezeParam('catalog') gpsf.sigmas.stepsize = len(gpsf.sigmas) * [1e-6] gpsf.weights.stepsize = len(gpsf.sigmas) * [1e-6] for i in range(200): #dlnp,X,alpha = tractor.optimize(damp=0.1) dlnp, X, alpha = tractor.optimize(damp=1) print(i, 'dlnp %.3g' % dlnp, 'psf', gpsf) if dlnp < 1e-6: break print('PSF3(opt): flux', src.brightness) print('PSF amps:', np.sum(mypsf.amp)) print('PSF amps * Source brightness:', src.brightness.getValue() * np.sum(mypsf.amp)) print('pix sum:', pix.sum()) print('Optimize source:', src) print('Optimized PSF:', mypsf) mod = tractor.getModelImage(0) print('Mod sum:', mod.sum()) _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join( ['%.3f' % a for a in mypsf.amp]), np.sum(pix - mod))) ps.savefig() # Write before normalizing! T = fits_table() T.amp = mypsf.mog.amp T.mean = mypsf.mog.mean T.var = mypsf.mog.var T.writeto('psf3-w%i.fits' % band) T.writeto('psf3.fits', append=(band != 1)) mypsf.weights.setParams( np.array(mypsf.weights.getParams()) / sum(mypsf.weights.getParams())) print('Normalized PSF weights:', mypsf) mod = tractor.getModelImage(0) print('Mod sum:', mod.sum()) _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join( ['%.3f' % a for a in mypsf.amp]), np.sum(pix - mod))) ps.savefig() class MyGaussianPSF(NCircularGaussianPSF): ''' A PSF model with strictly positive weights that sum to unity. ''' def __init__(self, sigmas, weights): ww = np.array(weights) ww = np.log(ww) super(MyGaussianPSF, self).__init__(sigmas, ww) @staticmethod def getNamedParams(): return dict(sigmas=0, logweights=1) def __str__(self): return ('MyGaussianPSF: sigmas [ ' + ', '.join(['%.3f' % s for s in self.mysigmas]) + ' ], weights [ ' + ', '.join(['%.3f' % w for w in self.myweights]) + ' ]') @property def myweights(self): ww = np.exp(self.logweights.getAllParams()) ww /= ww.sum() return ww @property def weights(self): ww = np.exp(self.logweights.getParams()) wsum = np.sum(np.exp(self.logweights.getAllParams())) return ww / wsum if band == 4: # HACK mypsf = MyGaussianPSF([1.7, 6.4, 15.0], [0.333, 0.666, 0.1]) else: mypsf = MyGaussianPSF(gpsf.sigmas, gpsf.amp) mypsf.radius = sh / 2 tim.psf = mypsf print('Optimizing Params:') tractor.printThawedParams() for i in range(200): #dlnp,X,alpha = tractor.optimize(damp=0.1) dlnp, X, alpha = tractor.optimize(damp=1) print(i, 'dlnp %.3g' % dlnp, 'psf', mypsf) if dlnp < 1e-6: break mypsf.sigmas.stepsize = len(mypsf.sigmas) * [1e-6] mypsf.logweights.stepsize = len(mypsf.sigmas) * [1e-6] for i in range(200): #dlnp,X,alpha = tractor.optimize(damp=0.1) dlnp, X, alpha = tractor.optimize(damp=1) print(i, 'dlnp %.3g' % dlnp, 'psf', mypsf) if dlnp < 1e-6: break print('PSF amps:', np.sum(mypsf.amp)) print('pix sum:', pix.sum()) print('Optimize source:', src) print('Optimized PSF:', mypsf) mod = tractor.getModelImage(0) print('Mod sum:', mod.sum()) _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt2): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join( ['%.3f' % a for a in mypsf.amp]), np.sum(pix - mod))) ps.savefig() # Write mog = mypsf.getMixtureOfGaussians() T = fits_table() T.amp = mog.amp T.mean = mog.mean T.var = mog.var T.writeto('psf4.fits', append=(band != 1))
def simult_photom(cat0=None, WW=None, band=None, tims=None, allrois=None, badrois=None, groups=None, tgroups=None, minsb=None, gslices=None, cat=None, opt=None, ps=None): def _plot_grid(ims, kwas): N = len(ims) C = int(np.ceil(np.sqrt(N))) R = int(np.ceil(N / float(C))) plt.clf() for i,(im,kwa) in enumerate(zip(ims, kwas)): plt.subplot(R,C, i+1) #print 'plotting grid cell', i, 'img shape', im.shape plt.imshow(im, **kwa) plt.gray() plt.xticks([]); plt.yticks([]) return R,C def _plot_grid2(ims, cat, tims, kwas, ptype='mod'): xys = [] stamps = [] for (img,mod,chi,roi),tim in zip(ims, tims): if ptype == 'mod': stamps.append(mod) elif ptype == 'chi': stamps.append(chi) wcs = tim.getWcs() y0,x0 = roi[0].start, roi[1].start xy = [] for src in cat: xi,yi = wcs.positionToPixel(src.getPosition()) xy.append((xi - x0, yi - y0)) xys.append(xy) #print 'X,Y source positions in stamp of shape', stamps[-1].shape #print ' ', xy R,C = _plot_grid(stamps, kwas) for i,xy in enumerate(xys): plt.subplot(R, C, i+1) ax = plt.axis() xy = np.array(xy) plt.plot(xy[:,0], xy[:,1], 'r+', lw=2) plt.axis(ax) # Simultaneous photometry if opt.osources: O = fits_table(opt.osources) ocat = Catalog() print 'Other catalog:' for i in range(len(O)): w1 = O.wiseflux[i, 0] s = PointSource(RaDecPos(O.ra[i], O.dec[i]), NanoMaggies(w1=w1)) ocat.append(s) print ocat ocat.freezeParamsRecursive('*') ocat.thawPathsTo(band) # Keep track of params after simultaneous photometry... cat.freezeParamsRecursive('*') cat.thawPathsTo(band) catsim = cat.getParams() if opt.opt: # ... and also after RA,Dec opt. cat.thawPathsTo('ra','dec') catopt = cat.getParams() cat.freezeParamsRecursive('*') cat.thawPathsTo(band) for gi in range(len(gslices)): gl = gi gl += 1 if not gl in groups: print 'Group', gl, 'not in groups array; skipping' continue gsrcs = groups[gl] tsrcs = tgroups[gl] print 'Group', gl print 'gsrcs:', gsrcs print 'tsrcs:', tsrcs if (not gl in allrois) and (not gl in badrois): print 'Group', gl, 'does not touch any images?' continue mytims = [] rois = [] if gl in allrois: for imi,roi in allrois[gl].items(): mytims.append(tims[imi]) rois.append(roi) mybadtims = [] mybadrois = [] if gl in badrois: for imi,roi in badrois[gl].items(): mybadtims.append(tims[imi]) mybadrois.append(roi) print 'Group', gl, 'touches', len(mytims), 'images and', len(mybadtims), 'bad ones' tt = 'group %i: %i+%i sources' % (gl, len(gsrcs), len(tsrcs)) if len(mytims): cat.setParams(catsim) #print 'Restoring catsim:' #cat.printThawedParams() subcat = Catalog(*[cat[i] for i in gsrcs + tsrcs]) for i in range(len(tsrcs)): subcat.freezeParam(len(gsrcs) + i) tractor = Tractor(mytims, subcat) tractor.freezeParam('images') print len(gsrcs), 'sources unfrozen; total', len(subcat) print 'Before fitting:' for src in subcat[:len(gsrcs)]: print ' ', src t0 = Time() ims0,ims1 = tractor.optimize_forced_photometry(minsb=minsb, mindlnp=1., rois=rois) print 'optimize_forced_photometry took', Time()-t0 print 'After fitting:' for src in subcat[:len(gsrcs)]: print ' ', src imas = [dict(interpolation='nearest', origin='lower', vmin=tim.zr[0], vmax=tim.zr[1]) for tim in mytims] imchi = dict(interpolation='nearest', origin='lower', vmin=-5, vmax=5) imchis = [imchi] * len(mytims) _plot_grid([img for (img, mod, chi, roi) in ims0], imas) plt.suptitle('Data: ' + tt) ps.savefig() if ims1 is not None: #_plot_grid([mod for (img, mod, chi, roi) in ims1], imas) _plot_grid2(ims1, subcat, mytims, imas) plt.suptitle('Forced-phot model: ' + tt) ps.savefig() #_plot_grid([chi for (img, mod, chi, roi) in ims1], imchis) _plot_grid2(ims1, subcat, mytims, imchis, ptype='chi') plt.suptitle('Forced-phot chi: ' + tt) ps.savefig() if opt.osources: cc = tractor.catalog tractor.catalog = ocat nil,nil,ims3 = tractor.optimize_forced_photometry(minsb=minsb, rois=rois, justims0=True) tractor.catalog = cc _plot_grid2(ims3, ocat, mytims, imas) plt.suptitle("Schlegel's model: group %i" % gl) ps.savefig() _plot_grid2(ims3, ocat, mytims, imchis, ptype='chi') plt.suptitle("Schlegel's chi: group %i" % gl) ps.savefig() if opt.opt: op1 = ps.getnext() op2 = ps.getnext() #fits[gl] = (tractor, len(gsrcs), rois, op1, op2) # print 'Plotting mods after simul photom' # #_plot_grid([mod for (img, mod, chi, roi) in ims0], imas) # _plot_grid2(ims0, subcat, mytims, imas) # plt.suptitle('Initial model: ' + tt) # ps.savefig() # # print 'Plotting chis after simul photom' # #_plot_grid([chi for (img, mod, chi, roi) in ims0], imchis) # _plot_grid2(ims0, subcat, mytims, imchis, ptype='chi') # plt.suptitle('Initial chi: ' + tt) # ps.savefig() print 'After simultaneous photometry:' subcat.printThawedParams() # Copy updated params to "catsim" catsim = cat.getParams() #print 'Saving catsim:' #cat.printThawedParams() cat.freezeParamsRecursive('*') cat.thawPathsTo(band) WW.nmall = np.array([src.getBrightness().getBand(band) for src in cat]) if len(mytims) and opt.opt: print 'Optimizing RA,Dec' subcat = tractor.catalog # Copy updated forced-phot params from catsim to catopt. #print 'Saving subcat forced-phot params:' #subcat.printThawedParams() fphot = subcat.getParams() cat.thawPathsTo('ra','dec') cat.setParams(catopt) #print 'Copying forced-phot results to catopt:' cat.freezeParamsRecursive('*') cat.thawPathsTo(band) cat.freezeAllBut(*gsrcs) #cat.printThawedParams() NP = cat.numberOfParams() cat.setParams(fphot[:NP]) #print 'Result:' #print 'Restoring catopt:' #cat.printThawedParams() cat.freezeParamsRecursive('*') cat.thawPathsTo(band) NG = len(gsrcs) for i in range(NG): subcat[i].thawPathsTo('ra','dec') p0 = subcat.getParams() print 'Optimizing params:' subcat.printThawedParams() thetims = tractor.images subimgs = [] for i,img in enumerate(thetims): roi = rois[i] y0 = roi[0].start x0 = roi[1].start subwcs = ShiftedWcs(img.wcs, x0, y0) subimg = Image(data=img.data[roi], invvar=img.invvar[roi], psf=img.psf, wcs=subwcs, sky=img.sky, photocal=img.photocal, name=img.name) subimgs.append(subimg) tractor.images = Images(*subimgs) while True: dlnp,X,alpha = tractor.optimize() print 'dlnp', dlnp print 'alpha', alpha if dlnp < 0.1: break p1 = subcat.getParams() print 'Param changes:' for nm,pp0,pp1 in zip(subcat.getParamNames(), p0, p1): print ' ', nm, pp0, 'to', pp1, '; delta', pp1-pp0 cat.thawPathsTo('ra','dec') catopt = cat.getParams() print 'Saving catopt:' cat.printThawedParams() cat.freezeParamsRecursive('ra', 'dec') tractor.images = thetims nil,nil,ims2 = tractor.optimize_forced_photometry(minsb=minsb, rois=rois, justims0=True) print 'Plotting mods after RA,Dec opt' #_plot_grid([mod for (img, mod, chi, roi) in ims2], imas) _plot_grid2(ims2, subcat, mytims, imas) plt.suptitle('RA,Dec-opt model: ' + tt) plt.savefig(op1) print 'Plotting chis after RA,Dec opt' #_plot_grid([chi for (img, mod, chi, roi) in ims2], imchis) _plot_grid2(ims2, subcat, mytims, imchis, ptype='chi') plt.suptitle('RA,Dec-opt chi: ' + tt) plt.savefig(op2) N = len(mybadtims) if N and False: C = int(np.ceil(np.sqrt(N))) R = int(np.ceil(N / float(C))) plt.clf() for i,(tim,roi) in enumerate(zip(mybadtims, mybadrois)): plt.subplot(R,C, i+1) plt.imshow(tim.getImage()[roi], interpolation='nearest', origin='lower', vmin=tim.zr[0], vmax=tim.zr[1]) plt.gray() plt.suptitle('Data in bad regions') ps.savefig() plt.clf() for i,(tim,roi) in enumerate(zip(mybadtims, mybadrois)): plt.subplot(R,C, i+1) plt.imshow(tim.getInvError()[roi], interpolation='nearest', origin='lower') plt.gray() plt.suptitle('Inverr in bad regions') ps.savefig() if gi == 0 and opt.plotmask: alltims = mybadtims+mytims _plot_grid([tim.uncplane[roi] for tim,roi in zip(alltims, mybadrois + rois)], [dict(interpolation='nearest', origin='lower')]*len(alltims)) plt.suptitle('Uncertainty plane') ps.savefig() for bit,txt in [ (0 , 'static: excessively noisy due to high dark current alone'), (1 , 'static: generally noisy [includes bit 0]'), (2 , 'static: dead or very low responsivity'), (3 , 'static: low responsivity or low dark current'), (4 , 'static: high responsivity or high dark current'), (5 , 'static: saturated anywhere in ramp'), (6 , 'static: high, uncertain, or unreliable non-linearity'), (7 , 'static: known broken hardware pixel or excessively noisy responsivity estimate [may include bit 1]'), (9 , 'broken pixel or negative slope fit value'), (10, 'saturated in sample read 1'), (11, 'saturated in sample read 2'), (12, 'saturated in sample read 3'), (13, 'saturated in sample read 4'), (14, 'saturated in sample read 5'), (15, 'saturated in sample read 6'), (16, 'saturated in sample read 7'), (17, 'saturated in sample read 8'), (18, 'saturated in sample read 9'), (21, 'new/transient bad pixel from dynamic masking'), (26, 'non-linearity correction unreliable'), (27, 'contains cosmic-ray or outlier that cannot be classified (from temporal outlier rejection in multi-frame pipeline)'), (28, 'contains positive or negative spike-outlier'), ]: _plot_grid([tim.maskplane[roi] & (1 << bit) for tim,roi in zip(alltims, mybadrois + rois)], [dict(interpolation='nearest', origin='lower', vmin=0, vmax=1)]*len(alltims)) plt.suptitle('Mask: ' + txt) ps.savefig() if opt.opt: fn = opt.output % 998 WW.writeto(fn) print 'Wrote', fn cat.thawPathsTo('ra','dec') cat.setParams(catopt) WW.nmoptrd = np.array([src.getBrightness().getBand(band) for src in cat]) cat.freezeParamsRecursive(band, 'dec') WW.raoptrd = np.array(cat.getParams()) cat.freezeParamsRecursive('ra') cat.thawPathsTo('dec') WW.decoptrd = np.array(cat.getParams()) cat.freezeParamsRecursive('dec') fn = opt.output % 999 WW.writeto(fn) print 'Wrote', fn
def _allwise_psf_models(): global plotslice # AllWISE PSF models for band in [1, 2, 3, 4]: print() print('W%i' % band) print() pix = reduce(np.add, [ fitsio.read('wise-w%i-psf-wpro-09x09-%02ix%02i.fits' % (band, 1 + (i / 9), 1 + (i % 9))) for i in range(9 * 9) ]) print('Pix', pix.shape) h, w = pix.shape print('Pix sum', pix.sum()) print('Pix max', pix.max()) pix /= pix.sum() psf = GaussianMixturePSF.fromStamp(pix) print('Fit PSF', psf) psfmodel = psf.getPointSourcePatch(0., 0., radius=h / 2) mod = psfmodel.patch print('Orig mod sum', mod.sum()) S = h / 2 plotss = 30 plotslice = slice(S - plotss, -(S - plotss)), slice(S - plotss, -(S - plotss)) _plot_psf(pix, mod, psf) plt.suptitle('W%i: from stamp' % band) ps.savefig() # Try concentric gaussian PSF sh, sw = pix.shape sigmas = [] for k in range(psf.mog.K): v = psf.mog.var[k, :, :] sigmas.append(np.sqrt(np.sqrt(v[0, 0] * v[1, 1]))) print('Initializing concentric Gaussian model with sigmas', sigmas) print('And weights', psf.mog.amp) # (Initial) W1: # sig [7.1729391870564569, 24.098952864976805, 108.78869923786333] # weights [ 0.80355109 0.15602835 0.04195982] # sigmas [ 6.928, 17.091, 45.745 ], weights [ 0.760, 0.154, 0.073 ] # W2: # sig [8.2356371659198189, 25.741694812001221, 110.17431488810806] # weights [ 0.80636191 0.1563742 0.03926182] # sigmas [ 7.177, 10.636, 30.247 ], weights [ 0.500, 0.341, 0.134 ] # W3: # sig [6.860124763919889, 19.160849966251824, 134.20812055907825] # weights [ 0.28227047 0.55080156 0.16706357] # sigmas [ 6.850, 18.922, 109.121 ], weights [ 0.276, 0.554, 0.148 ] # W4: # [4.6423676603462001, 5.31542132669962, 18.375512539373585] # weights [ 0.10764341 0.26915295 0.62320374] # (Opt) # sigmas [ 6.293, 6.314, 20.932 ], weights [ 0.129, 0.309, 0.598 ] weights = psf.mog.amp # HACK if band == 4: sigmas = [2., 6., 25.] weights = [0.5, 0.25, 0.25] else: sigmas = [8., 24., 100.] weights = [0.5, 0.25, 0.25] gpsf = NCircularGaussianPSF(sigmas, weights) gpsf.radius = sh / 2 mypsf = gpsf tim = Image(data=pix, invvar=1e6 * np.ones_like(pix), psf=mypsf) cx, cy = sw / 2, sh / 2 src = PointSource(PixPos(cx, cy), Flux(1.0)) tractor = Tractor([tim], [src]) tim.freezeAllBut('psf') # tractor.freezeParam('catalog') src.freezeAllBut('pos') print('Optimizing Params:') tractor.printThawedParams() for i in range(100): dlnp, X, alpha = tractor.optimize(damp=0.1) print('dlnp', dlnp) print('PSF', mypsf) if dlnp < 0.001: break print('PSF3(opt): flux', src.brightness) print('PSF amps:', np.sum(mypsf.amp)) print('PSF amps * Source brightness:', src.brightness.getValue() * np.sum(mypsf.amp)) print('pix sum:', pix.sum()) print('Optimize source:', src) print('Optimized PSF:', mypsf) mod = tractor.getModelImage(0) print('Mod sum:', mod.sum()) print('Mod min:', mod.min()) print('Mod max:', mod.max()) _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join( ['%.3f' % a for a in mypsf.amp]), np.sum(pix - mod))) ps.savefig() # These postage stamps are subsampled at 8x the 2.75"/pix, # except for the W4 one, which is at 4x that. scale = 8 if band == 4: scale = 4 T = fits_table() T.amp = mypsf.mog.amp T.mean = mypsf.mog.mean / scale T.var = mypsf.mog.var / scale**2 T.writeto('psf-allwise-con3-w%i.fits' % band) T.writeto('psf-allwise-con3.fits', append=(band != 1)) mypsf.weights.setParams( np.array(mypsf.weights.getParams()) / sum(mypsf.weights.getParams())) print('Normalized PSF weights:', mypsf) mod = tractor.getModelImage(0) print('Mod sum:', mod.sum()) _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join( ['%.3f' % a for a in mypsf.amp]), np.sum(pix - mod))) ps.savefig()
mypsf.mog.mean[:2, :], mypsf.mog.var[:2, :, :]) psf2.radius = sh / 2 tim.psf = psf2 mod = tractor.getModelImage(0) _plot_psf(lpix, mod, psf2, flux=src.brightness.getValue()) plt.suptitle('psf2 (init)') ps.savefig() src.freezeAllBut('brightness') tractor.freezeParam('catalog') for i in range(100): print('Optimizing PSF:') tractor.printThawedParams() dlnp, X, alpha = tractor.optimize(damp=1.) tractor.freezeParam('images') tractor.thawParam('catalog') print('Optimizing flux:') tractor.printThawedParams() tractor.optimize_forced_photometry() tractor.thawParam('images') tractor.freezeParam('catalog') mod = tractor.getModelImage(0) _plot_psf(lpix, mod, psf2, flux=src.brightness.getValue()) plt.suptitle('psf2 (opt)') ps.savefig()
def _meisner_psf_models(): global plotslice # Meisner's PSF models #for band in [4]: for band in [1,2,3,4]: print print 'W%i' % band print #pix = fitsio.read('wise-psf-avg-pix.fits', ext=band-1) pix = fitsio.read('wise-psf-avg-pix-bright.fits', ext=band-1) fit = fits_table('wise-psf-avg.fits', hdu=band) #fit = fits_table('psf-allwise-con3.fits', hdu=band) scale = 1. print 'Pix shape', pix.shape h,w = pix.shape xx,yy = np.meshgrid(np.arange(w), np.arange(h)) cx,cy = np.sum(xx*pix)/np.sum(pix), np.sum(yy*pix)/np.sum(pix) print 'Centroid:', cx,cy #S = 100 S = h/2 slc = slice(h/2-S, h/2+S+1), slice(w/2-S, w/2+S+1) plotss = 30 plotslice = slice(S-plotss, -(S-plotss)), slice(S-plotss, -(S-plotss)) opix = pix print 'Original pixels sum:', opix.sum() pix /= pix.sum() pix = pix[slc] print 'Sliced pix sum', pix.sum() psf = GaussianMixturePSF(fit.amp, fit.mean * scale, fit.var * scale**2) psfmodel = psf.getPointSourcePatch(0., 0., radius=h/2) mod = psfmodel.patch print 'Orig mod sum', mod.sum() mod = mod[slc] print 'Sliced mod sum', mod.sum() print 'Amps:', np.sum(psf.mog.amp) _plot_psf(pix, mod, psf) plt.suptitle('W%i: Orig' % band) ps.savefig() # Lanczos sub-sample if band == 4: lpix = _lanczos_subsample(opix, 2) pix = lpix h,w = pix.shape #S = 140 slc = slice(h/2-S, h/2+S+1), slice(w/2-S, w/2+S+1) print 'Resampled pix sum', pix.sum() pix = pix[slc] print 'sliced pix sum', pix.sum() psf = GaussianMixturePSF(fit.amp, fit.mean * scale, fit.var * scale**2) psfmodel = psf.getPointSourcePatch(0., 0., radius=h/2) mod = psfmodel.patch print 'Scaled mod sum', mod.sum() mod = mod[slc] print 'Sliced mod sum', mod.sum() _plot_psf(pix, mod, psf) plt.suptitle('W%i: Scaled' % band) ps.savefig() plotslice = slice(S-plotss,-(S-plotss)),slice(S-plotss,-(S-plotss)) psfx = GaussianMixturePSF.fromStamp(pix, P0=(fit.amp, fit.mean*scale, fit.var*scale**2)) psfmodel = psfx.getPointSourcePatch(0., 0., radius=h/2) mod = psfmodel.patch print 'From stamp: mod sum', mod.sum() mod = mod[slc] print 'Sliced mod sum:', mod.sum() _plot_psf(pix, mod, psfx) plt.suptitle('W%i: fromStamp: %g = %s, res %.3f' % (band, np.sum(psfx.mog.amp), ','.join(['%.3f'%a for a in psfx.mog.amp]), np.sum(pix - mod))) ps.savefig() print 'Stamp-Fit PSF params:', psfx # class MyGaussianMixturePSF(GaussianMixturePSF): # def getLogPrior(self): # if np.any(self.mog.amp < 0.): # return -np.inf # for k in range(self.mog.K): # if np.linalg.det(self.mog.var[k]) <= 0: # return -np.inf # return 0 # # @property # def amp(self): # return self.mog.amp # # mypsf = MyGaussianMixturePSF(psfx.mog.amp, psfx.mog.mean, psfx.mog.var) # mypsf.radius = sh/2 sh,sw = pix.shape # Initialize from original fit params psfx = psf # Try concentric gaussian PSF sigmas = [] for k in range(psfx.mog.K): v = psfx.mog.var[k,:,:] sigmas.append(np.sqrt(np.sqrt(np.abs(v[0,0] * v[1,1])))) print 'Initializing concentric Gaussian PSF with sigmas', sigmas gpsf = NCircularGaussianPSF(sigmas, psfx.mog.amp) gpsf.radius = sh/2 mypsf = gpsf tim = Image(data=pix, invvar=1e6 * np.ones_like(pix), psf=mypsf) tim.modelMinval = 1e-16 # xx,yy = np.meshgrid(np.arange(sw), np.arange(sh)) # cx,cy = np.sum(xx*pix)/np.sum(pix), np.sum(yy*pix)/np.sum(pix) # print 'Centroid:', cx,cy # print 'Pix midpoint:', sw/2, sh/2 cx,cy = sw/2, sh/2 src = PointSource(PixPos(cx, cy), Flux(1.0)) tractor = Tractor([tim], [src]) tim.freezeAllBut('psf') #tractor.freezeParam('catalog') src.freezeAllBut('pos') # src.freezeAllBut('brightness') # tractor.freezeParam('images') # tractor.optimize_forced_photometry() # tractor.thawParam('images') # print 'Source flux after forced-photom fit:', src.getBrightness() print 'Optimizing Params:' tractor.printThawedParams() for i in range(200): #dlnp,X,alpha = tractor.optimize(damp=0.1) dlnp,X,alpha = tractor.optimize(damp=1) print i,'dlnp %.3g' % dlnp, 'psf', gpsf if dlnp < 1e-6: break tractor.freezeParam('catalog') gpsf.sigmas.stepsize = len(gpsf.sigmas) * [1e-6] gpsf.weights.stepsize = len(gpsf.sigmas) * [1e-6] for i in range(200): #dlnp,X,alpha = tractor.optimize(damp=0.1) dlnp,X,alpha = tractor.optimize(damp=1) print i,'dlnp %.3g' % dlnp, 'psf', gpsf if dlnp < 1e-6: break print 'PSF3(opt): flux', src.brightness print 'PSF amps:', np.sum(mypsf.amp) print 'PSF amps * Source brightness:', src.brightness.getValue() * np.sum(mypsf.amp) print 'pix sum:', pix.sum() print 'Optimize source:', src print 'Optimized PSF:', mypsf mod = tractor.getModelImage(0) print 'Mod sum:', mod.sum() _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join(['%.3f'%a for a in mypsf.amp]), np.sum(pix-mod))) ps.savefig() # Write before normalizing! T = fits_table() T.amp = mypsf.mog.amp T.mean = mypsf.mog.mean T.var = mypsf.mog.var T.writeto('psf3-w%i.fits' % band) T.writeto('psf3.fits', append=(band != 1)) mypsf.weights.setParams(np.array(mypsf.weights.getParams()) / sum(mypsf.weights.getParams())) print 'Normalized PSF weights:', mypsf mod = tractor.getModelImage(0) print 'Mod sum:', mod.sum() _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join(['%.3f'%a for a in mypsf.amp]), np.sum(pix-mod))) ps.savefig() class MyGaussianPSF(NCircularGaussianPSF): ''' A PSF model with strictly positive weights that sum to unity. ''' def __init__(self, sigmas, weights): ww = np.array(weights) ww = np.log(ww) super(MyGaussianPSF, self).__init__(sigmas, ww) @staticmethod def getNamedParams(): return dict(sigmas=0, logweights=1) def __str__(self): return ('MyGaussianPSF: sigmas [ ' + ', '.join(['%.3f'%s for s in self.mysigmas]) + ' ], weights [ ' + ', '.join(['%.3f'%w for w in self.myweights]) + ' ]') @property def myweights(self): ww = np.exp(self.logweights.getAllParams()) ww /= ww.sum() return ww @property def weights(self): ww = np.exp(self.logweights.getParams()) wsum = np.sum(np.exp(self.logweights.getAllParams())) return ww / wsum if band == 4: # HACK mypsf = MyGaussianPSF([1.7, 6.4, 15.0], [0.333, 0.666, 0.1]) else: mypsf = MyGaussianPSF(gpsf.sigmas, gpsf.amp) mypsf.radius = sh/2 tim.psf = mypsf print 'Optimizing Params:' tractor.printThawedParams() for i in range(200): #dlnp,X,alpha = tractor.optimize(damp=0.1) dlnp,X,alpha = tractor.optimize(damp=1) print i,'dlnp %.3g' % dlnp, 'psf', mypsf if dlnp < 1e-6: break mypsf.sigmas.stepsize = len(mypsf.sigmas) * [1e-6] mypsf.logweights.stepsize = len(mypsf.sigmas) * [1e-6] for i in range(200): #dlnp,X,alpha = tractor.optimize(damp=0.1) dlnp,X,alpha = tractor.optimize(damp=1) print i,'dlnp %.3g' % dlnp, 'psf', mypsf if dlnp < 1e-6: break print 'PSF amps:', np.sum(mypsf.amp) print 'pix sum:', pix.sum() print 'Optimize source:', src print 'Optimized PSF:', mypsf mod = tractor.getModelImage(0) print 'Mod sum:', mod.sum() _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt2): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join(['%.3f'%a for a in mypsf.amp]), np.sum(pix-mod))) ps.savefig() # Write mog = mypsf.getMixtureOfGaussians() T = fits_table() T.amp = mog.amp T.mean = mog.mean T.var = mog.var T.writeto('psf4.fits', append=(band != 1))
def _allwise_psf_models(): global plotslice # AllWISE PSF models for band in [1,2,3,4]: print print 'W%i' % band print pix = reduce(np.add, [fitsio.read('wise-w%i-psf-wpro-09x09-%02ix%02i.fits' % (band, 1+(i/9), 1+(i%9))) for i in range(9*9)]) print 'Pix', pix.shape h,w = pix.shape print 'Pix sum', pix.sum() print 'Pix max', pix.max() pix /= pix.sum() psf = GaussianMixturePSF.fromStamp(pix) print 'Fit PSF', psf psfmodel = psf.getPointSourcePatch(0., 0., radius=h/2) mod = psfmodel.patch print 'Orig mod sum', mod.sum() S = h/2 plotss = 30 plotslice = slice(S-plotss, -(S-plotss)), slice(S-plotss, -(S-plotss)) _plot_psf(pix, mod, psf) plt.suptitle('W%i: from stamp' % band) ps.savefig() # Try concentric gaussian PSF sh,sw = pix.shape sigmas = [] for k in range(psf.mog.K): v = psf.mog.var[k,:,:] sigmas.append(np.sqrt(np.sqrt(v[0,0] * v[1,1]))) print 'Initializing concentric Gaussian model with sigmas', sigmas print 'And weights', psf.mog.amp # (Initial) W1: # sig [7.1729391870564569, 24.098952864976805, 108.78869923786333] # weights [ 0.80355109 0.15602835 0.04195982] # sigmas [ 6.928, 17.091, 45.745 ], weights [ 0.760, 0.154, 0.073 ] # W2: # sig [8.2356371659198189, 25.741694812001221, 110.17431488810806] # weights [ 0.80636191 0.1563742 0.03926182] # sigmas [ 7.177, 10.636, 30.247 ], weights [ 0.500, 0.341, 0.134 ] # W3: # sig [6.860124763919889, 19.160849966251824, 134.20812055907825] # weights [ 0.28227047 0.55080156 0.16706357] # sigmas [ 6.850, 18.922, 109.121 ], weights [ 0.276, 0.554, 0.148 ] # W4: # [4.6423676603462001, 5.31542132669962, 18.375512539373585] # weights [ 0.10764341 0.26915295 0.62320374] # (Opt) # sigmas [ 6.293, 6.314, 20.932 ], weights [ 0.129, 0.309, 0.598 ] weights = psf.mog.amp # HACK if band == 4: sigmas = [ 2., 6., 25. ] weights = [ 0.5, 0.25, 0.25 ] else: sigmas = [ 8., 24., 100. ] weights = [ 0.5, 0.25, 0.25 ] gpsf = NCircularGaussianPSF(sigmas, weights) gpsf.radius = sh/2 mypsf = gpsf tim = Image(data=pix, invvar=1e6 * np.ones_like(pix), psf=mypsf) cx,cy = sw/2, sh/2 src = PointSource(PixPos(cx, cy), Flux(1.0)) tractor = Tractor([tim], [src]) tim.freezeAllBut('psf') #tractor.freezeParam('catalog') src.freezeAllBut('pos') print 'Optimizing Params:' tractor.printThawedParams() for i in range(100): dlnp,X,alpha = tractor.optimize(damp=0.1) print 'dlnp', dlnp print 'PSF', mypsf if dlnp < 0.001: break print 'PSF3(opt): flux', src.brightness print 'PSF amps:', np.sum(mypsf.amp) print 'PSF amps * Source brightness:', src.brightness.getValue() * np.sum(mypsf.amp) print 'pix sum:', pix.sum() print 'Optimize source:', src print 'Optimized PSF:', mypsf mod = tractor.getModelImage(0) print 'Mod sum:', mod.sum() print 'Mod min:', mod.min() print 'Mod max:', mod.max() _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join(['%.3f'%a for a in mypsf.amp]), np.sum(pix-mod))) ps.savefig() # These postage stamps are subsampled at 8x the 2.75"/pix, # except for the W4 one, which is at 4x that. scale = 8 if band == 4: scale = 4 T = fits_table() T.amp = mypsf.mog.amp T.mean = mypsf.mog.mean / scale T.var = mypsf.mog.var / scale**2 T.writeto('psf-allwise-con3-w%i.fits' % band) T.writeto('psf-allwise-con3.fits', append=(band != 1)) mypsf.weights.setParams(np.array(mypsf.weights.getParams()) / sum(mypsf.weights.getParams())) print 'Normalized PSF weights:', mypsf mod = tractor.getModelImage(0) print 'Mod sum:', mod.sum() _plot_psf(pix, mod, mypsf, flux=src.brightness.getValue()) plt.suptitle('W%i psf3 (opt): %g = %s, resid %.3f' % (band, np.sum(mypsf.amp), ','.join(['%.3f'%a for a in mypsf.amp]), np.sum(pix-mod))) ps.savefig()
mypsf.mog.mean[:2,:], mypsf.mog.var[:2,:,:]) psf2.radius = sh/2 tim.psf = psf2 mod = tractor.getModelImage(0) _plot_psf(lpix, mod, psf2, flux=src.brightness.getValue()) plt.suptitle('psf2 (init)') ps.savefig() src.freezeAllBut('brightness') tractor.freezeParam('catalog') for i in range(100): print 'Optimizing PSF:' tractor.printThawedParams() dlnp,X,alpha = tractor.optimize(damp=1.) tractor.freezeParam('images') tractor.thawParam('catalog') print 'Optimizing flux:' tractor.printThawedParams() tractor.optimize_forced_photometry() tractor.thawParam('images') tractor.freezeParam('catalog') mod = tractor.getModelImage(0) _plot_psf(lpix, mod, psf2, flux=src.brightness.getValue()) plt.suptitle('psf2 (opt)') ps.savefig()