LSST Applications g00274db5b6+edbf708997,g00d0e8bbd7+edbf708997,g199a45376c+5137f08352,g1fd858c14a+1d4b6db739,g262e1987ae+f4d9505c4f,g29ae962dfc+7156fb1a53,g2cef7863aa+73c82f25e4,g35bb328faa+edbf708997,g3e17d7035e+5b3adc59f5,g3fd5ace14f+852fa6fbcb,g47891489e3+6dc8069a4c,g53246c7159+edbf708997,g64539dfbff+9f17e571f4,g67b6fd64d1+6dc8069a4c,g74acd417e5+ae494d68d9,g786e29fd12+af89c03590,g7ae74a0b1c+a25e60b391,g7aefaa3e3d+536efcc10a,g7cc15d900a+d121454f8d,g87389fa792+a4172ec7da,g89139ef638+6dc8069a4c,g8d7436a09f+28c28d8d6d,g8ea07a8fe4+db21c37724,g92c671f44c+9f17e571f4,g98df359435+b2e6376b13,g99af87f6a8+b0f4ad7b8d,gac66b60396+966efe6077,gb88ae4c679+7dec8f19df,gbaa8f7a6c5+38b34f4976,gbf99507273+edbf708997,gc24b5d6ed1+9f17e571f4,gca7fc764a6+6dc8069a4c,gcc769fe2a4+97d0256649,gd7ef33dd92+6dc8069a4c,gdab6d2f7ff+ae494d68d9,gdbb4c4dda9+9f17e571f4,ge410e46f29+6dc8069a4c,geaed405ab2+e194be0d2b,w.2025.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask Class Reference
Inheritance diagram for lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask:

Public Member Functions

 __init__ (self, **kwargs)
 
 run (self, exposure, sources, background)
 
 update_psf_stats (self, summary, psf, bbox, sources=None, image_mask=None, image_ap_corr_map=None, sources_is_astropy=False)
 
 update_wcs_stats (self, summary, wcs, bbox, visitInfo)
 
 update_photo_calib_stats (self, summary, photo_calib)
 
 update_background_stats (self, summary, background)
 
 update_masked_image_stats (self, summary, masked_image)
 
 update_effective_time_stats (self, summary, exposure)
 
 update_magnitude_limit_stats (self, summary, exposure)
 

Static Public Attributes

 ConfigClass = ComputeExposureSummaryStatsConfig
 

Static Protected Attributes

str _DefaultName = "computeExposureSummaryStats"
 

Detailed Description

Task to compute exposure summary statistics.

This task computes various quantities suitable for DPDD and other
downstream processing at the detector centers, including:
- expTime
- psfSigma
- psfArea
- psfIxx
- psfIyy
- psfIxy
- ra
- dec
- pixelScale (arcsec/pixel)
- zenithDistance
- zeroPoint
- skyBg
- skyNoise
- meanVar
- raCorners
- decCorners
- astromOffsetMean
- astromOffsetStd

These additional quantities are computed from the stars in the detector:
- psfStarDeltaE1Median
- psfStarDeltaE2Median
- psfStarDeltaE1Scatter
- psfStarDeltaE2Scatter
- psfStarDeltaSizeMedian
- psfStarDeltaSizeScatter
- psfStarScaledDeltaSizeScatter

These quantities are computed based on the PSF model and image mask
to assess the robustness of the PSF model across a given detector
(against, e.g., extrapolation instability):
- maxDistToNearestPsf
- psfTraceRadiusDelta
- psfApFluxDelta

This quantity is computed based on the aperture correction map, the
psfSigma, and the image mask to assess the robustness of the aperture
corrections across a given detector:
- psfApCorrSigmaScaledDelta

These quantities are computed to assess depth:
- effTime
- effTimePsfSigmaScale
- effTimeSkyBgScale
- effTimeZeroPointScale
- magLim

Definition at line 163 of file computeExposureSummaryStats.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.__init__ ( self,
** kwargs )

Definition at line 218 of file computeExposureSummaryStats.py.

218 def __init__(self, **kwargs):
219 super().__init__(**kwargs)
220
221 self.makeSubtask("starSelector")
222

Member Function Documentation

◆ run()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.run ( self,
exposure,
sources,
background )
Measure exposure statistics from the exposure, sources, and
background.

Parameters
----------
exposure : `lsst.afw.image.ExposureF`
sources : `lsst.afw.table.SourceCatalog`
background : `lsst.afw.math.BackgroundList`

Returns
-------
summary : `lsst.afw.image.ExposureSummary`

Definition at line 224 of file computeExposureSummaryStats.py.

224 def run(self, exposure, sources, background):
225 """Measure exposure statistics from the exposure, sources, and
226 background.
227
228 Parameters
229 ----------
230 exposure : `lsst.afw.image.ExposureF`
231 sources : `lsst.afw.table.SourceCatalog`
232 background : `lsst.afw.math.BackgroundList`
233
234 Returns
235 -------
236 summary : `lsst.afw.image.ExposureSummary`
237 """
238 self.log.info("Measuring exposure statistics")
239
241
242 # Set exposure time.
243 exposureTime = exposure.getInfo().getVisitInfo().getExposureTime()
244 summary.expTime = exposureTime
245
246 bbox = exposure.getBBox()
247
248 psf = exposure.getPsf()
249 self.update_psf_stats(
250 summary, psf, bbox, sources, image_mask=exposure.mask, image_ap_corr_map=exposure.apCorrMap
251 )
252
253 wcs = exposure.getWcs()
254 visitInfo = exposure.getInfo().getVisitInfo()
255 self.update_wcs_stats(summary, wcs, bbox, visitInfo)
256
257 photoCalib = exposure.getPhotoCalib()
258 self.update_photo_calib_stats(summary, photoCalib)
259
260 self.update_background_stats(summary, background)
261
262 self.update_masked_image_stats(summary, exposure.getMaskedImage())
263
264 self.update_magnitude_limit_stats(summary, exposure)
265
266 self.update_effective_time_stats(summary, exposure)
267
268 md = exposure.getMetadata()
269 if 'SFM_ASTROM_OFFSET_MEAN' in md:
270 summary.astromOffsetMean = md['SFM_ASTROM_OFFSET_MEAN']
271 summary.astromOffsetStd = md['SFM_ASTROM_OFFSET_STD']
272
273 return summary
274

◆ update_background_stats()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.update_background_stats ( self,
summary,
background )
Compute summary-statistic fields that depend only on the
background model.

Parameters
----------
summary : `lsst.afw.image.ExposureSummaryStats`
    Summary object to update in-place.
background : `lsst.afw.math.BackgroundList` or `None`
    Background model.  If `None`, all fields that depend on the
    background will be reset (generally to NaN).

Notes
-----
This does not include fields that depend on the background-subtracted
masked image; when the background changes, it should generally be
applied to the image and `update_masked_image_stats` should be called
as well.

Definition at line 516 of file computeExposureSummaryStats.py.

516 def update_background_stats(self, summary, background):
517 """Compute summary-statistic fields that depend only on the
518 background model.
519
520 Parameters
521 ----------
522 summary : `lsst.afw.image.ExposureSummaryStats`
523 Summary object to update in-place.
524 background : `lsst.afw.math.BackgroundList` or `None`
525 Background model. If `None`, all fields that depend on the
526 background will be reset (generally to NaN).
527
528 Notes
529 -----
530 This does not include fields that depend on the background-subtracted
531 masked image; when the background changes, it should generally be
532 applied to the image and `update_masked_image_stats` should be called
533 as well.
534 """
535 if background is not None:
536 bgStats = (bg[0].getStatsImage().getImage().array
537 for bg in background)
538 summary.skyBg = float(sum(np.median(bg[np.isfinite(bg)]) for bg in bgStats))
539 else:
540 summary.skyBg = float("nan")
541

◆ update_effective_time_stats()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.update_effective_time_stats ( self,
summary,
exposure )
Compute effective exposure time statistics to estimate depth.

The effective exposure time is the equivalent shutter open
time that would be needed under nominal conditions to give the
same signal-to-noise for a point source as what is achieved by
the observation of interest. This metric combines measurements
of the point-spread function, the sky brightness, and the
transparency. It assumes that the observation is
sky-background dominated.

.. _teff_definitions:

The effective exposure time and its subcomponents are defined in [1]_.

References
----------

.. [1] Neilsen, E.H., Bernstein, G., Gruendl, R., and Kent, S. (2016).
       Limiting Magnitude, \tau, teff, and Image Quality in DES Year 1
       https://www.osti.gov/biblio/1250877/

Parameters
----------
summary : `lsst.afw.image.ExposureSummaryStats`
    Summary object to update in-place.
exposure : `lsst.afw.image.ExposureF`
    Exposure to grab band and exposure time metadata

Definition at line 574 of file computeExposureSummaryStats.py.

574 def update_effective_time_stats(self, summary, exposure):
575 """Compute effective exposure time statistics to estimate depth.
576
577 The effective exposure time is the equivalent shutter open
578 time that would be needed under nominal conditions to give the
579 same signal-to-noise for a point source as what is achieved by
580 the observation of interest. This metric combines measurements
581 of the point-spread function, the sky brightness, and the
582 transparency. It assumes that the observation is
583 sky-background dominated.
584
585 .. _teff_definitions:
586
587 The effective exposure time and its subcomponents are defined in [1]_.
588
589 References
590 ----------
591
592 .. [1] Neilsen, E.H., Bernstein, G., Gruendl, R., and Kent, S. (2016).
593 Limiting Magnitude, \tau, teff, and Image Quality in DES Year 1
594 https://www.osti.gov/biblio/1250877/
595
596 Parameters
597 ----------
598 summary : `lsst.afw.image.ExposureSummaryStats`
599 Summary object to update in-place.
600 exposure : `lsst.afw.image.ExposureF`
601 Exposure to grab band and exposure time metadata
602
603 """
604 nan = float("nan")
605 summary.effTime = nan
606 summary.effTimePsfSigmaScale = nan
607 summary.effTimeSkyBgScale = nan
608 summary.effTimeZeroPointScale = nan
609
610 exposureTime = exposure.getInfo().getVisitInfo().getExposureTime()
611 filterLabel = exposure.getFilter()
612 if (filterLabel is None) or (not filterLabel.hasBandLabel):
613 band = None
614 else:
615 band = filterLabel.bandLabel
616
617 if band is None:
618 self.log.warning("No band associated with exposure; effTime not calculated.")
619 return
620
621 # PSF component
622 if np.isnan(summary.psfSigma):
623 self.log.debug("PSF sigma is NaN")
624 f_eff = nan
625 elif band not in self.config.fiducialPsfSigma:
626 self.log.debug(f"Fiducial PSF value not found for {band}")
627 f_eff = nan
628 else:
629 fiducialPsfSigma = self.config.fiducialPsfSigma[band]
630 f_eff = (summary.psfSigma / fiducialPsfSigma)**-2
631
632 # Transparency component
633 # Note: Assumes that the zeropoint includes the exposure time
634 if np.isnan(summary.zeroPoint):
635 self.log.debug("Zero point is NaN")
636 c_eff = nan
637 elif band not in self.config.fiducialZeroPoint:
638 self.log.debug(f"Fiducial zero point value not found for {band}")
639 c_eff = nan
640 else:
641 fiducialZeroPoint = self.config.fiducialZeroPoint[band]
642 zeroPointDiff = fiducialZeroPoint - (summary.zeroPoint - 2.5*np.log10(exposureTime))
643 c_eff = min(10**(-2.0*(zeroPointDiff)/2.5), self.config.maxEffectiveTransparency)
644
645 # Sky brightness component (convert to cts/s)
646 if np.isnan(summary.skyBg):
647 self.log.debug("Sky background is NaN")
648 b_eff = nan
649 elif band not in self.config.fiducialSkyBackground:
650 self.log.debug(f"Fiducial sky background value not found for {band}")
651 b_eff = nan
652 else:
653 fiducialSkyBackground = self.config.fiducialSkyBackground[band]
654 b_eff = fiducialSkyBackground/(summary.skyBg/exposureTime)
655
656 # Effective exposure time scale factor
657 t_eff = f_eff * c_eff * b_eff
658
659 # Effective exposure time (seconds)
660 effectiveTime = t_eff * exposureTime
661
662 # Output quantities
663 summary.effTime = float(effectiveTime)
664 summary.effTimePsfSigmaScale = float(f_eff)
665 summary.effTimeSkyBgScale = float(b_eff)
666 summary.effTimeZeroPointScale = float(c_eff)
667

◆ update_magnitude_limit_stats()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.update_magnitude_limit_stats ( self,
summary,
exposure )
Compute a summary statistic for the point-source magnitude limit at
a given signal-to-noise ratio using exposure-level metadata.

The magnitude limit is calculated at a given SNR from the PSF,
sky, zeropoint, and readnoise in accordance with SMTN-002 [1]_,
LSE-40 [2]_, and DMTN-296 [3]_.

References
----------

.. [1] "Calculating LSST limiting magnitudes and SNR" (SMTN-002)
.. [2] "Photon Rates and SNR Calculations" (LSE-40)
.. [3] "Calculations of Image and Catalog Depth" (DMTN-296)


Parameters
----------
summary : `lsst.afw.image.ExposureSummaryStats`
    Summary object to update in-place.
exposure : `lsst.afw.image.ExposureF`
    Exposure to grab band and exposure time metadata

Definition at line 668 of file computeExposureSummaryStats.py.

668 def update_magnitude_limit_stats(self, summary, exposure):
669 """Compute a summary statistic for the point-source magnitude limit at
670 a given signal-to-noise ratio using exposure-level metadata.
671
672 The magnitude limit is calculated at a given SNR from the PSF,
673 sky, zeropoint, and readnoise in accordance with SMTN-002 [1]_,
674 LSE-40 [2]_, and DMTN-296 [3]_.
675
676 References
677 ----------
678
679 .. [1] "Calculating LSST limiting magnitudes and SNR" (SMTN-002)
680 .. [2] "Photon Rates and SNR Calculations" (LSE-40)
681 .. [3] "Calculations of Image and Catalog Depth" (DMTN-296)
682
683
684 Parameters
685 ----------
686 summary : `lsst.afw.image.ExposureSummaryStats`
687 Summary object to update in-place.
688 exposure : `lsst.afw.image.ExposureF`
689 Exposure to grab band and exposure time metadata
690 """
691 if exposure.getDetector() is None:
692 summary.magLim = float("nan")
693 return
694
695 # Calculate the average readnoise [e-]
696 readNoiseList = list(ipIsr.getExposureReadNoises(exposure).values())
697 readNoise = np.nanmean(readNoiseList)
698 if np.isnan(readNoise):
699 readNoise = 0.0
700 self.log.warning("Read noise set to NaN! Setting readNoise to 0.0 to proceed.")
701
702 # Calculate the average gain [e-/ADU]
703 gainList = list(ipIsr.getExposureGains(exposure).values())
704 gain = np.nanmean(gainList)
705 if np.isnan(gain):
706 self.log.warning("Gain set to NaN! Setting magLim to NaN.")
707 summary.magLim = float("nan")
708 return
709
710 # Get the image units (default to 'adu' if metadata key absent)
711 md = exposure.getMetadata()
712 if md.get("LSST ISR UNITS", "adu") == "electron":
713 gain = 1.0
714
715 # Convert readNoise to image units
716 readNoise /= gain
717
718 # Calculate the limiting magnitude.
719 # Note 1: Assumes that the image and readnoise have the same units
720 # Note 2: Assumes that the zeropoint includes the exposure time
721 magLim = compute_magnitude_limit(summary.psfArea, summary.skyBg,
722 summary.zeroPoint, readNoise,
723 gain, self.config.magLimSnr)
724
725 summary.magLim = float(magLim)
726
727

◆ update_masked_image_stats()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.update_masked_image_stats ( self,
summary,
masked_image )
Compute summary-statistic fields that depend on the masked image
itself.

Parameters
----------
summary : `lsst.afw.image.ExposureSummaryStats`
    Summary object to update in-place.
masked_image : `lsst.afw.image.MaskedImage` or `None`
    Masked image.  If `None`, all fields that depend
    on the masked image will be reset (generally to NaN).

Definition at line 542 of file computeExposureSummaryStats.py.

542 def update_masked_image_stats(self, summary, masked_image):
543 """Compute summary-statistic fields that depend on the masked image
544 itself.
545
546 Parameters
547 ----------
548 summary : `lsst.afw.image.ExposureSummaryStats`
549 Summary object to update in-place.
550 masked_image : `lsst.afw.image.MaskedImage` or `None`
551 Masked image. If `None`, all fields that depend
552 on the masked image will be reset (generally to NaN).
553 """
554 nan = float("nan")
555 if masked_image is None:
556 summary.skyNoise = nan
557 summary.meanVar = nan
558 return
559 statsCtrl = afwMath.StatisticsControl()
560 statsCtrl.setNumSigmaClip(self.config.sigmaClip)
561 statsCtrl.setNumIter(self.config.clipIter)
562 statsCtrl.setAndMask(afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes))
563 statsCtrl.setNanSafe(True)
564
565 statObj = afwMath.makeStatistics(masked_image, afwMath.STDEVCLIP, statsCtrl)
566 skyNoise, _ = statObj.getResult(afwMath.STDEVCLIP)
567 summary.skyNoise = skyNoise
568
569 statObj = afwMath.makeStatistics(masked_image.variance, masked_image.mask, afwMath.MEANCLIP,
570 statsCtrl)
571 meanVar, _ = statObj.getResult(afwMath.MEANCLIP)
572 summary.meanVar = meanVar
573
Pass parameters to a Statistics object.
Definition Statistics.h:83
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)
Definition Statistics.h:361

◆ update_photo_calib_stats()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.update_photo_calib_stats ( self,
summary,
photo_calib )
Compute all summary-statistic fields that depend on the photometric
calibration model.

Parameters
----------
summary : `lsst.afw.image.ExposureSummaryStats`
    Summary object to update in-place.
photo_calib : `lsst.afw.image.PhotoCalib` or `None`
    Photometric calibration model.  If `None`, all fields that depend
    on the photometric calibration will be reset (generally to NaN).

Definition at line 499 of file computeExposureSummaryStats.py.

499 def update_photo_calib_stats(self, summary, photo_calib):
500 """Compute all summary-statistic fields that depend on the photometric
501 calibration model.
502
503 Parameters
504 ----------
505 summary : `lsst.afw.image.ExposureSummaryStats`
506 Summary object to update in-place.
507 photo_calib : `lsst.afw.image.PhotoCalib` or `None`
508 Photometric calibration model. If `None`, all fields that depend
509 on the photometric calibration will be reset (generally to NaN).
510 """
511 if photo_calib is not None:
512 summary.zeroPoint = float(2.5*np.log10(photo_calib.getInstFluxAtZeroMagnitude()))
513 else:
514 summary.zeroPoint = float("nan")
515

◆ update_psf_stats()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.update_psf_stats ( self,
summary,
psf,
bbox,
sources = None,
image_mask = None,
image_ap_corr_map = None,
sources_is_astropy = False )
Compute all summary-statistic fields that depend on the PSF model.

Parameters
----------
summary : `lsst.afw.image.ExposureSummaryStats`
    Summary object to update in-place.
psf : `lsst.afw.detection.Psf` or `None`
    Point spread function model.  If `None`, all fields that depend on
    the PSF will be reset (generally to NaN).
bbox : `lsst.geom.Box2I`
    Bounding box of the image for which summary stats are being
    computed.
sources : `lsst.afw.table.SourceCatalog` or `astropy.table.Table`
    Catalog for quantities that are computed from source table columns.
    If `None`, these quantities will be reset (generally to NaN).
    The type of this table must correspond to the
    ``sources_is_astropy`` argument.
image_mask : `lsst.afw.image.Mask`, optional
    Mask image that may be used to compute distance-to-nearest-star
    metrics.
sources_is_astropy : `bool`, optional
    Whether ``sources`` is an `astropy.table.Table` instance instead
    of an `lsst.afw.table.Catalog` instance.  Default is `False` (the
    latter).

Definition at line 275 of file computeExposureSummaryStats.py.

284 ):
285 """Compute all summary-statistic fields that depend on the PSF model.
286
287 Parameters
288 ----------
289 summary : `lsst.afw.image.ExposureSummaryStats`
290 Summary object to update in-place.
291 psf : `lsst.afw.detection.Psf` or `None`
292 Point spread function model. If `None`, all fields that depend on
293 the PSF will be reset (generally to NaN).
294 bbox : `lsst.geom.Box2I`
295 Bounding box of the image for which summary stats are being
296 computed.
297 sources : `lsst.afw.table.SourceCatalog` or `astropy.table.Table`
298 Catalog for quantities that are computed from source table columns.
299 If `None`, these quantities will be reset (generally to NaN).
300 The type of this table must correspond to the
301 ``sources_is_astropy`` argument.
302 image_mask : `lsst.afw.image.Mask`, optional
303 Mask image that may be used to compute distance-to-nearest-star
304 metrics.
305 sources_is_astropy : `bool`, optional
306 Whether ``sources`` is an `astropy.table.Table` instance instead
307 of an `lsst.afw.table.Catalog` instance. Default is `False` (the
308 latter).
309 """
310 nan = float("nan")
311 summary.psfSigma = nan
312 summary.psfIxx = nan
313 summary.psfIyy = nan
314 summary.psfIxy = nan
315 summary.psfArea = nan
316 summary.nPsfStar = 0
317 summary.psfStarDeltaE1Median = nan
318 summary.psfStarDeltaE2Median = nan
319 summary.psfStarDeltaE1Scatter = nan
320 summary.psfStarDeltaE2Scatter = nan
321 summary.psfStarDeltaSizeMedian = nan
322 summary.psfStarDeltaSizeScatter = nan
323 summary.psfStarScaledDeltaSizeScatter = nan
324 summary.maxDistToNearestPsf = nan
325 summary.psfTraceRadiusDelta = nan
326 summary.psfApFluxDelta = nan
327 summary.psfApCorrSigmaScaledDelta = nan
328
329 if psf is None:
330 return
331 shape = psf.computeShape(bbox.getCenter())
332 summary.psfSigma = shape.getDeterminantRadius()
333 summary.psfIxx = shape.getIxx()
334 summary.psfIyy = shape.getIyy()
335 summary.psfIxy = shape.getIxy()
336 im = psf.computeKernelImage(bbox.getCenter())
337 # The calculation of effective psf area is taken from
338 # ls.st/srd Equation 1.
339 summary.psfArea = float(np.sum(im.array)**2./np.sum(im.array**2.))
340
341 if image_mask is not None:
342 psfApRadius = max(self.config.minPsfApRadiusPix, 3.0*summary.psfSigma)
343 self.log.debug("Using radius of %.3f (pixels) for psfApFluxDelta metric", psfApRadius)
344 psfTraceRadiusDelta, psfApFluxDelta = compute_psf_image_deltas(
345 image_mask,
346 psf,
347 sampling=self.config.psfGridSampling,
348 ap_radius_pix=psfApRadius,
349 bad_mask_bits=self.config.psfBadMaskPlanes
350 )
351 summary.psfTraceRadiusDelta = float(psfTraceRadiusDelta)
352 summary.psfApFluxDelta = float(psfApFluxDelta)
353 if image_ap_corr_map is not None:
354 if self.config.psfApCorrFieldName not in image_ap_corr_map.keys():
355 self.log.warning(f"{self.config.psfApCorrFieldName} not found in "
356 "image_ap_corr_map. Setting psfApCorrSigmaScaledDelta to NaN.")
357 psfApCorrSigmaScaledDelta = nan
358 else:
359 image_ap_corr_field = image_ap_corr_map[self.config.psfApCorrFieldName]
360 psfApCorrSigmaScaledDelta = compute_ap_corr_sigma_scaled_delta(
361 image_mask,
362 image_ap_corr_field,
363 summary.psfSigma,
364 sampling=self.config.psfGridSampling,
365 bad_mask_bits=self.config.psfBadMaskPlanes,
366 )
367 summary.psfApCorrSigmaScaledDelta = float(psfApCorrSigmaScaledDelta)
368
369 if sources is None:
370 # No sources are available (as in some tests and rare cases where
371 # the selection criteria in finalizeCharacterization lead to no
372 # good sources).
373 return
374
375 # Count the total number of psf stars used (prior to stats selection).
376 nPsfStar = sources[self.config.starSelection].sum()
377 summary.nPsfStar = int(nPsfStar)
378
379 psf_mask = self.starSelector.run(sources).selected
380 nPsfStarsUsedInStats = psf_mask.sum()
381
382 if nPsfStarsUsedInStats == 0:
383 # No stars to measure statistics, so we must return the defaults
384 # of 0 stars and NaN values.
385 return
386
387 if sources_is_astropy:
388 psf_cat = sources[psf_mask]
389 else:
390 psf_cat = sources[psf_mask].copy(deep=True)
391
392 starXX = psf_cat[self.config.starShape + '_xx']
393 starYY = psf_cat[self.config.starShape + '_yy']
394 starXY = psf_cat[self.config.starShape + '_xy']
395 psfXX = psf_cat[self.config.psfShape + '_xx']
396 psfYY = psf_cat[self.config.psfShape + '_yy']
397 psfXY = psf_cat[self.config.psfShape + '_xy']
398
399 # Use the trace radius for the star size.
400 starSize = np.sqrt(starXX/2. + starYY/2.)
401
402 starE1 = (starXX - starYY)/(starXX + starYY)
403 starE2 = 2*starXY/(starXX + starYY)
404 starSizeMedian = np.median(starSize)
405
406 # Use the trace radius for the psf size.
407 psfSize = np.sqrt(psfXX/2. + psfYY/2.)
408 psfE1 = (psfXX - psfYY)/(psfXX + psfYY)
409 psfE2 = 2*psfXY/(psfXX + psfYY)
410
411 psfStarDeltaE1Median = np.median(starE1 - psfE1)
412 psfStarDeltaE1Scatter = sigmaMad(starE1 - psfE1, scale='normal')
413 psfStarDeltaE2Median = np.median(starE2 - psfE2)
414 psfStarDeltaE2Scatter = sigmaMad(starE2 - psfE2, scale='normal')
415
416 psfStarDeltaSizeMedian = np.median(starSize - psfSize)
417 psfStarDeltaSizeScatter = sigmaMad(starSize - psfSize, scale='normal')
418 psfStarScaledDeltaSizeScatter = psfStarDeltaSizeScatter/starSizeMedian
419
420 summary.psfStarDeltaE1Median = float(psfStarDeltaE1Median)
421 summary.psfStarDeltaE2Median = float(psfStarDeltaE2Median)
422 summary.psfStarDeltaE1Scatter = float(psfStarDeltaE1Scatter)
423 summary.psfStarDeltaE2Scatter = float(psfStarDeltaE2Scatter)
424 summary.psfStarDeltaSizeMedian = float(psfStarDeltaSizeMedian)
425 summary.psfStarDeltaSizeScatter = float(psfStarDeltaSizeScatter)
426 summary.psfStarScaledDeltaSizeScatter = float(psfStarScaledDeltaSizeScatter)
427
428 if image_mask is not None:
429 maxDistToNearestPsf = maximum_nearest_psf_distance(
430 image_mask,
431 psf_cat,
432 sampling=self.config.psfSampling,
433 bad_mask_bits=self.config.psfBadMaskPlanes
434 )
435 summary.maxDistToNearestPsf = float(maxDistToNearestPsf)
436

◆ update_wcs_stats()

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.update_wcs_stats ( self,
summary,
wcs,
bbox,
visitInfo )
Compute all summary-statistic fields that depend on the WCS model.

Parameters
----------
summary : `lsst.afw.image.ExposureSummaryStats`
    Summary object to update in-place.
wcs : `lsst.afw.geom.SkyWcs` or `None`
    Astrometric calibration model.  If `None`, all fields that depend
    on the WCS will be reset (generally to NaN).
bbox : `lsst.geom.Box2I`
    Bounding box of the image for which summary stats are being
    computed.
visitInfo : `lsst.afw.image.VisitInfo`
    Observation information used in together with ``wcs`` to compute
    the zenith distance.

Definition at line 437 of file computeExposureSummaryStats.py.

437 def update_wcs_stats(self, summary, wcs, bbox, visitInfo):
438 """Compute all summary-statistic fields that depend on the WCS model.
439
440 Parameters
441 ----------
442 summary : `lsst.afw.image.ExposureSummaryStats`
443 Summary object to update in-place.
444 wcs : `lsst.afw.geom.SkyWcs` or `None`
445 Astrometric calibration model. If `None`, all fields that depend
446 on the WCS will be reset (generally to NaN).
447 bbox : `lsst.geom.Box2I`
448 Bounding box of the image for which summary stats are being
449 computed.
450 visitInfo : `lsst.afw.image.VisitInfo`
451 Observation information used in together with ``wcs`` to compute
452 the zenith distance.
453 """
454 nan = float("nan")
455 summary.raCorners = [nan]*4
456 summary.decCorners = [nan]*4
457 summary.ra = nan
458 summary.dec = nan
459 summary.pixelScale = nan
460 summary.zenithDistance = nan
461
462 if wcs is None:
463 return
464
465 sph_pts = wcs.pixelToSky(geom.Box2D(bbox).getCorners())
466 summary.raCorners = [float(sph.getRa().asDegrees()) for sph in sph_pts]
467 summary.decCorners = [float(sph.getDec().asDegrees()) for sph in sph_pts]
468
469 sph_pt = wcs.pixelToSky(bbox.getCenter())
470 summary.ra = sph_pt.getRa().asDegrees()
471 summary.dec = sph_pt.getDec().asDegrees()
472 summary.pixelScale = wcs.getPixelScale(bbox.getCenter()).asArcseconds()
473
474 date = visitInfo.getDate()
475
476 if date.isValid():
477 # We compute the zenithDistance at the center of the detector
478 # rather than use the boresight value available via the visitInfo,
479 # because the zenithDistance may vary significantly over a large
480 # field of view.
481 observatory = visitInfo.getObservatory()
482 loc = EarthLocation(lat=observatory.getLatitude().asDegrees()*units.deg,
483 lon=observatory.getLongitude().asDegrees()*units.deg,
484 height=observatory.getElevation()*units.m)
485 obstime = Time(visitInfo.getDate().get(system=DateTime.MJD),
486 location=loc, format='mjd')
487 coord = SkyCoord(
488 summary.ra*units.degree,
489 summary.dec*units.degree,
490 obstime=obstime,
491 location=loc,
492 )
493 with warnings.catch_warnings():
494 warnings.simplefilter('ignore')
495 altaz = coord.transform_to(AltAz)
496
497 summary.zenithDistance = float(90.0 - altaz.alt.degree)
498
A floating-point coordinate rectangle geometry.
Definition Box.h:413

Member Data Documentation

◆ _DefaultName

str lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask._DefaultName = "computeExposureSummaryStats"
staticprotected

Definition at line 216 of file computeExposureSummaryStats.py.

◆ ConfigClass

lsst.pipe.tasks.computeExposureSummaryStats.ComputeExposureSummaryStatsTask.ConfigClass = ComputeExposureSummaryStatsConfig
static

Definition at line 215 of file computeExposureSummaryStats.py.


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