def _getModelPatches(self, img, minsb=0., modelMask=None): d = DevGalaxy(self.pos, self.brightnessDev, self.shapeDev) p = PointSource(self.pos, self.brightnessPsf) if minsb == 0. or minsb is None: kw = {} else: kw = dict(minsb=minsb / 2.) if hasattr(self, 'halfsize'): d.halfsize = self.halfsize pd = d.getModelPatch(img, modelMask=modelMask, **kw) pp = p.getModelPatch(img, modelMask=modelMask, **kw) return (pd, pp)
def getUnitFluxModelPatches(self, img, minval=0., modelMask=None): # Needed for forced photometry if minval > 0: # allow each component half the error minval = minval * 0.5 d = DevGalaxy(self.pos, self.brightnessDev, self.shapeDev) p = PointSource(self.pos, self.brightnessPsf) if hasattr(self, 'halfsize'): d.halfsize = self.halfsize return (d.getUnitFluxModelPatches(img, minval=minval, modelMask=modelMask) + p.getUnitFluxModelPatches(img, minval=minval, modelMask=modelMask))
def _getModelPatches(self, img, minsb=0., modelMask=None): s = SersicGalaxy(self.pos, self.brightness, self.shape, self.sersicindex) p = PointSource(self.pos, self.brightnessPsf) if minsb == 0. or minsb is None: kw = {} else: kw = dict(minsb=minsb / 2.) if hasattr(self, 'halfsize'): s.halfsize = self.halfsize ps = s.getModelPatch(img, modelMask=modelMask, **kw) pp = p.getModelPatch(img, modelMask=modelMask, **kw) return (ps, pp)
def getParamDerivatives(self, img, modelMask=None): d = DevGalaxy(self.pos, self.brightnessDev, self.shapeDev) p = PointSource(self.pos, self.brightnessPsf) if hasattr(self, 'halfsize'): d.halfsize = self.halfsize d.dname = 'devcore.dev' p.dname = 'devcore.psf' if self.isParamFrozen('pos'): d.freezeParam('pos') p.freezeParam('pos') if self.isParamFrozen('brightnessDev'): d.freezeParam('brightness') if self.isParamFrozen('shapeDev'): d.freezeParam('shape') if self.isParamFrozen('brightnessPsf'): p.freezeParam('brightness') dd = d.getParamDerivatives(img, modelMask=modelMask) dp = p.getParamDerivatives(img, modelMask=modelMask) if self.isParamFrozen('pos'): derivs = dd + dp else: derivs = [] # "pos" is shared between the models, so add the derivs. npos = len(self.pos.getStepSizes()) for i in range(npos): dpos = add_patches(dd[i], dp[i]) if dpos is not None: dpos.setName('d(devcore)/d(pos%i)' % i) derivs.append(dpos) derivs.extend(dd[npos:]) derivs.extend(dp[npos:]) return derivs
def pointsource_fit(xsub, ysub, fluxsub, TractorImage): ''' Returns the optimized Tractor object and variances of each source fit ''' # Generate Tractor source object TractorSources = [ PointSource(PixPos(x, y), Flux(flux)) for x, y, flux in zip(xsub, ysub, fluxsub) ] # Freeze position for src in TractorSources: src.pos.freezeParam('x') src.pos.freezeParam('y') # Construct Final Tractor Object for Fitting tractor = Tractor(TractorImage, TractorSources) # Freeze image parameters tractor.freezeParam('images') # Initial Source Model and Initial Residual left behind in map units # mod0 = tractor.getModelImage(0) # res0 = tractor.getChiImage(0) * sky_noise # Fit the model for k in xrange(100): dlnp, X, alpha, var = tractor.optimize(variance=True) # print 'dlnp',dlnp # print 'var', var if dlnp < 1e-3: break return tractor, var
def fromStamp(stamp, N=3, P0=None, approx=1e-6, damp=0.): ''' optional P0 = (list of floats): initial parameter guess. (parameters of a GaussianMixtureEllipsePSF) ''' from tractor.ellipses import EllipseESoft w = np.ones(N) / float(N) mu = np.zeros((N, 2)) ell = [EllipseESoft(np.log(2 * r), 0., 0.) for r in range(1, N + 1)] psf = GaussianMixtureEllipsePSF(w, mu, ell) if P0 is not None: psf.setAllParams(P0) tim = Image(data=stamp, invvar=1e6 * np.ones_like(stamp), psf=psf) H, W = stamp.shape src = PointSource(PixPos(W // 2, H // 2), Flux(1.)) tr = Tractor([tim], [src]) tr.freezeParam('catalog') tim.freezeAllBut('psf') # print 'Fitting:' # tr.printThawedParams() tim.modelMinval = approx alphas = [0.1, 0.3, 1.0] for step in range(50): dlnp, X, alpha = tr.optimize(shared_params=False, alphas=alphas, damp=damp) # print 'dlnp', dlnp, 'alpha', alpha # print 'X', X if dlnp < 1e-6: break # print 'psf', psf return psf
def gim2d_catalog(cat, band): ''' http://irsa.ipac.caltech.edu/data/COSMOS/tables/morphology/cosmos_morph_zurich_colDescriptions.html ''' ''' ACS_MU_CLASS float Type of object. 1 = galaxy 2 = star 3 = spurious ''' ''' ACS_CLEAN float Object useable flag. 0 = do not use this object 1 = use this object ''' ''' FLUX_GIM2D float counts GIM2D total flux R_GIM2D float arcseconds GIM2D psf-convolved half-light radius of object ELL_GIM2D float GIM2D ellipticity = 1-b/a of object PA_GIM2D float degrees GIM2D position angle of object - cw from +y-axis DX_GIM2D float arcseconds x-offset of GIM2D-model center from ACS-coordinate center DY_GIM2D float arcseconds y-offset of GIM2D-model center from ACS-coordinate center SERSIC_N_GIM2D float GIM2D Sersic index R_0P5_GIM2D float arcseconds GIM2D half-light radius of object without PSF convolution TYPE float ZEST Type CLASS 1 = Early type 2 = Disk 3 = Irregular Galaxy 9 = no classification ''' ''' BULG float ZEST "Bulgeness" CLASS - only for Type 2 (disk) galaxies. 0 = bulge dominated galaxy 1,2 = intermediate-bulge galaxies 3 = pure disk galaxy 9 = no classification ''' ''' STELLARITY float Visual Stellarity flag. 0 if ACS_CLASS_STAR<0.6 (object is ASSUMED to be a galaxy; no visual inspection) 0 if ACS_CLASS_STAR>=0.6 AND object visually identified as a galaxy. 1 if ACS_CLASS_STAR>=0.6 AND visually identified as a star. 2 if ACS_CLASS_STAR>=0.8 (object is assumed to be a star and was not visually inspected) 3 if ACS_CLASS_STAR<0.6 but object is visually identified as a star (e.g. saturated star, etc) JUNKFLAG float 0 = good object 1 = spurious ''' print('Classifications:', Counter(cat.type).most_common()) cat.is_galaxy = (cat.stellarity == 0) srcs = [] for t in cat: pos = RaDecPos(t.ra, t.dec) bright = NanoMaggies( **{band: NanoMaggies.magToNanomaggies(t.acs_mag_auto)}) shape = GalaxyShape(t.r_0p5_gim2d, 1. - t.ell_gim2d, 90. + t.pa_gim2d) is_galaxy = (t.is_galaxy * (shape.re >= 0) * (shape.ab <= 1.) * (shape.phi > -999)) if is_galaxy and t.type == 1: # deV src = DevGalaxy(pos, bright, shape) elif is_galaxy and t.type == 2: # exp src = ExpGalaxy(pos, bright, shape) else: src = PointSource(pos, bright) srcs.append(src) return srcs
def fromStamp(stamp, N=3, P0=None, xy0=None, alpha=0., emsteps=1000, v2=False, approx=1e-30, v3=False): ''' optional P0 = (w,mu,var): initial parameter guess. w has shape (N,) mu has shape (N,2) var (variance) has shape (N,2,2) optional xy0 = int x0,y0 origin of stamp. ''' from tractor.emfit import em_fit_2d_reg from tractor.fitpsf import em_init_params if P0 is not None: w, mu, var = P0 else: w, mu, var = em_init_params(N, None, None, None) stamp = stamp.copy() if xy0 is None: xm, ym = -(stamp.shape[1] // 2), -(stamp.shape[0] // 2) else: xm, ym = xy0 if v3: tpsf = GaussianMixturePSF(w, mu, var) tim = Image(data=stamp, invvar=1e6 * np.ones_like(stamp), psf=tpsf) h, w = tim.shape src = PointSource(PixPos(w // 2, h // 2), Flux(1.)) tr = Tractor([tim], [src]) tr.freezeParam('catalog') tim.freezeAllBut('psf') tim.modelMinval = approx for step in range(20): dlnp, X, alpha = tr.optimize(shared_params=False) print('dlnp', dlnp) if dlnp < 1e-6: break return tpsf elif v2: from tractor.emfit import em_fit_2d_reg2 print('stamp sum:', np.sum(stamp)) #stamp *= 1000. ok, skyamp = em_fit_2d_reg2(stamp, xm, ym, w, mu, var, alpha, emsteps, approx) # print 'sky amp:', skyamp # print 'w sum:', sum(w) tpsf = GaussianMixturePSF(w, mu, var) return tpsf, skyamp else: stamp /= stamp.sum() stamp = np.maximum(stamp, 0) em_fit_2d_reg(stamp, xm, ym, w, mu, var, alpha, emsteps) tpsf = GaussianMixturePSF(w, mu, var) return tpsf
# create tractor.Image object for rendering synthetic galaxy # images tim = Image(data=np.zeros((H, W)), invvar=np.ones((H, W)) / (noisesigma**2), psf=NCircularGaussianPSF([psfsigma], [1.])) types = {'PSF ': 1, 'SIMP': 2, 'EXP ': 3, 'DEV ': 4, 'COMP': 5} g, r = 1, 2 sources = [] for i in range(len(cat['ra'])): x, y = grid.nearest_cell_index(cat['ra'][i], cat['dec'][i]) gflux = cat['decam_flux'][i][g] if gflux <= 0: continue if types[cat['type'][i]] == 1: sources.append(PointSource(PixPos(x, y), Flux(gflux))) elif types[cat['type'][i]] == 2: sources.append( ExpGalaxy(PixPos(x, y), Flux(gflux), EllipseE(0.45, 0., 0.))) elif types[cat['type'][i]] == 3: radius, e1, e2 = cat['shapeexp_r'][i], cat['shapeexp_e1'][i], cat[ 'shapeexp_e2'][i] sources.append( ExpGalaxy(PixPos(x, y), Flux(gflux), EllipseE(radius, e1, e2))) elif types[cat['type'][i]] == 4: radius, e1, e2 = cat['shapedev_r'][i], cat['shapedev_e1'][i], cat[ 'shapedev_e2'][i] sources.append( DevGalaxy(PixPos(x, y), Flux(gflux), EllipseE(radius, e1, e2))) elif types[cat['type'][i]] == 5: fdev = cat['fracdev'][i]