예제 #1
0
파일: nfit.py 프로젝트: esheldon/espy
    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)
예제 #2
0
    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)
예제 #3
0
    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)