LSST Applications 26.0.0,g0265f82a02+6660c170cc,g07994bdeae+30b05a742e,g0a0026dc87+17526d298f,g0a60f58ba1+17526d298f,g0e4bf8285c+96dd2c2ea9,g0ecae5effc+c266a536c8,g1e7d6db67d+6f7cb1f4bb,g26482f50c6+6346c0633c,g2bbee38e9b+6660c170cc,g2cc88a2952+0a4e78cd49,g3273194fdb+f6908454ef,g337abbeb29+6660c170cc,g337c41fc51+9a8f8f0815,g37c6e7c3d5+7bbafe9d37,g44018dc512+6660c170cc,g4a941329ef+4f7594a38e,g4c90b7bd52+5145c320d2,g58be5f913a+bea990ba40,g635b316a6c+8d6b3a3e56,g67924a670a+bfead8c487,g6ae5381d9b+81bc2a20b4,g93c4d6e787+26b17396bd,g98cecbdb62+ed2cb6d659,g98ffbb4407+81bc2a20b4,g9ddcbc5298+7f7571301f,ga1e77700b3+99e9273977,gae46bcf261+6660c170cc,gb2715bf1a1+17526d298f,gc86a011abf+17526d298f,gcf0d15dbbd+96dd2c2ea9,gdaeeff99f8+0d8dbea60f,gdb4ec4c597+6660c170cc,ge23793e450+96dd2c2ea9,gf041782ebf+171108ac67
LSST Data Management Base Package
Loading...
Searching...
No Matches
_exposureSummaryStats.py
Go to the documentation of this file.
1# This file is part of afw.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21from __future__ import annotations
22
23import dataclasses
24from typing import TYPE_CHECKING
25import yaml
26import warnings
27
28from ..typehandling import Storable, StorableHelperFactory
29
30if TYPE_CHECKING:
31 from ..table import BaseRecord, Schema
32
33__all__ = ("ExposureSummaryStats", )
34
35
37 return [float("nan")] * 4
38
39
40@dataclasses.dataclass
42 _persistence_name = 'ExposureSummaryStats'
43
44 _factory = StorableHelperFactory(__name__, _persistence_name)
45
46 version: int = 0
47
48 psfSigma: float = float('nan')
49 """PSF determinant radius (pixels)."""
50
51 psfArea: float = float('nan')
52 """PSF effective area (pixels**2)."""
53
54 psfIxx: float = float('nan')
55 """PSF shape Ixx (pixels**2)."""
56
57 psfIyy: float = float('nan')
58 """PSF shape Iyy (pixels**2)."""
59
60 psfIxy: float = float('nan')
61 """PSF shape Ixy (pixels**2)."""
62
63 ra: float = float('nan')
64 """Bounding box center Right Ascension (degrees)."""
65
66 dec: float = float('nan')
67 """Bounding box center Declination (degrees)."""
68
69 zenithDistance: float = float('nan')
70 """Bounding box center zenith distance (degrees)."""
71
72 zeroPoint: float = float('nan')
73 """Mean zeropoint in detector (mag)."""
74
75 skyBg: float = float('nan')
76 """Average sky background (ADU)."""
77
78 skyNoise: float = float('nan')
79 """Average sky noise (ADU)."""
80
81 meanVar: float = float('nan')
82 """Mean variance of the weight plane (ADU**2)."""
83
84 raCorners: list[float] = dataclasses.field(default_factory=_default_corners)
85 """Right Ascension of bounding box corners (degrees)."""
86
87 decCorners: list[float] = dataclasses.field(default_factory=_default_corners)
88 """Declination of bounding box corners (degrees)."""
89
90 astromOffsetMean: float = float('nan')
91 """Astrometry match offset mean."""
92
93 astromOffsetStd: float = float('nan')
94 """Astrometry match offset stddev."""
95
96 nPsfStar: int = 0
97 """Number of stars used for psf model."""
98
99 psfStarDeltaE1Median: float = float('nan')
100 """Psf stars median E1 residual (starE1 - psfE1)."""
101
102 psfStarDeltaE2Median: float = float('nan')
103 """Psf stars median E2 residual (starE2 - psfE2)."""
104
105 psfStarDeltaE1Scatter: float = float('nan')
106 """Psf stars MAD E1 scatter (starE1 - psfE1)."""
107
108 psfStarDeltaE2Scatter: float = float('nan')
109 """Psf stars MAD E2 scatter (starE2 - psfE2)."""
110
111 psfStarDeltaSizeMedian: float = float('nan')
112 """Psf stars median size residual (starSize - psfSize)."""
113
114 psfStarDeltaSizeScatter: float = float('nan')
115 """Psf stars MAD size scatter (starSize - psfSize)."""
116
117 psfStarScaledDeltaSizeScatter: float = float('nan')
118 """Psf stars MAD size scatter scaled by psfSize**2."""
119
120 psfTraceRadiusDelta: float = float('nan')
121 """Delta (max - min) of the model psf trace radius values evaluated on a
122 grid of unmasked pixels (pixels).
123 """
124
125 maxDistToNearestPsf: float = float('nan')
126 """Maximum distance of an unmasked pixel to its nearest model psf star
127 (pixels).
128 """
129
130 def __post_init__(self):
131 Storable.__init__(self)
132
133 def isPersistable(self):
134 return True
135
137 return self._persistence_name
138
140 return __name__
141
142 def _write(self):
143 return yaml.dump(dataclasses.asdict(self), encoding='utf-8')
144
145 @staticmethod
146 def _read(bytes):
147 yamlDict = yaml.load(bytes, Loader=yaml.SafeLoader)
148 # For forwards compatibility, filter out any fields that are
149 # not defined in the dataclass.
150 droppedFields = []
151 for _field in list(yamlDict.keys()):
152 if _field not in ExposureSummaryStats.__dataclass_fields__:
153 droppedFields.append(_field)
154 yamlDict.pop(_field)
155 if len(droppedFields) > 0:
156 droppedFieldString = ", ".join([str(f) for f in droppedFields])
157 plural = "s" if len(droppedFields) != 1 else ""
158 them = "them" if len(droppedFields) > 1 else "it"
159 warnings.warn(
160 f"Summary field{plural} [{droppedFieldString}] not recognized by this software version;"
161 f" ignoring {them}.",
162 FutureWarning,
163 stacklevel=2,
164 )
165 return ExposureSummaryStats(**yamlDict)
166
167 @classmethod
168 def update_schema(cls, schema: Schema) -> None:
169 """Update an schema to includes for all summary statistic fields.
170
171 Parameters
172 -------
173 schema : `lsst.afw.table.Schema`
174 Schema to add which fields will be added.
175 """
176 schema.addField(
177 "psfSigma",
178 type="F",
179 doc="PSF model second-moments determinant radius (center of chip) (pixel)",
180 )
181 schema.addField(
182 "psfArea",
183 type="F",
184 doc="PSF model effective area (center of chip) (pixel**2)",
185 )
186 schema.addField(
187 "psfIxx", type="F", doc="PSF model Ixx (center of chip) (pixel**2)"
188 )
189 schema.addField(
190 "psfIyy", type="F", doc="PSF model Iyy (center of chip) (pixel**2)"
191 )
192 schema.addField(
193 "psfIxy", type="F", doc="PSF model Ixy (center of chip) (pixel**2)"
194 )
195 schema.addField(
196 "raCorners",
197 type="ArrayD",
198 size=4,
199 doc="Right Ascension of bounding box corners (degrees)",
200 )
201 schema.addField(
202 "decCorners",
203 type="ArrayD",
204 size=4,
205 doc="Declination of bounding box corners (degrees)",
206 )
207 schema.addField(
208 "ra", type="D", doc="Right Ascension of bounding box center (degrees)"
209 )
210 schema.addField(
211 "dec", type="D", doc="Declination of bounding box center (degrees)"
212 )
213 schema.addField(
214 "zenithDistance",
215 type="F",
216 doc="Zenith distance of bounding box center (degrees)",
217 )
218 schema.addField("zeroPoint", type="F", doc="Mean zeropoint in detector (mag)")
219 schema.addField("skyBg", type="F", doc="Average sky background (ADU)")
220 schema.addField("skyNoise", type="F", doc="Average sky noise (ADU)")
221 schema.addField(
222 "meanVar", type="F", doc="Mean variance of the weight plane (ADU**2)"
223 )
224 schema.addField(
225 "astromOffsetMean",
226 type="F",
227 doc="Mean offset of astrometric calibration matches (arcsec)",
228 )
229 schema.addField(
230 "astromOffsetStd",
231 type="F",
232 doc="Standard deviation of offsets of astrometric calibration matches (arcsec)",
233 )
234 schema.addField("nPsfStar", type="I", doc="Number of stars used for PSF model")
235 schema.addField(
236 "psfStarDeltaE1Median",
237 type="F",
238 doc="Median E1 residual (starE1 - psfE1) for psf stars",
239 )
240 schema.addField(
241 "psfStarDeltaE2Median",
242 type="F",
243 doc="Median E2 residual (starE2 - psfE2) for psf stars",
244 )
245 schema.addField(
246 "psfStarDeltaE1Scatter",
247 type="F",
248 doc="Scatter (via MAD) of E1 residual (starE1 - psfE1) for psf stars",
249 )
250 schema.addField(
251 "psfStarDeltaE2Scatter",
252 type="F",
253 doc="Scatter (via MAD) of E2 residual (starE2 - psfE2) for psf stars",
254 )
255 schema.addField(
256 "psfStarDeltaSizeMedian",
257 type="F",
258 doc="Median size residual (starSize - psfSize) for psf stars (pixel)",
259 )
260 schema.addField(
261 "psfStarDeltaSizeScatter",
262 type="F",
263 doc="Scatter (via MAD) of size residual (starSize - psfSize) for psf stars (pixel)",
264 )
265 schema.addField(
266 "psfStarScaledDeltaSizeScatter",
267 type="F",
268 doc="Scatter (via MAD) of size residual scaled by median size squared",
269 )
270 schema.addField(
271 "psfTraceRadiusDelta",
272 type="F",
273 doc="Delta (max - min) of the model psf trace radius values evaluated on a grid of "
274 "unmasked pixels (pixel).",
275 )
276 schema.addField(
277 "maxDistToNearestPsf",
278 type="F",
279 doc="Maximum distance of an unmasked pixel to its nearest model psf star (pixel).",
280 )
281
282 def update_record(self, record: BaseRecord) -> None:
283 """Write summary-statistic columns into a record.
284
285 Parameters
286 ----------
288 Record to update. This is expected to frequently be an
289 `ExposureRecord` instance (with higher-level code adding other
290 columns and objects), but this method can work with any record
291 type.
292 """
293 for field in dataclasses.fields(self):
294 value = getattr(self, field.name)
295 if field.name == "version":
296 continue
297 elif field.type.startswith("list"):
298 record[field.name][:] = value
299 else:
300 record[field.name] = value
301
302 @classmethod
303 def from_record(cls, record: BaseRecord) -> ExposureSummaryStats:
304 """Read summary-statistic columns from a record into ``self``.
305
306 Parameters
307 ----------
309 Record to read from. This is expected to frequently be an
310 `ExposureRecord` instance (with higher-level code adding other
311 columns and objects), but this method can work with any record
312 type, ignoring any attributes or columns it doesn't recognize.
313
314 Returns
315 -------
316 summary : `ExposureSummaryStats`
317 Summary statistics object created from the given record.
318 """
319 return cls(
320 **{
321 field.name: (
322 record[field.name] if not field.type.startswith("list")
323 else [float(v) for v in record[field.name]]
324 )
325 for field in dataclasses.fields(cls)
326 if field.name != "version"
327 }
328 )
ExposureSummaryStats from_record(cls, BaseRecord record)
Base class for all records.
Definition BaseRecord.h:31
Defines the fields and offsets for a table.
Definition Schema.h:51
virtual bool isPersistable() const noexcept
Return true if this particular object can be persisted using afw::table::io.
Interface supporting iteration over heterogenous containers.
Definition Storable.h:58
daf::base::PropertyList * list
Definition fits.cc:928