142 def selectStars(self, exposure, catalog, matches=None):
143 """Return a list of PSF candidates that represent likely stars
145 A list of PSF candidates may be used by a PSF fitter to construct a PSF.
147 @param[in] exposure: the exposure containing the sources
148 @param[in] catalog: a SourceCatalog containing sources that may be stars
149 @param[in] matches: astrometric matches; ignored by this star selector
151 @return psfCandidateList: a list of PSF candidates.
158 isGoodSource =
CheckSource(catalog.getTable(), self.config.badFlags, self.config.fluxLim,
161 detector = exposure.getDetector()
163 mi = exposure.getMaskedImage()
171 ixx, iyy = s.getIxx(), s.getIyy()
173 if (ixx == ixx
and ixx < self.config.histMomentMax
and
174 iyy == iyy
and iyy < self.config.histMomentMax
and
176 iqqList.append(s.getIxx())
177 iqqList.append(s.getIyy())
179 iqqMean = stat.getValue(afwMath.MEANCLIP)
180 iqqStd = stat.getValue(afwMath.STDEVCLIP)
181 iqqMax = stat.getValue(afwMath.MAX)
183 iqqLimit = max(iqqMean + self.config.histMomentClip*iqqStd,
184 self.config.histMomentMaxMultiplier*iqqMean)
186 if iqqLimit > iqqMax:
187 iqqLimit = max(self.config.histMomentMinMultiplier*iqqMean, iqqMax)
189 psfHist =
_PsfShapeHistogram(detector=detector, xSize=self.config.histSize, ySize=self.config.histSize,
190 ixxMax=iqqLimit, iyyMax=iqqLimit)
192 if display
and displayExposure:
194 ds9.mtv(mi, frame=frame, title=
"PSF candidates")
196 with ds9.Buffering():
197 for source
in catalog:
198 if isGoodSource(source):
199 if psfHist.insert(source):
206 if display
and displayExposure:
207 ds9.dot(
"o", source.getX() - mi.getX0(),
208 source.getY() - mi.getY0(), frame=frame, ctype=ctype)
210 clumps = psfHist.getClumps(display=display)
218 psfCandidateList = []
220 pixToTanXYTransform =
None
221 if detector
is not None:
222 tanSys = detector.makeCameraSys(cameraGeom.TAN_PIXELS)
223 pixToTanXYTransform = detector.getTransformMap().get(tanSys)
228 for source
in catalog:
229 if not isGoodSource(source):
continue
230 Ixx, Ixy, Iyy = source.getIxx(), source.getIxy(), source.getIyy()
231 if pixToTanXYTransform:
233 linTransform = pixToTanXYTransform.linearizeForwardTransform(p).getLinear()
234 m = geomEllip.Quadrupole(Ixx, Iyy, Ixy)
235 m.transform(linTransform)
236 Ixx, Iyy, Ixy = m.getIxx(), m.getIyy(), m.getIxy()
238 x, y = psfHist.momentsToPixel(Ixx, Iyy)
240 dx, dy = (x - clump.x), (y - clump.y)
242 if math.sqrt(clump.a*dx*dx + 2*clump.b*dx*dy + clump.c*dy*dy) < 2*self.config.clumpNSigma:
244 if not isGoodSource(source):
247 psfCandidate = algorithmsLib.makePsfCandidate(source, exposure)
252 if psfCandidate.getWidth() == 0:
253 psfCandidate.setBorderWidth(self.config.borderWidth)
254 psfCandidate.setWidth(self.config.kernelSize + 2*self.config.borderWidth)
255 psfCandidate.setHeight(self.config.kernelSize + 2*self.config.borderWidth)
257 im = psfCandidate.getMaskedImage().getImage()
260 psfCandidateList.append(psfCandidate)
262 if display
and displayExposure:
263 ds9.dot(
"o", source.getX() - mi.getX0(), source.getY() - mi.getY0(),
264 size=4, frame=frame, ctype=ds9.CYAN)
265 except Exception
as err:
269 return psfCandidateList