4040
4141class ComputeExposureSummaryStatsConfig (pexConfig .Config ):
4242 """Config for ComputeExposureSummaryTask"""
43+ doUpdatePsfModelStats = pexConfig .Field (
44+ dtype = bool ,
45+ default = True ,
46+ doc = "Update the grid-based PSF model maximum - minimum range metrics (psfTraceRadiusDelta & "
47+ "psfApFluxDelta)? Set to False if speed is of the essence." ,
48+ )
49+ doUpdateApCorrModelStats = pexConfig .Field (
50+ dtype = bool ,
51+ default = True ,
52+ doc = "Update the grid-based apCorr model maximum - minimum range metric (psfApCorrSigmaScaledDelta)? "
53+ "Set to False if speed is of the essence." ,
54+ )
55+ doUpdateMaxDistToNearestPsfStats = pexConfig .Field (
56+ dtype = bool ,
57+ default = True ,
58+ doc = "Update the grid-based maximum distance to the nearest PSF star PSF model metric "
59+ "(maxDistToNearestPsf)? Set to False if speed is of the essence." ,
60+ )
61+ doUpdateWcsStats = pexConfig .Field (
62+ dtype = bool ,
63+ default = True ,
64+ doc = "Update the wcs statistics? Set to False if speed is of the essence." ,
65+ )
66+ doUpdatePhotoCalibStats = pexConfig .Field (
67+ dtype = bool ,
68+ default = True ,
69+ doc = "Update the photoCalib statistics? Set to False if speed is of the essence." ,
70+ )
71+ doUpdateBackgroundStats = pexConfig .Field (
72+ dtype = bool ,
73+ default = True ,
74+ doc = "Update the background statistics? Set to False if speed is of the essence." ,
75+ )
76+ doUpdateMaskedImageStats = pexConfig .Field (
77+ dtype = bool ,
78+ default = True ,
79+ doc = "Update the masked image (i.e. skyNoise & meanVar) statistics? Set to False "
80+ "if speed is of the essence." ,
81+ )
82+ doUpdateEffectiveTimeStats = pexConfig .Field (
83+ dtype = bool ,
84+ default = True ,
85+ doc = "Update the effective time statistics? Set to False if speed is of the essence." ,
86+ )
4387 sigmaClip = pexConfig .Field (
4488 dtype = float ,
4589 doc = "Sigma for outlier rejection for sky noise." ,
@@ -158,13 +202,26 @@ class ComputeExposureSummaryStatsTask(pipeBase.Task):
158202 """Task to compute exposure summary statistics.
159203
160204 This task computes various quantities suitable for DPDD and other
161- downstream processing at the detector centers, including:
205+ downstream processing at the detector centers. The non-optionally
206+ computed quantities are:
162207 - expTime
163208 - psfSigma
164209 - psfArea
165210 - psfIxx
166211 - psfIyy
167212 - psfIxy
213+
214+ And these quantities which are computed from the stars in the detector:
215+ - psfStarDeltaE1Median
216+ - psfStarDeltaE2Median
217+ - psfStarDeltaE1Scatter
218+ - psfStarDeltaE2Scatter
219+ - psfStarDeltaSizeMedian
220+ - psfStarDeltaSizeScatter
221+ - psfStarScaledDeltaSizeScatter
222+
223+ The subsequently listed quatities are optionally computed via the
224+ "doUpdateX" config parameters (which all default to True):
168225 - ra
169226 - dec
170227 - pixelScale (arcsec/pixel)
@@ -178,15 +235,6 @@ class ComputeExposureSummaryStatsTask(pipeBase.Task):
178235 - astromOffsetMean
179236 - astromOffsetStd
180237
181- These additional quantities are computed from the stars in the detector:
182- - psfStarDeltaE1Median
183- - psfStarDeltaE2Median
184- - psfStarDeltaE1Scatter
185- - psfStarDeltaE2Scatter
186- - psfStarDeltaSizeMedian
187- - psfStarDeltaSizeScatter
188- - psfStarScaledDeltaSizeScatter
189-
190238 These quantities are computed based on the PSF model and image mask
191239 to assess the robustness of the PSF model across a given detector
192240 (against, e.g., extrapolation instability):
@@ -243,18 +291,23 @@ def run(self, exposure, sources, background):
243291 summary , psf , bbox , sources , image_mask = exposure .mask , image_ap_corr_map = exposure .apCorrMap
244292 )
245293
246- wcs = exposure .getWcs ()
247- visitInfo = exposure .getInfo ().getVisitInfo ()
248- self .update_wcs_stats (summary , wcs , bbox , visitInfo )
294+ if self .config .doUpdateWcsStats :
295+ wcs = exposure .getWcs ()
296+ visitInfo = exposure .getInfo ().getVisitInfo ()
297+ self .update_wcs_stats (summary , wcs , bbox , visitInfo )
249298
250- photoCalib = exposure .getPhotoCalib ()
251- self .update_photo_calib_stats (summary , photoCalib )
299+ if self .config .doUpdatePhotoCalibStats :
300+ photoCalib = exposure .getPhotoCalib ()
301+ self .update_photo_calib_stats (summary , photoCalib )
252302
253- self .update_background_stats (summary , background )
303+ if self .config .doUpdateBackgroundStats :
304+ self .update_background_stats (summary , background )
254305
255- self .update_masked_image_stats (summary , exposure .getMaskedImage ())
306+ if self .config .doUpdateMaskedImageStats :
307+ self .update_masked_image_stats (summary , exposure .getMaskedImage ())
256308
257- self .update_effective_time_stats (summary , exposure )
309+ if self .config .doUpdateEffectiveTimeStats :
310+ self .update_effective_time_stats (summary , exposure )
258311
259312 md = exposure .getMetadata ()
260313 if 'SFM_ASTROM_OFFSET_MEAN' in md :
@@ -331,33 +384,49 @@ def update_psf_stats(
331384 # 750bffe6620e565bda731add1509507f5c40c8bb/src/PsfFlux.cc#L112
332385 summary .psfArea = float (np .sum (im .array )/ np .sum (im .array ** 2. ))
333386
334- if image_mask is not None :
335- psfApRadius = max (self .config .minPsfApRadiusPix , 3.0 * summary .psfSigma )
336- self .log .debug ("Using radius of %.3f (pixels) for psfApFluxDelta metric" , psfApRadius )
337- psfTraceRadiusDelta , psfApFluxDelta = compute_psf_image_deltas (
338- image_mask ,
339- psf ,
340- sampling = self .config .psfGridSampling ,
341- ap_radius_pix = psfApRadius ,
342- bad_mask_bits = self .config .psfBadMaskPlanes
343- )
344- summary .psfTraceRadiusDelta = float (psfTraceRadiusDelta )
345- summary .psfApFluxDelta = float (psfApFluxDelta )
346- if image_ap_corr_map is not None :
347- if self .config .psfApCorrFieldName not in image_ap_corr_map .keys ():
348- self .log .warn (f"{ self .config .psfApCorrFieldName } not found in "
349- "image_ap_corr_map. Setting psfApCorrSigmaScaledDelta to NaN." )
350- psfApCorrSigmaScaledDelta = nan
351- else :
352- image_ap_corr_field = image_ap_corr_map [self .config .psfApCorrFieldName ]
353- psfApCorrSigmaScaledDelta = compute_ap_corr_sigma_scaled_delta (
354- image_mask ,
355- image_ap_corr_field ,
356- summary .psfSigma ,
357- sampling = self .config .psfGridSampling ,
358- bad_mask_bits = self .config .psfBadMaskPlanes ,
359- )
360- summary .psfApCorrSigmaScaledDelta = float (psfApCorrSigmaScaledDelta )
387+ if not self .config .doUpdatePsfModelStats :
388+ self .log .info ("Note: not computing grid-based PSF model maximum - minimum range metrics "
389+ "psfTraceRadiusDelta & psfApFluxDelta." )
390+ else :
391+ if image_mask is None :
392+ self .log .info ("Note: computation of grid-based PSF model maximum - minimum range metrics "
393+ "was requested, but required image_mask parameter was not provided." )
394+ else :
395+ psfApRadius = max (self .config .minPsfApRadiusPix , 3.0 * summary .psfSigma )
396+ self .log .debug ("Using radius of %.3f (pixels) for psfApFluxDelta metric." , psfApRadius )
397+
398+ psfTraceRadiusDelta , psfApFluxDelta = compute_psf_image_deltas (
399+ image_mask ,
400+ psf ,
401+ sampling = self .config .psfGridSampling ,
402+ ap_radius_pix = psfApRadius ,
403+ bad_mask_bits = self .config .psfBadMaskPlanes
404+ )
405+ summary .psfTraceRadiusDelta = float (psfTraceRadiusDelta )
406+ summary .psfApFluxDelta = float (psfApFluxDelta )
407+ if not self .config .doUpdateApCorrModelStats :
408+ self .log .info ("Note: not computing grid-based apCorr model maximum - minimum range metric "
409+ "psfApCorrSigmaScaledDelta." )
410+ else :
411+ if image_mask is None :
412+ self .log .info ("Note: computation of grid-based apCorr model maximum - minimum metric "
413+ "was requested, but required image_mask parameter was not provided." )
414+ else :
415+ if image_ap_corr_map is not None :
416+ if self .config .psfApCorrFieldName not in image_ap_corr_map .keys ():
417+ self .log .warn (f"{ self .config .psfApCorrFieldName } not found in "
418+ "image_ap_corr_map. Setting psfApCorrSigmaScaledDelta to NaN." )
419+ psfApCorrSigmaScaledDelta = nan
420+ else :
421+ image_ap_corr_field = image_ap_corr_map [self .config .psfApCorrFieldName ]
422+ psfApCorrSigmaScaledDelta = compute_ap_corr_sigma_scaled_delta (
423+ image_mask ,
424+ image_ap_corr_field ,
425+ summary .psfSigma ,
426+ sampling = self .config .psfGridSampling ,
427+ bad_mask_bits = self .config .psfBadMaskPlanes ,
428+ )
429+ summary .psfApCorrSigmaScaledDelta = float (psfApCorrSigmaScaledDelta )
361430
362431 if sources is None :
363432 # No sources are available (as in some tests and rare cases where
@@ -418,14 +487,20 @@ def update_psf_stats(
418487 summary .psfStarDeltaSizeScatter = float (psfStarDeltaSizeScatter )
419488 summary .psfStarScaledDeltaSizeScatter = float (psfStarScaledDeltaSizeScatter )
420489
421- if image_mask is not None :
422- maxDistToNearestPsf = maximum_nearest_psf_distance (
423- image_mask ,
424- psf_cat ,
425- sampling = self .config .psfSampling ,
426- bad_mask_bits = self .config .psfBadMaskPlanes
427- )
428- summary .maxDistToNearestPsf = float (maxDistToNearestPsf )
490+ if not self .config .doUpdateMaxDistToNearestPsfStats :
491+ self .log .info ("Note: not computing grid-based maxDistToNearestPsf PSF model metric." )
492+ else :
493+ if image_mask is None :
494+ self .log .info ("Note: computation of maxDistToNearestPsf PSF model metric was "
495+ "requested, but required image_mask parameter was not provided." )
496+ else :
497+ maxDistToNearestPsf = maximum_nearest_psf_distance (
498+ image_mask ,
499+ psf_cat ,
500+ sampling = self .config .psfSampling ,
501+ bad_mask_bits = self .config .psfBadMaskPlanes
502+ )
503+ summary .maxDistToNearestPsf = float (maxDistToNearestPsf )
429504
430505 def update_wcs_stats (self , summary , wcs , bbox , visitInfo ):
431506 """Compute all summary-statistic fields that depend on the WCS model.
0 commit comments