def _fit_psf(self): """ Fit a psf to a single gauss and more complex model """ from ngmix import GMixMaxIterEM if 'psf_gmix' in self.res: del self.res['psf_gmix'] del self.res['psf_obs'] self.fitting_galaxy=False jacobian=self._get_jacobian(cen=self.psf_cen_guess_pix) psf_obs = Observation(self.psf_image, jacobian=jacobian) if 'em' in self['psf_model']: fitter=self._fit_em_ngauss(psf_obs, self['psf_sigma_guess'], self['psf_ngauss']) else: fitter=self._fit_psf_max(psf_obs) if fitter is None: self.res['flags'] = PSF_FIT_FAILURE print("psf utter failure") else: pres=fitter.get_result() if pres['flags'] != 0: self.res['flags'] = PSF_FIT_FAILURE print("psf convergence failure") else: psf_gmix = fitter.get_gmix() #print("psf fit:") #print(psf_gmix) print(" psf fwhm:",2.35*sqrt( psf_gmix.get_T()/2. )) self.res['psf_gmix']=psf_gmix psf_obs.set_gmix(psf_gmix) self.res['psf_obs'] = psf_obs if self['make_plots']: self._compare_psf(fitter)
def _fit_psf(self): """ Fit a psf to a single gauss and more complex model """ from ngmix import GMixMaxIterEM if 'psf_gmix' in self.res: del self.res['psf_gmix'] del self.res['psf_obs'] self.fitting_galaxy = False jacobian = self._get_jacobian(cen=self.psf_cen_guess_pix) psf_obs = Observation(self.psf_image, jacobian=jacobian) if 'em' in self['psf_model']: fitter = self._fit_em_ngauss(psf_obs, self['psf_sigma_guess'], self['psf_ngauss']) else: fitter = self._fit_psf_max(psf_obs) if fitter is None: self.res['flags'] = PSF_FIT_FAILURE print("psf utter failure") else: pres = fitter.get_result() if pres['flags'] != 0: self.res['flags'] = PSF_FIT_FAILURE print("psf convergence failure") else: psf_gmix = fitter.get_gmix() #print("psf fit:") #print(psf_gmix) print(" psf fwhm:", 2.35 * sqrt(psf_gmix.get_T() / 2.)) self.res['psf_gmix'] = psf_gmix psf_obs.set_gmix(psf_gmix) self.res['psf_obs'] = psf_obs if self['make_plots']: self._compare_psf(fitter)
def measure(self, measRecord, exposure): psf = exposure.getPsf() if psf is None: raise MeasurementError( self.flagHandler.getDefinition( SingleFrameLMSimpleShapePlugin.ErrEnum.flag_noPsf).doc, SingleFrameLMSimpleShapePlugin.ErrEnum.flag_noPsf) # make an observation for the psf image psfArray = psf.computeKernelImage().getArray() psfJacob = ngmix.UnitJacobian(row=psfArray.shape[0] / 2.0, col=psfArray.shape[1] / 2.0) psfObs = Observation(psfArray, jacobian=psfJacob) # Fallback code if no psf algorithm is requested. Then just do an LM single gaussian fit if self.config.psfName is None: pfitter = LMSimple(psfObs, 'gauss') # gues parameters for a simple Gaussian psfPars = [0.0, 0.0, -0.03, 0.02, 8.0, 1.0] pfitter.go(psfPars) psfGMix = pfitter.get_gmix() else: shape = psfArray.shape image = lsst.afw.image.ImageD(shape[1], shape[0]) evaluate = measRecord.get(self.psfMsfKey).evaluate() evaluate.addToImage( image.getArray(), lsst.afw.geom.Point2I(-(shape[0] - 1) // 2, -(shape[1] - 1) // 2)) psfObs = Observation(image.getArray(), jacobian=psfJacob) # Now create a gmix directly from what the PsfApprox algorithm produced multiShapeletFunction = measRecord.get(self.psfMsfKey) shapeletFunctions = multiShapeletFunction.getComponents() psfPars = [] # add pars in the order flux, y, x, yy, xy, xx for sf in shapeletFunctions: psfPars.append(sf.getCoefficients()[0]) psfPars.append(sf.getEllipse().getCenter().getY()) psfPars.append(sf.getEllipse().getCenter().getX()) psfPars.append(sf.getEllipse().getCore().getIyy()) psfPars.append(sf.getEllipse().getCore().getIxy()) psfPars.append(sf.getEllipse().getCore().getIxx()) psfGMix = ngmix.gmix.GMix(len(shapeletFunctions), psfPars) psfObs.set_gmix(psfGMix) # Now create an obs for the galaxy itself, including the weight plane galArray = exposure.getMaskedImage().getImage().getArray() galShape = galArray.shape galJacob = ngmix.UnitJacobian(row=galShape[1] / 2.0, col=galShape[0] / 2.0) variance = exposure.getMaskedImage().getVariance().getArray() gal_weight = 1 / variance obs = Observation(galArray, weight=gal_weight, jacobian=galJacob, psf=psfObs) fp = measRecord.getFootprint() bbox = fp.getBBox() ymin = bbox.getBeginY() - exposure.getXY0().getY() ymax = bbox.getEndY() - exposure.getXY0().getY() xmin = bbox.getBeginX() - exposure.getXY0().getX() xmax = bbox.getEndX() - exposure.getXY0().getX() flux = exposure.getMaskedImage().getImage().getArray()[ ymin:ymax, xmin:xmax].sum() xx = fp.getShape().getIxx() yy = fp.getShape().getIyy() xy = fp.getShape().getIxy() # Now run the shape algorithm, using the config parameters lmPars = { 'maxfev': self.config.maxfev, 'ftol': self.config.ftol, 'xtol': self.config.xtol } maxPars = {'method': 'lm', 'lm_pars': lmPars} guesser = ngmix.guessers.TFluxGuesser(xx + yy, flux) runner = ngmix.bootstrap.MaxRunner(obs, self.config.model, maxPars, guesser) runner.go(ntry=4) fitter = runner.fitter res = fitter.get_result() # Set the results, including the fit info returned by MaxRunner if res['flags'] != 0: if res['flags'] & LM_SINGULAR_MATRIX: raise MeasurementError( self.flagHandler.getDefinition( SingleFrameLMSimpleShapePlugin.ErrEnum. flag_singularMatrix).doc, SingleFrameLMSimpleShapePlugin.ErrEnum.flag_singularMatrix) if res['flags'] & LM_NEG_COV_EIG: raise MeasurementError( self.flagHandler.getDefinition( SingleFrameLMSimpleShapePlugin.ErrEnum. flag_negativeCovEig).doc, SingleFrameLMSimpleShapePlugin.ErrEnum.flag_negativeCovEig) if res['flags'] & LM_NEG_COV_DIAG: raise MeasurementError( self.flagHandler.getDefinition( SingleFrameLMSimpleShapePlugin.ErrEnum. flag_negativeCovDiag).doc, SingleFrameLMSimpleShapePlugin.ErrEnum.flag_negativeCovDiag ) if res['flags'] & EIG_NOTFINITE: raise MeasurementError( self.flagHandler.getDefinition( SingleFrameLMSimpleShapePlugin.ErrEnum. flag_eigNotFinite).doc, SingleFrameLMSimpleShapePlugin.ErrEnum.flag_eigNotFinite) if res['flags'] & LM_FUNC_NOTFINITE: raise MeasurementError( self.flagHandler.getDefinition( SingleFrameLMSimpleShapePlugin.ErrEnum. flag_funcNotFinite).doc, SingleFrameLMSimpleShapePlugin.ErrEnum.flag_funcNotFinite) if res['flags'] & DIV_ZERO: raise MeasurementError( self.flagHandler.getDefinition( SingleFrameLMSimpleShapePlugin.ErrEnum.flag_divZero). doc, SingleFrameLMSimpleShapePlugin.ErrEnum.flag_divZero) if res['nfev'] >= self.config.maxfev: raise MeasurementError( self.flagHandler.getDefinition( SingleFrameLMSimpleShapePlugin.ErrEnum.flag_maxFev). doc, SingleFrameLMSimpleShapePlugin.ErrEnum.flag_maxFev) # Unknown error, but there should be an errmsg set by ngmix raise RuntimeError(res['errmsg']) # Convert the nGauss Gaussians to ShapeletFunction's. Zeroth order HERMITES are Gaussians. # There are always 6 parameters for each Gaussian. galGMix = fitter.get_gmix() galPars = galGMix.get_full_pars() # convert the center in row,col coordinates to pixel coordinates and save cen = galGMix.get_cen() measRecord.set(self.xKey, cen[1] + galShape[1] / 2.0) measRecord.set(self.yKey, cen[0] + galShape[0] / 2.0) # save the model flux measRecord.set(self.fluxKey, galGMix.get_flux()) # save the model T=xx+yy, e1, and e2 (e1, e2, T) = galGMix.get_e1e2T() measRecord.set(self.e1Key, e1) measRecord.set(self.e2Key, e2) measRecord.set(self.TKey, T) for i in range(self.nGauss): flux, y, x, iyy, ixy, ixx = galPars[i * self._gaussian_pars_len:(i + 1) * self._gaussian_pars_len] quad = lsst.afw.geom.ellipses.Quadrupole(ixx, iyy, ixy) ellipse = lsst.afw.geom.ellipses.Ellipse( quad, lsst.afw.geom.Point2D(x, y)) # create a 0th order (gaussian) shapelet function. sf = ShapeletFunction(0, HERMITE, ellipse) sf.getCoefficients()[0] = flux / ShapeletFunction.FLUX_FACTOR measRecord.set(self.keys[i], sf)