Loading [MathJax]/extensions/tex2jax.js
LSST Applications 28.0.0,g1653933729+a8ce1bb630,g1a997c3884+a8ce1bb630,g28da252d5a+5bd70b7e6d,g2bbee38e9b+638fca75ac,g2bc492864f+638fca75ac,g3156d2b45e+07302053f8,g347aa1857d+638fca75ac,g35bb328faa+a8ce1bb630,g3a166c0a6a+638fca75ac,g3e281a1b8c+7bbb0b2507,g4005a62e65+17cd334064,g414038480c+5b5cd4fff3,g41af890bb2+4ffae9de63,g4e1a3235cc+0f1912dca3,g6249c6f860+3c3976f90c,g80478fca09+46aba80bd6,g82479be7b0+77990446f6,g858d7b2824+78ba4d1ce1,g89c8672015+f667a5183b,g9125e01d80+a8ce1bb630,ga5288a1d22+2a6264e9ca,gae0086650b+a8ce1bb630,gb58c049af0+d64f4d3760,gc22bb204ba+78ba4d1ce1,gc28159a63d+638fca75ac,gcf0d15dbbd+32ddb6096f,gd6b7c0dfd1+3e339405e9,gda3e153d99+78ba4d1ce1,gda6a2b7d83+32ddb6096f,gdaeeff99f8+1711a396fd,gdd5a9049c5+b18c39e5e3,ge2409df99d+a5e4577cdc,ge33fd446bb+78ba4d1ce1,ge79ae78c31+638fca75ac,gf0baf85859+64e8883e75,gf5289d68f6+e1b046a8d7,gfa443fc69c+91d9ed1ecf,gfda6b12a05+8419469a56
LSST Data Management Base Package
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
overscanAmpConfig.py
Go to the documentation of this file.
1import lsst.pex.config as pexConfig
2import hashlib
3
4from .overscan import SerialOverscanCorrectionTaskConfig, ParallelOverscanCorrectionTaskConfig
5
6
7__all__ = [
8 "OverscanAmpConfig",
9 "OverscanDetectorConfig",
10 "OverscanCameraConfig",
11]
12
13
14class OverscanAmpConfig(pexConfig.Config):
15 """Overscan configurations applicable to a single amplifier."""
16 doSerialOverscan = pexConfig.Field(
17 dtype=bool,
18 doc="Do serial overscan subtraction?",
19 default=True,
20 )
21 serialOverscanConfig = pexConfig.ConfigField(
22 dtype=SerialOverscanCorrectionTaskConfig,
23 doc="Serial overscan configuration.",
24 )
25 doParallelOverscanCrosstalk = pexConfig.Field(
26 dtype=bool,
27 doc="Apply crosstalk correction in parallel overscan region?",
28 default=True,
29 )
30 doParallelOverscan = pexConfig.Field(
31 dtype=bool,
32 doc="Do parallel overscan subtraction?",
33 default=True,
34 )
35 parallelOverscanConfig = pexConfig.ConfigField(
36 dtype=ParallelOverscanCorrectionTaskConfig,
37 doc="Parallel overscan configuration.",
38 )
39 saturation = pexConfig.Field(
40 dtype=float,
41 doc="The saturation level to use to override any detector/calibration product value "
42 "(ignored if NaN). Units are ADU.",
43 default=float("NaN"),
44 )
45 suspectLevel = pexConfig.Field(
46 dtype=float,
47 doc="The ``suspect`` level to use to override any detector/calibration product value "
48 "(ignored if NaN). Units are ADU.",
49 default=float("NaN"),
50 )
51 gain = pexConfig.Field(
52 dtype=float,
53 doc="The gain to use to override any calibration product value (ignored if NaN). "
54 "Units are e-/ADU.",
55 default=float("NaN"),
56 )
57
58 def setDefaults(self):
59 super().setDefaults()
60
61 self.serialOverscanConfig.fitType = "MEDIAN_PER_ROW"
62 self.serialOverscanConfig.leadingToSkip = 3
63 self.serialOverscanConfig.trailingToSkip = 3
64 self.serialOverscanConfig.overscanIsInt = False
65 self.parallelOverscanConfig.fitType = "MEDIAN_PER_ROW"
66 self.parallelOverscanConfig.leadingToSkip = 3
67 self.parallelOverscanConfig.trailingToSkip = 3
68 self.parallelOverscanConfig.overscanIsInt = False
69 # We expect the parallel overscan to not deviate much
70 # after serial overscan subtraction and crosstalk correction.
71 self.parallelOverscanConfig.maxDeviation = 100.0
72
73 @property
74 def _stringForHash(self):
75 """Turn this config into a simple string for hashing.
76
77 Only essential data for tracking is returned.
78
79 Returns
80 -------
81 stringForHash : `str`
82 """
83 stringForHash = (f"doSerial={self.doSerialOverscan} "
84 f"serialFitType={self.serialOverscanConfig.fitType} "
85 f"doParallelCrosstalk={self.doParallelOverscanCrosstalk} "
86 f"doParallel={self.doParallelOverscan} "
87 f"parallelFitType={self.parallelOverscanConfig.fitType}")
88 return stringForHash
89
90
91class OverscanDetectorConfig(pexConfig.Config):
92 """Overscan configurations applicable to multiple amplifiers in
93 a single detector.
94 """
95 ampRules = pexConfig.ConfigDictField(
96 doc="Amplifier level rules for overscan, keyed by amp name.",
97 keytype=str,
98 itemtype=OverscanAmpConfig,
99 default={},
100 )
101 defaultAmpConfig = pexConfig.ConfigField(
102 dtype=OverscanAmpConfig,
103 doc="Default configuration for amplifiers.",
104 )
105 integerDitherMode = pexConfig.ChoiceField(
106 dtype=str,
107 doc="Dithering mode to cancel integerization of counts.",
108 default="SYMMETRIC",
109 allowed={
110 "POSITIVE": "Dithering is done with a uniform random in the range [0, 1).",
111 "NEGATIVE": "Dithering is done with a uniform random in the range [-1, 0).",
112 "SYMMETRIC": "Dithering is done with a uniform random in the range [-0.5, 0.5).",
113 "NONE": "No dithering is performed.",
114 },
115 )
116
117 @property
119 """Check if any of the amp configs have doSerialOverscan.
120
121 Returns
122 -------
123 doAnySerialOverscan : `bool`
124 """
125 if self.defaultAmpConfig.doSerialOverscan:
126 return True
127
128 for _, ampRule in self.ampRules.items():
129 if ampRule.doSerialOverscan:
130 return True
131
132 return False
133
134 @property
136 """Check if any of the amp configs have doParallelOverscan.
137
138 Returns
139 -------
140 doAnyParallelOverscan : `bool`
141 """
142 if self.defaultAmpConfig.doParallelOverscan:
143 return True
144
145 for _, ampRule in self.ampRules.items():
146 if ampRule.doParallelOverscan:
147 return True
148
149 return False
150
151 @property
153 """Check if any of the amp configs have doParallelOverscanCrosstalk.
154
155 Returns
156 -------
157 doAnyParallelOverscanCrosstalk : `bool`
158 """
159 if self.defaultAmpConfig.doParallelOverscanCrosstalk:
160 return True
161
162 for _, ampRule in self.ampRules.items():
163 if ampRule.doParallelOverscanCrosstalk:
164 return True
165
166 return False
167
168 def getOverscanAmpConfig(self, amplifier):
169 """Get the OverscanAmpConfig for a specific amplifier.
170
171 Parameters
172 ----------
173 amplifier : `lsst.afw.cameraGeom.Amplifier`
174
175 Returns
176 -------
177 overscanAmpConfig : `lsst.ip.isr.overscanAmpConfig.OverscanAmpConfig`
178 """
179 ampKey = amplifier.getName()
180
181 if ampKey in self.ampRules.keys():
182 overscanAmpConfig = self.ampRules[ampKey]
183 else:
184 overscanAmpConfig = self.defaultAmpConfig
185
186 return overscanAmpConfig
187
188 @property
189 def _stringForHash(self):
190 """Turn this config into a simple string for hashing.
191
192 Only the default and amps that are different than the
193 default are used in the string representation.
194
195 Returns
196 -------
197 stringForHash : `str`
198 """
199 defaultString = self.defaultAmpConfig._stringForHash
200
201 stringForHash = f"default: {defaultString}"
202 for ampName in self.ampRules:
203 ampString = self.ampRules[ampName]._stringForHash
204 if ampString != defaultString:
205 stringForHash += f" {ampName}: {ampString}"
206
207 return stringForHash
208
209 @property
210 def md5(self):
211 """Compute the MD5 hash of this config (detector + amps).
212
213 This can be used to ensure overscan configs are consistent.
214
215 Returns
216 -------
217 md5Hash : `str`
218 """
219 return hashlib.md5(self._stringForHash.encode("UTF-8")).hexdigest()
220
221
222class OverscanCameraConfig(pexConfig.Config):
223 """Overscan configurations applicable to multiple detectors in
224 a single camera.
225 """
226 detectorRules = pexConfig.ConfigDictField(
227 doc="Detector level rules for overscan",
228 keytype=str,
229 itemtype=OverscanDetectorConfig,
230 default={},
231 )
232 defaultDetectorConfig = pexConfig.ConfigField(
233 dtype=OverscanDetectorConfig,
234 doc="Default configuration for detectors.",
235 )
236 detectorRuleKeyType = pexConfig.ChoiceField(
237 doc="Detector rule key type.",
238 dtype=str,
239 default="NAME",
240 allowed={
241 "NAME": "DetectorRules has a key that is the detector name.",
242 "SERIAL": "DetectorRules has a key that is the detector serial number.",
243 "ID": "DetectorRules has a key that is the detector id number.",
244 },
245 )
246
247 @property
249 """Check if any of the detector/amp configs have doSerialOverscan.
250
251 Returns
252 -------
253 doAnySerialOverscan : `bool`
254 """
255 if self.defaultDetectorConfig.doAnySerialOverscan:
256 return True
257
258 for _, detectorRule in self.detectorRules.items():
259 if detectorRule.doAnySerialOverscan:
260 return True
261
262 return False
263
264 @property
266 """Check if any of the detector/amp configs have
267 doParallelOverscan.
268
269 Returns
270 -------
271 doAnyParallelOverscan : `bool`
272 """
273
274 if self.defaultDetectorConfig.doAnyParallelOverscan:
275 return True
276
277 for _, detectorRule in self.detectorRules.items():
278 if detectorRule.doAnyParallelOverscan:
279 return True
280
281 return False
282
283 @property
285 """Check if any of the detector/amp configs have
286 doParallelOverscanCrosstalk.
287
288 Returns
289 -------
290 doAnyParallelOverscanCrosstalk : `bool`
291 """
292
293 if self.defaultDetectorConfig.doAnyParallelOverscanCrosstalk:
294 return True
295
296 for _, detectorRule in self.detectorRules.items():
297 if detectorRule.doAnyParallelOverscanCrosstalk:
298 return True
299
300 return False
301
302 def getOverscanDetectorConfig(self, detector):
303 """Get the OverscanDetectorConfig for a specific detector.
304
305 Parameters
306 ----------
307 detector : `lsst.afw.cameraGeom.Detector`
308
309 Returns
310 -------
311 overscanDetectorConfig : `OverscanDetectorConfig`
312 """
313 match self.detectorRuleKeyType:
314 case "NAME":
315 key = detector.getName()
316 case "SERIAL":
317 key = detector.getSerial()
318 case "ID":
319 key = str(detector.getId())
320
321 if key in self.detectorRules.keys():
322 overscanDetectorConfig = self.detectorRules[key]
323 else:
324 overscanDetectorConfig = self.defaultDetectorConfig
325
326 return overscanDetectorConfig
std::vector< SchemaItem< Flag > > * items