38 fluxLim = pexConfig.Field(
39 doc =
"specify the minimum psfFlux for good Psf Candidates",
42 check =
lambda x: x >= 0.0,
44 fluxMax = pexConfig.Field(
45 doc =
"specify the maximum psfFlux for good Psf Candidates (ignored if == 0)",
49 check =
lambda x: x >= 0.0,
51 badStarPixelFlags = pexConfig.ListField(
52 doc =
"PSF candidate objects may not have any of these bits set",
54 default = [
"base_PixelFlags_flag_edge",
"base_PixelFlags_flag_interpolatedCenter",
"base_PixelFlags_flag_saturatedCenter"],
56 kernelSize = pexConfig.Field(
57 doc =
"size of the kernel to create",
61 borderWidth = pexConfig.Field(
62 doc =
"number of pixels to ignore around the edge of PSF candidate postage stamps",
68 """A functor to check whether a source has any flags set that should cause it to be labeled bad."""
70 def __init__(self, table, fluxLim, fluxMax, badStarPixelFlags):
71 self.
keys = [table.getSchema().find(name).key
for name
in badStarPixelFlags]
72 self.keys.append(table.getCentroidFlagKey())
87 ConfigClass = CatalogStarSelectorConfig
90 """Construct a star selector that uses second moments
92 This is a naive algorithm and should be used with caution.
94 @param[in] config: An instance of CatalogStarSelectorConfig
97 config = CatalogStarSelector.ConfigClass()
106 """Return a list of PSF candidates that represent likely stars
108 A list of PSF candidates may be used by a PSF fitter to construct a PSF.
110 @param[in] exposure: the exposure containing the sources
111 @param[in] sources: a source list containing sources that may be stars
112 @param[in] matches: a match vector as produced by meas_astrom; not actually optional
113 (passing None just allows us to handle the exception better here
114 than in calling code)
116 @return psfCandidateList: a list of PSF candidates.
125 "Cannot use catalog star selector without running astrometry."
128 mi = exposure.getMaskedImage()
133 frames[
"displayExposure"] = 1
134 ds9.mtv(mi, frame=frames[
"displayExposure"], title=
"PSF candidates")
138 wcs = exposure.getWcs()
139 imageSize = exposure.getDimensions()
140 filterName = exposure.getFilter().getName()
141 calib = exposure.getCalib()
150 psfCandidateList = []
152 with ds9.Buffering():
153 for ref, source, d
in matches:
154 if not ref.get(
"resolved"):
155 if not isGoodSource(source):
156 symb, ctype =
"+", ds9.RED
164 if psfCandidate.getWidth() == 0:
169 im = psfCandidate.getMaskedImage().getImage()
171 if not numpy.isfinite(max):
173 psfCandidateList.append(psfCandidate)
175 symb, ctype =
"+", ds9.GREEN
176 except Exception
as err:
177 symb, ctype =
"o", ds9.RED
181 symb, ctype =
"o", ds9.BLUE
183 if display
and displayExposure:
184 ds9.dot(symb, source.getX() - mi.getX0(), source.getY() - mi.getY0(),
185 size=4, frame=frames[
"displayExposure"], ctype=ctype)
187 if display
and pauseAtEnd:
188 raw_input(
"Continue? y[es] p[db] ")
190 return psfCandidateList
192 measAlg.starSelectorRegistry.register(
"catalog", CatalogStarSelector)
boost::shared_ptr< PsfCandidate< PixelT > > makePsfCandidate(boost::shared_ptr< afw::table::SourceRecord > const &source, boost::shared_ptr< afw::image::Exposure< PixelT > > image)
Statistics makeStatistics(afwImage::Mask< afwImage::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl)
Specialization to handle Masks.