23 import astropy.units
as units
24 from astropy.time
import Time
25 from astropy.coordinates
import AltAz, SkyCoord, EarthLocation
35 __all__ = (
"ComputeExposureSummaryStatsTask",
"ComputeExposureSummaryStatsConfig")
39 """Config for ComputeExposureSummaryTask"""
40 sigmaClip = pexConfig.Field(
42 doc=
"Sigma for outlier rejection for sky noise.",
45 clipIter = pexConfig.Field(
47 doc=
"Number of iterations of outlier rejection for sky noise.",
50 badMaskPlanes = pexConfig.ListField(
52 doc=
"Mask planes that, if set, the associated pixel should not be included sky noise calculation.",
53 default=(
"NO_DATA",
"SUSPECT"),
58 """Task to compute exposure summary statistics.
60 This task computes various quantities suitable for DPDD and other
61 downstream processing at the detector centers, including:
79 ConfigClass = ComputeExposureSummaryStatsConfig
80 _DefaultName =
"computeExposureSummaryStats"
83 def run(self, exposure, sources, background):
84 """Measure exposure statistics from the exposure, sources, and background.
88 exposure : `lsst.afw.image.ExposureF`
89 sources : `lsst.afw.table.SourceCatalog`
90 background : `lsst.afw.math.BackgroundList`
94 summary : `lsst.afw.image.ExposureSummary`
96 self.log.
info(
"Measuring exposure statistics")
98 bbox = exposure.getBBox()
100 psf = exposure.getPsf()
102 shape = psf.computeShape(bbox.getCenter())
103 psfSigma = shape.getDeterminantRadius()
104 psfIxx = shape.getIxx()
105 psfIyy = shape.getIyy()
106 psfIxy = shape.getIxy()
107 im = psf.computeKernelImage(bbox.getCenter())
112 psfArea = np.sum(im.array)/np.sum(im.array**2.)
120 wcs = exposure.getWcs()
123 raCorners = [float(sph.getRa().asDegrees())
for sph
in sph_pts]
124 decCorners = [float(sph.getDec().asDegrees())
for sph
in sph_pts]
126 sph_pt = wcs.pixelToSky(bbox.getCenter())
127 ra = sph_pt.getRa().asDegrees()
128 decl = sph_pt.getDec().asDegrees()
130 raCorners = [float(np.nan)]*4
131 decCorners = [float(np.nan)]*4
135 photoCalib = exposure.getPhotoCalib()
136 if photoCalib
is not None:
137 zeroPoint = 2.5*np.log10(photoCalib.getInstFluxAtZeroMagnitude())
141 visitInfo = exposure.getInfo().getVisitInfo()
142 date = visitInfo.getDate()
148 observatory = visitInfo.getObservatory()
149 loc = EarthLocation(lat=observatory.getLatitude().asDegrees()*units.deg,
150 lon=observatory.getLongitude().asDegrees()*units.deg,
151 height=observatory.getElevation()*units.m)
152 obstime = Time(visitInfo.getDate().get(system=DateTime.MJD),
153 location=loc, format=
'mjd')
154 coord = SkyCoord(ra*units.degree, decl*units.degree, obstime=obstime, location=loc)
155 with warnings.catch_warnings():
156 warnings.simplefilter(
'ignore')
157 altaz = coord.transform_to(AltAz)
159 zenithDistance = 90.0 - altaz.alt.degree
161 zenithDistance = np.nan
163 if background
is not None:
164 bgStats = (bg[0].getStatsImage().getImage().array
165 for bg
in background)
166 skyBg = sum(np.median(bg[np.isfinite(bg)])
for bg
in bgStats)
171 statsCtrl.setNumSigmaClip(self.config.sigmaClip)
172 statsCtrl.setNumIter(self.config.clipIter)
173 statsCtrl.setAndMask(afwImage.Mask.getPlaneBitMask(self.config.badMaskPlanes))
174 statsCtrl.setNanSafe(
True)
178 skyNoise, _ = statObj.getResult(afwMath.STDEVCLIP)
181 exposure.getMaskedImage().getMask(),
182 afwMath.MEANCLIP, statsCtrl)
183 meanVar, _ = statObj.getResult(afwMath.MEANCLIP)
185 md = exposure.getMetadata()
186 if 'SFM_ASTROM_OFFSET_MEAN' in md:
187 astromOffsetMean = md[
'SFM_ASTROM_OFFSET_MEAN']
188 astromOffsetStd = md[
'SFM_ASTROM_OFFSET_STD']
190 astromOffsetMean = np.nan
191 astromOffsetStd = np.nan
194 psfArea=float(psfArea),
195 psfIxx=float(psfIxx),
196 psfIyy=float(psfIyy),
197 psfIxy=float(psfIxy),
200 zenithDistance=float(zenithDistance),
201 zeroPoint=float(zeroPoint),
203 skyNoise=float(skyNoise),
204 meanVar=float(meanVar),
206 decCorners=decCorners,
207 astromOffsetMean=astromOffsetMean,
208 astromOffsetStd=astromOffsetStd)
Pass parameters to a Statistics object.
A floating-point coordinate rectangle geometry.
def run(self, exposure, sources, background)
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
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)