LSST Applications g0265f82a02+0e5473021a,g02d81e74bb+0dd8ce4237,g1470d8bcf6+3ea6592b6f,g2079a07aa2+86d27d4dc4,g2305ad1205+5ca4c0b359,g295015adf3+d10818ec9d,g2a9a014e59+6f9be1b9cd,g2bbee38e9b+0e5473021a,g337abbeb29+0e5473021a,g3ddfee87b4+703ba97ebf,g487adcacf7+4fa16da234,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+ffa42b374e,g5a732f18d5+53520f316c,g64a986408d+0dd8ce4237,g858d7b2824+0dd8ce4237,g8a8a8dda67+585e252eca,g99cad8db69+d39438377f,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,ga8c6da7877+f1d96605c8,gb0e22166c9+60f28cb32d,gb6a65358fc+0e5473021a,gba4ed39666+c2a2e4ac27,gbb8dafda3b+e5339d463f,gc120e1dc64+da31e9920e,gc28159a63d+0e5473021a,gcf0d15dbbd+703ba97ebf,gdaeeff99f8+f9a426f77a,ge6526c86ff+889fc9d533,ge79ae78c31+0e5473021a,gee10cc3b42+585e252eca,gf18bd8381d+7268b93478,gff1a9f87cc+0dd8ce4237,w.2024.16
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Static Public Attributes | Static Protected Attributes | List of all members
lsst.meas.extensions.piff.piffPsfDeterminer.PiffPsfDeterminerTask Class Reference
Inheritance diagram for lsst.meas.extensions.piff.piffPsfDeterminer.PiffPsfDeterminerTask:
lsst.meas.algorithms.psfDeterminer.BasePsfDeterminerTask

Public Member Functions

 determinePsf (self, exposure, psfCandidateList, metadata=None, flagKey=None)
 

Static Public Attributes

 ConfigClass = PiffPsfDeterminerConfig
 

Static Protected Attributes

str _DefaultName = "psfDeterminer.Piff"
 

Detailed Description

A measurePsfTask PSF estimator using Piff as the implementation.

Definition at line 269 of file piffPsfDeterminer.py.

Member Function Documentation

◆ determinePsf()

lsst.meas.extensions.piff.piffPsfDeterminer.PiffPsfDeterminerTask.determinePsf ( self,
exposure,
psfCandidateList,
metadata = None,
flagKey = None )
Determine a Piff PSF model for an exposure given a list of PSF
candidates.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
   Exposure containing the PSF candidates.
psfCandidateList : `list` of `lsst.meas.algorithms.PsfCandidate`
   A sequence of PSF candidates typically obtained by detecting sources
   and then running them through a star selector.
metadata : `lsst.daf.base import PropertyList` or `None`, optional
   A home for interesting tidbits of information.
flagKey : `str` or `None`, optional
   Schema key used to mark sources actually used in PSF determination.

Returns
-------
psf : `lsst.meas.extensions.piff.PiffPsf`
   The measured PSF model.
psfCellSet : `None`
   Unused by this PsfDeterminer.

Reimplemented from lsst.meas.algorithms.psfDeterminer.BasePsfDeterminerTask.

Definition at line 275 of file piffPsfDeterminer.py.

277 ):
278 """Determine a Piff PSF model for an exposure given a list of PSF
279 candidates.
280
281 Parameters
282 ----------
283 exposure : `lsst.afw.image.Exposure`
284 Exposure containing the PSF candidates.
285 psfCandidateList : `list` of `lsst.meas.algorithms.PsfCandidate`
286 A sequence of PSF candidates typically obtained by detecting sources
287 and then running them through a star selector.
288 metadata : `lsst.daf.base import PropertyList` or `None`, optional
289 A home for interesting tidbits of information.
290 flagKey : `str` or `None`, optional
291 Schema key used to mark sources actually used in PSF determination.
292
293 Returns
294 -------
295 psf : `lsst.meas.extensions.piff.PiffPsf`
296 The measured PSF model.
297 psfCellSet : `None`
298 Unused by this PsfDeterminer.
299 """
300 psfCandidateList = self.downsampleCandidates(psfCandidateList)
301
302 if self.config.stampSize:
303 stampSize = self.config.stampSize
304 if stampSize > psfCandidateList[0].getWidth():
305 self.log.warning("stampSize is larger than the PSF candidate size. Using candidate size.")
306 stampSize = psfCandidateList[0].getWidth()
307 else: # TODO: Only the if block should stay after DM-36311
308 self.log.debug("stampSize not set. Using candidate size.")
309 stampSize = psfCandidateList[0].getWidth()
310
311 scale = exposure.getWcs().getPixelScale().asArcseconds()
312 match self.config.useCoordinates:
313 case 'field':
314 detector = exposure.getDetector()
315 pix_to_field = detector.getTransform(PIXELS, FIELD_ANGLE)
316 gswcs = UVWcsWrapper(pix_to_field)
317 pointing = None
318 case 'sky':
319 gswcs = CelestialWcsWrapper(exposure.getWcs())
320 skyOrigin = exposure.getWcs().getSkyOrigin()
321 ra = skyOrigin.getLongitude().asDegrees()
322 dec = skyOrigin.getLatitude().asDegrees()
323 pointing = galsim.CelestialCoord(
324 ra*galsim.degrees,
325 dec*galsim.degrees
326 )
327 case 'pixel':
328 gswcs = galsim.PixelScale(scale)
329 pointing = None
330
331 stars = []
332 for candidate in psfCandidateList:
333 cmi = candidate.getMaskedImage(stampSize, stampSize)
334 good = getGoodPixels(cmi, self.config.zeroWeightMaskBits)
335 fracGood = np.sum(good)/good.size
336 if fracGood < self.config.minimumUnmaskedFraction:
337 continue
338 weight = computeWeight(cmi, self.config.maxSNR, good)
339
340 bbox = cmi.getBBox()
341 bds = galsim.BoundsI(
342 galsim.PositionI(*bbox.getMin()),
343 galsim.PositionI(*bbox.getMax())
344 )
345 gsImage = galsim.Image(bds, wcs=gswcs, dtype=float)
346 gsImage.array[:] = cmi.image.array
347 gsWeight = galsim.Image(bds, wcs=gswcs, dtype=float)
348 gsWeight.array[:] = weight
349
350 source = candidate.getSource()
351 image_pos = galsim.PositionD(source.getX(), source.getY())
352
353 data = piff.StarData(
354 gsImage,
355 image_pos,
356 weight=gsWeight,
357 pointing=pointing
358 )
359 stars.append(piff.Star(data, None))
360
361 piffConfig = {
362 'type': "Simple",
363 'model': {
364 'type': 'PixelGrid',
365 'scale': scale * self.config.samplingSize,
366 'size': stampSize,
367 'interp': self.config.interpolant
368 },
369 'interp': {
370 'type': 'BasisPolynomial',
371 'order': self.config.spatialOrder
372 },
373 'outliers': {
374 'type': 'Chisq',
375 'nsigma': self.config.outlierNSigma,
376 'max_remove': self.config.outlierMaxRemove
377 }
378 }
379
380 piffResult = piff.PSF.process(piffConfig)
381 wcs = {0: gswcs}
382
383 piffResult.fit(stars, wcs, pointing, logger=self.log)
384 drawSize = 2*np.floor(0.5*stampSize/self.config.samplingSize) + 1
385
386 used_image_pos = [s.image_pos for s in piffResult.stars]
387 if flagKey:
388 for candidate in psfCandidateList:
389 source = candidate.getSource()
390 posd = galsim.PositionD(source.getX(), source.getY())
391 if posd in used_image_pos:
392 source.set(flagKey, True)
393
394 if metadata is not None:
395 metadata["spatialFitChi2"] = piffResult.chisq
396 metadata["numAvailStars"] = len(stars)
397 metadata["numGoodStars"] = len(piffResult.stars)
398 metadata["avgX"] = np.mean([p.x for p in piffResult.stars])
399 metadata["avgY"] = np.mean([p.y for p in piffResult.stars])
400
401 if not self.config.debugStarData:
402 for star in piffResult.stars:
403 # Remove large data objects from the stars
404 del star.fit.params
405 del star.fit.params_var
406 del star.fit.A
407 del star.fit.b
408 del star.data.image
409 del star.data.weight
410 del star.data.orig_weight
411
412 return PiffPsf(drawSize, drawSize, piffResult), None
413
414

Member Data Documentation

◆ _DefaultName

str lsst.meas.extensions.piff.piffPsfDeterminer.PiffPsfDeterminerTask._DefaultName = "psfDeterminer.Piff"
staticprotected

Definition at line 273 of file piffPsfDeterminer.py.

◆ ConfigClass

lsst.meas.extensions.piff.piffPsfDeterminer.PiffPsfDeterminerTask.ConfigClass = PiffPsfDeterminerConfig
static

Definition at line 272 of file piffPsfDeterminer.py.


The documentation for this class was generated from the following file: