Coverage for python/lsst/meas/extensions/psfex/psfexPsfDeterminer.py : 67%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# # LSST Data Management System # Copyright 2008-2015 AURA/LSST. # # This product includes software developed by the # LSST Project (http://www.lsst.org/). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the LSST License Statement and # the GNU General Public License along with this program. If not, # see <https://www.lsstcorp.org/LegalNotices/>. #
doc="number of eigen components for PSF kernel creation", dtype=int, default=4, ) doc="specify spatial order for PSF kernel creation", dtype=int, default=2, check=lambda x: x >= 0, ) doc="size of cell used to determine PSF (pixels, column direction)", dtype=int, default=256, # minValue = 10, check=lambda x: x >= 10, ) doc="size of cell used to determine PSF (pixels, row direction)", dtype=int, default=sizeCellX.default, # minValue = 10, check=lambda x: x >= 10, ) doc="number of stars per psf cell for PSF kernel creation", dtype=int, default=3, ) doc="Resolution of the internal PSF model relative to the pixel size; " "e.g. 0.5 is equal to 2x oversampling", dtype=float, default=1, ) doc="List of mask bits which cause a source to be rejected as bad " "N.b. INTRP is used specially in PsfCandidateSet; it means \"Contaminated by neighbour\"", dtype=str, default=["INTRP", "SAT"], ) doc="BASIS value given to psfex. PIXEL_AUTO will use the requested samplingSize only if " "the FWHM < 3 pixels. Otherwise, it will use samplingSize=1. PIXEL will always use the " "requested samplingSize", dtype=str, allowed={ "PIXEL": "Always use requested samplingSize", "PIXEL_AUTO": "Only use requested samplingSize when FWHM < 3", }, default='PIXEL', optional=False, ) doc="Number of pixels to ignore around the edge of PSF candidate postage stamps", dtype=int, default=0, ) doc="number of stars per psf Cell for spatial fitting", dtype=int, default=5, ) doc="Should each PSF candidate be given the same weight, independent of magnitude?", dtype=bool, default=True, ) doc="number of iterations of PSF candidate star list", dtype=int, default=3, ) doc="tolerance of spatial fitting", dtype=float, default=1e-2, ) doc="floor for variance is lam*data", dtype=float, default=0.05, ) doc="for psf candidate evaluation", dtype=float, default=2.0, ) doc="Rejection threshold (stdev) for candidates based on spatial fit", dtype=float, default=3.0, ) doc="Should PSFEX be permitted to recentroid PSF candidates?", dtype=bool, default=False, )
"""Determine a PSFEX PSF model for an exposure given a list of PSF candidates
@param[in] exposure: exposure containing the psf candidates (lsst.afw.image.Exposure) @param[in] psfCandidateList: a sequence of PSF candidates (each an lsst.meas.algorithms.PsfCandidate); typically obtained by detecting sources and then running them through a star selector @param[in,out] metadata a home for interesting tidbits of information @param[in] flagKey: schema key used to mark sources actually used in PSF determination
@return psf: a meas.extensions.psfex.PsfexPsf """ lsstDebug.Info(__name__).displayExposure # display the Exposure + spatialCells lsstDebug.Info(__name__).displayPsfComponents # show the basis functions lsstDebug.Info(__name__).showBadCandidates # Include bad candidates (meaningless, methinks) lsstDebug.Info(__name__).displayResiduals # show residuals lsstDebug.Info(__name__).displayPsfMosaic # show mosaic of reconstructed PSF(x,y) # Normalise residuals by object amplitude
raise RuntimeError("No PSF candidates supplied.") # # How big should our PSF models be? # # construct and populate a spatial cell set bbox = mi.getBBox(afwImage.PARENT) psfCellSet = afwMath.SpatialCellSet(bbox, self.config.sizeCellX, self.config.sizeCellY) else:
psfCellSet.insertCandidate(psfCandidate) except Exception as e: self.log.debug("Skipping PSF candidate %d of %d: %s", i, len(psfCandidateList), e) continue
else: actualKernelSize = 2 * int(self.config.kernelSize * np.sqrt(np.median(sizes)) + 0.5) + 1 if actualKernelSize < self.config.kernelSizeMin: actualKernelSize = self.config.kernelSizeMin if actualKernelSize > self.config.kernelSizeMax: actualKernelSize = self.config.kernelSizeMax if display: rms = np.median(sizes) print("Median PSF RMS size=%.2f pixels (\"FWHM\"=%.2f)" % (rms, 2*np.sqrt(2*np.log(2))*rms))
# If we manually set the resolution then we need the size in pixel units pixKernelSize += 1
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- BEGIN PSFEX # # Insert the good candidates into the set #
if False else psfex.Context.KEEPHIDDEN) prefs.getGroupDeg(), principalComponentExclusionFlag)
gain = np.mean(np.array([a.getGain() for a in ccd])) else:
contextvalp.append(pcval[pc]) pc += 1 try: contextvalp.append(exposure.getMetadata().get(key[1:])) except KeyError: raise RuntimeError("*Error*: %s parameter not found in the header of %s" % (key[1:], prefs.getContextName())) else: for _ in range(nCand)])) except KeyError: raise RuntimeError("*Error*: %s parameter not found" % (key,))
frame = 0 if displayExposure: ds9.mtv(exposure, frame=frame, title="psf determination")
except ValueError: continue
except Exception as e: continue
continue
continue
# From this point, we're configuring the "sample" (PSFEx's version of a PSF candidate). # Having created the sample, we must proceed to configure it, and then fini (finalize), # or it will be malformed.
-2*psfex.BIG
except Exception as e: self.log.debug("Exception when processing sample at (%f,%f): %s", xc, yc, e) continue else:
with ds9.Buffering(): ds9.dot("o", xc, yc, ctype=ds9.CYAN, size=4, frame=frame)
raise RuntimeError("No good PSF candidates to pass to PSFEx")
#---- Update min and max and then the scaling
# Don't waste memory!
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- END PSFEX # # Do a PSFEX decomposition of those PSF candidates #
# Flag which objects were actually used in psfex by
for i, psfCandidate in enumerate(psfCandidateList): source = psfCandidate.getSource() if i in good_indices: source.set(flagKey, True)
ext = 0 frame = 1 diagnostics = True catDir = "." title = "psfexPsfDeterminer" psfex.psfex.showPsf(psfs, set, ext, [(exposure.getWcs(), exposure.getWidth(), exposure.getHeight())], nspot=3, trim=5, frame=frame, diagnostics=diagnostics, outDir=catDir, title=title) # # Display code for debugging # assert psfCellSet is not None
if displayExposure: maUtils.showPsfSpatialCells(exposure, psfCellSet, showChi2=True, symb="o", ctype=ds9.YELLOW, ctypeBad=ds9.RED, size=8, frame=frame) if displayResiduals: maUtils.showPsfCandidates(exposure, psfCellSet, psf=psf, frame=4, normalize=normalizeResiduals, showBadCandidates=showBadCandidates) if displayPsfComponents: maUtils.showPsf(psf, frame=6) if displayPsfMosaic: maUtils.showPsfMosaic(exposure, psf, frame=7, showFwhm=True) ds9.scale('linear', 0, 1, frame=7) # # Generate some QA information # # Count PSF stars #
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|