194 def run(self, exposure, sources, expId=0, matches=None):
199 exposure : `lsst.afw.image.Exposure`
200 Exposure to process; measured PSF will be added.
202 Measured sources on exposure; flag fields will be set marking
203 stars chosen by the star selector and the PSF determiner if a schema
204 was passed to the task constructor.
205 expId : `int`, optional
206 Exposure id used for generating random seed.
207 matches : `list`, optional
208 A list of ``lsst.afw.table.ReferenceMatch`` objects
209 (i.e. of ``lsst.afw.table.Match`` with @c first being
210 of type ``lsst.afw.table.SimpleRecord`` and @c second
211 type lsst.afw.table.SourceRecord --- the reference object and detected
212 object respectively) as returned by @em e.g. the AstrometryTask.
213 Used by star selectors that choose to refer to an external catalog.
217 measurement : `lsst.pipe.base.Struct`
218 PSF measurement as a struct with attributes:
221 The measured PSF (also set in the input exposure).
223 An `lsst.afw.math.SpatialCellSet` containing the PSF candidates
224 as returned by the psf determiner.
228 NonfinitePsfShapeError
229 If the new PSF has NaN or Inf width.
231 self.log.info(
"Measuring PSF")
237 displayPsfCandidates =
lsstDebug.Info(__name__).displayPsfCandidates
245 stars = self.starSelector.run(sourceCat=sources, matches=matches, exposure=exposure)
246 selectionResult = self.makePsfCandidates.run(stars.sourceCat, exposure=exposure)
247 self.log.info(
"PSF star selector found %d candidates", len(selectionResult.psfCandidates))
248 reserveResult = self.reserve.run(selectionResult.goodStarCat, expId=expId)
250 psfDeterminerList = [cand
for cand, use
251 in zip(selectionResult.psfCandidates, reserveResult.use)
if use]
253 if selectionResult.psfCandidates
and self.
candidateKey is not None:
254 for cand
in selectionResult.psfCandidates:
255 source = cand.getSource()
258 self.log.info(
"Sending %d candidates to PSF determiner", len(psfDeterminerList))
263 disp = afwDisplay.Display(frame=frame)
264 disp.mtv(exposure, title=
"psf determination")
269 psf, cellSet = self.psfDeterminer.determinePsf(exposure, psfDeterminerList, self.metadata,
271 self.log.info(
"PSF determination using %d/%d stars.",
272 self.metadata.getScalar(
"numGoodStars"), self.metadata.getScalar(
"numAvailStars"))
273 if not np.isfinite((psfSize := psf.computeShape(psf.getAveragePosition()).getDeterminantRadius())):
276 self.log.info(
"Fitted PSF size: %f pixels", psfSize)
283 disp = afwDisplay.Display(frame=frame)
287 if displayPsfCandidates:
293 showBadCandidates=showBadCandidates,
294 normalizeResiduals=normalizeResiduals,
297 disp = afwDisplay.Display(frame=frame)
298 maUtils.showPsfMosaic(exposure, psf, display=disp, showFwhm=
True)
299 disp.scale(
"linear", 0, 1)
302 return pipeBase.Struct(