LSST Applications g04e9c324dd+8c5ae1fdc5,g134cb467dc+1b3060144d,g18429d2f64+f642bf4753,g199a45376c+0ba108daf9,g1fd858c14a+2dcf163641,g262e1987ae+7b8c96d2ca,g29ae962dfc+3bd6ecb08a,g2cef7863aa+aef1011c0b,g35bb328faa+8c5ae1fdc5,g3fd5ace14f+53e1a9e7c5,g4595892280+fef73a337f,g47891489e3+2efcf17695,g4d44eb3520+642b70b07e,g53246c7159+8c5ae1fdc5,g67b6fd64d1+2efcf17695,g67fd3c3899+b70e05ef52,g74acd417e5+317eb4c7d4,g786e29fd12+668abc6043,g87389fa792+8856018cbb,g89139ef638+2efcf17695,g8d7436a09f+3be3c13596,g8ea07a8fe4+9f5ccc88ac,g90f42f885a+a4e7b16d9b,g97be763408+ad77d7208f,g9dd6db0277+b70e05ef52,ga681d05dcb+a3f46e7fff,gabf8522325+735880ea63,gac2eed3f23+2efcf17695,gb89ab40317+2efcf17695,gbf99507273+8c5ae1fdc5,gd8ff7fe66e+b70e05ef52,gdab6d2f7ff+317eb4c7d4,gdc713202bf+b70e05ef52,gdfd2d52018+b10e285e0f,ge365c994fd+310e8507c4,ge410e46f29+2efcf17695,geaed405ab2+562b3308c0,gffca2db377+8c5ae1fdc5,w.2025.35
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.ip.isr.defects.Defects Class Reference
Inheritance diagram for lsst.ip.isr.defects.Defects:
lsst.ip.isr.calibType.IsrCalib

Public Member Functions

 __init__ (self, defectList=None, metadata=None, *, normalize_on_init=True, **kwargs)
 
 __len__ (self)
 
 __getitem__ (self, index)
 
 __setitem__ (self, index, value)
 
 __iter__ (self)
 
 __delitem__ (self, index)
 
 __eq__ (self, other)
 
 __str__ (self)
 
 bulk_update (self)
 
 append (self, value)
 
 insert (self, index, value)
 
 copy (self)
 
 transpose (self)
 
 maskPixels (self, mask, maskName="BAD")
 
 updateCounters (self, columns=None, hot=None, cold=None)
 
 toFitsRegionTable (self)
 
 fromDict (cls, dictionary)
 
 toDict (self)
 
 toTable (self)
 
 fromTable (cls, tableList, normalize_on_init=True)
 
 readLsstDefectsFile (cls, filename, normalize_on_init=False)
 
 fromFootprintList (cls, fpList)
 
 fromMask (cls, mask, maskName)
 
 requiredAttributes (self)
 
 requiredAttributes (self, value)
 
 metadata (self)
 
 getMetadata (self)
 
 setMetadata (self, metadata)
 
 updateMetadata (self, camera=None, detector=None, filterName=None, setCalibId=False, setCalibInfo=False, setDate=False, **kwargs)
 
 updateMetadataFromExposures (self, exposures)
 
 calibInfoFromDict (self, dictionary)
 
 determineCalibClass (cls, metadata, message)
 
 readText (cls, filename, **kwargs)
 
 writeText (self, filename, format="auto")
 
 readFits (cls, filename, **kwargs)
 
 writeFits (self, filename)
 
 fromDetector (self, detector)
 
 validate (self, other=None)
 
 apply (self, target)
 

Public Attributes

 requiredAttributes = set(["_OBSTYPE", "_SCHEMA", "_VERSION"])
 
 log = log if log else logging.getLogger(__name__)
 

Protected Member Functions

 _check_value (self, value)
 
 _normalize (self)
 

Static Protected Member Functions

 _get_values (values, n=1)
 

Protected Attributes

list _defects = []
 
bool _bulk_update = True
 
 _instrument = None
 
 _raftName = None
 
 _slotName = None
 
 _detectorName = None
 
 _detectorSerial = None
 
 _detectorId = None
 
 _filter = None
 
str _calibId = None
 
 _seqfile = None
 
 _seqname = None
 
 _seqcksum = None
 
 _metadata = PropertyList()
 
 _requiredAttributes
 

Static Protected Attributes

str _OBSTYPE = "generic"
 
str _SCHEMA = "NO SCHEMA"
 
int _VERSION = 0
 

Detailed Description

Calibration handler for collections of `lsst.meas.algorithms.Defect`.

Parameters
----------
defectList : iterable, optional
    Collections of defects to apply to the image. Can be an iterable of
    `lsst.meas.algorithms.Defect` or `lsst.geom.BoxI`.
metadata : `lsst.daf.base.PropertyList`, optional
    Metadata to associate with the defects.  Will be copied and
    overwrite existing metadata, if any. If not supplied the existing
    metadata will be reset.
normalize_on_init : `bool`
    If True, normalization is applied to the defects in ``defectList`` to
    remove duplicates, eliminate overlaps, etc.

Notes
-----
Defects are stored within this collection in a "reduced" or "normalized"
form: rather than simply storing the bounding boxes which are added to the
collection, we eliminate overlaps and duplicates. This normalization
procedure may introduce overhead when adding many new defects; it may be
temporarily disabled using the `Defects.bulk_update` context manager if
necessary.

The attributes stored in this calibration are:

_defects : `list` [`lsst.meas.algorithms.Defect`]
    The collection of Defect objects.
The calibration type used for ingest.

Definition at line 47 of file defects.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.ip.isr.defects.Defects.__init__ ( self,
defectList = None,
metadata = None,
* ,
normalize_on_init = True,
** kwargs )

Definition at line 83 of file defects.py.

83 def __init__(self, defectList=None, metadata=None, *, normalize_on_init=True, **kwargs):
84 self._defects = []
85
86 if defectList is not None:
87 self._bulk_update = True
88 for d in defectList:
89 self.append(d)
90 self._bulk_update = False
91
92 if normalize_on_init:
93 self._normalize()
94
95 super().__init__(**kwargs)
96 self.requiredAttributes.update(['_defects'])
97

Member Function Documentation

◆ __delitem__()

lsst.ip.isr.defects.Defects.__delitem__ ( self,
index )

Definition at line 145 of file defects.py.

145 def __delitem__(self, index):
146 del self._defects[index]
147

◆ __eq__()

lsst.ip.isr.defects.Defects.__eq__ ( self,
other )
Compare if two `Defects` are equal.

Two `Defects` are equal if their bounding boxes are equal and in
the same order.  Metadata content is ignored.

Definition at line 148 of file defects.py.

148 def __eq__(self, other):
149 """Compare if two `Defects` are equal.
150
151 Two `Defects` are equal if their bounding boxes are equal and in
152 the same order. Metadata content is ignored.
153 """
154 super().__eq__(other)
155
156 if not isinstance(other, self.__class__):
157 return False
158
159 # checking the bboxes with zip() only works if same length
160 if len(self) != len(other):
161 return False
162
163 # Assume equal if bounding boxes are equal
164 for d1, d2 in zip(self, other):
165 if d1.getBBox() != d2.getBBox():
166 return False
167
168 return True
169

◆ __getitem__()

lsst.ip.isr.defects.Defects.__getitem__ ( self,
index )

Definition at line 133 of file defects.py.

133 def __getitem__(self, index):
134 return self._defects[index]
135

◆ __iter__()

lsst.ip.isr.defects.Defects.__iter__ ( self)

Definition at line 142 of file defects.py.

142 def __iter__(self):
143 return iter(self._defects)
144

◆ __len__()

lsst.ip.isr.defects.Defects.__len__ ( self)

Definition at line 130 of file defects.py.

130 def __len__(self):
131 return len(self._defects)
132

◆ __setitem__()

lsst.ip.isr.defects.Defects.__setitem__ ( self,
index,
value )
Can be given a `~lsst.meas.algorithms.Defect` or a `lsst.geom.BoxI`

Definition at line 136 of file defects.py.

136 def __setitem__(self, index, value):
137 """Can be given a `~lsst.meas.algorithms.Defect` or a `lsst.geom.BoxI`
138 """
139 self._defects[index] = self._check_value(value)
140 self._normalize()
141

◆ __str__()

lsst.ip.isr.defects.Defects.__str__ ( self)

Definition at line 170 of file defects.py.

170 def __str__(self):
171 baseStr = super().__str__()
172 return baseStr + ",".join(str(d.getBBox()) for d in self) + ")"
173

◆ _check_value()

lsst.ip.isr.defects.Defects._check_value ( self,
value )
protected
Check that the supplied value is a `~lsst.meas.algorithms.Defect`
or can be converted to one.

Parameters
----------
value : `object`
    Value to check.

Returns
-------
new : `~lsst.meas.algorithms.Defect`
    Either the supplied value or a new object derived from it.

Raises
------
ValueError
    Raised if the supplied value can not be converted to
    `~lsst.meas.algorithms.Defect`

Definition at line 98 of file defects.py.

98 def _check_value(self, value):
99 """Check that the supplied value is a `~lsst.meas.algorithms.Defect`
100 or can be converted to one.
101
102 Parameters
103 ----------
104 value : `object`
105 Value to check.
106
107 Returns
108 -------
109 new : `~lsst.meas.algorithms.Defect`
110 Either the supplied value or a new object derived from it.
111
112 Raises
113 ------
114 ValueError
115 Raised if the supplied value can not be converted to
116 `~lsst.meas.algorithms.Defect`
117 """
118 if isinstance(value, Defect):
119 pass
120 elif isinstance(value, lsst.geom.BoxI):
121 value = Defect(value)
122 elif isinstance(value, lsst.geom.PointI):
123 value = Defect(lsst.geom.Box2I(value, lsst.geom.Extent2I(1, 1)))
124 elif isinstance(value, lsst.afw.image.DefectBase):
125 value = Defect(value.getBBox())
126 else:
127 raise ValueError(f"Defects must be of type Defect, BoxI, or PointI, not '{value!r}'")
128 return value
129
Encapsulate information about a bad portion of a detector.
Definition Defect.h:39
An integer coordinate rectangle.
Definition Box.h:55

◆ _get_values()

lsst.ip.isr.defects.Defects._get_values ( values,
n = 1 )
staticprotected
Retrieve N values from the supplied values.

Parameters
----------
values : `numbers.Number` or `list` or `np.array`
    Input values.
n : `int`
    Number of values to retrieve.

Returns
-------
vals : `list` or `np.array` or `numbers.Number`
    Single value from supplied list if ``n`` is 1, or `list`
    containing first ``n`` values from supplied values.

Notes
-----
Some supplied tables have vectors in some columns that can also
be scalars.  This method can be used to get the first number as
a scalar or the first N items from a vector as a vector.

Definition at line 486 of file defects.py.

486 def _get_values(values, n=1):
487 """Retrieve N values from the supplied values.
488
489 Parameters
490 ----------
491 values : `numbers.Number` or `list` or `np.array`
492 Input values.
493 n : `int`
494 Number of values to retrieve.
495
496 Returns
497 -------
498 vals : `list` or `np.array` or `numbers.Number`
499 Single value from supplied list if ``n`` is 1, or `list`
500 containing first ``n`` values from supplied values.
501
502 Notes
503 -----
504 Some supplied tables have vectors in some columns that can also
505 be scalars. This method can be used to get the first number as
506 a scalar or the first N items from a vector as a vector.
507 """
508 if n == 1:
509 if isinstance(values, numbers.Number):
510 return values
511 else:
512 return values[0]
513
514 return values[:n]
515

◆ _normalize()

lsst.ip.isr.defects.Defects._normalize ( self)
protected
Recalculate defect bounding boxes for efficiency.

Notes
-----
Ideally, this would generate the provably-minimal set of bounding
boxes necessary to represent the defects. At present, however, that
doesn't happen: see DM-24781. In the cases of substantial overlaps or
duplication, though, this will produce a much reduced set.

Definition at line 174 of file defects.py.

174 def _normalize(self):
175 """Recalculate defect bounding boxes for efficiency.
176
177 Notes
178 -----
179 Ideally, this would generate the provably-minimal set of bounding
180 boxes necessary to represent the defects. At present, however, that
181 doesn't happen: see DM-24781. In the cases of substantial overlaps or
182 duplication, though, this will produce a much reduced set.
183 """
184 # In bulk-update mode, normalization is a no-op.
185 if self._bulk_update:
186 return
187
188 # If we have no defects, there is nothing to normalize.
189 if len(self) == 0:
190 return
191
192 # work out the minimum and maximum bounds from all defect regions.
193 minX, minY, maxX, maxY = float('inf'), float('inf'), float('-inf'), float('-inf')
194 for defect in self:
195 bbox = defect.getBBox()
196 minX = min(minX, bbox.getMinX())
197 minY = min(minY, bbox.getMinY())
198 maxX = max(maxX, bbox.getMaxX())
199 maxY = max(maxY, bbox.getMaxY())
200
201 region = lsst.geom.Box2I(lsst.geom.Point2I(minX, minY),
202 lsst.geom.Point2I(maxX, maxY))
203
204 mask = lsst.afw.image.Mask(region)
205 self.maskPixels(mask, maskName="BAD")
206 self._defects = Defects.fromMask(mask, "BAD")._defects
207
Represent a 2-dimensional array of bitmask pixels.
Definition Mask.h:82

◆ append()

lsst.ip.isr.defects.Defects.append ( self,
value )

Definition at line 219 of file defects.py.

219 def append(self, value):
220 self._defects.append(self._check_value(value))
221 self._normalize()
222

◆ apply()

lsst.ip.isr.calibType.IsrCalib.apply ( self,
target )
inherited
Method to apply the calibration to the target object.

Parameters
----------
target : `object`
    Thing to validate against.

Returns
-------
valid : `bool`
    Returns true if the calibration was applied correctly.

Raises
------
NotImplementedError
    Raised if not implemented.

Definition at line 704 of file calibType.py.

704 def apply(self, target):
705 """Method to apply the calibration to the target object.
706
707 Parameters
708 ----------
709 target : `object`
710 Thing to validate against.
711
712 Returns
713 -------
714 valid : `bool`
715 Returns true if the calibration was applied correctly.
716
717 Raises
718 ------
719 NotImplementedError
720 Raised if not implemented.
721 """
722 raise NotImplementedError("Must be implemented by subclass.")
723
724

◆ bulk_update()

lsst.ip.isr.defects.Defects.bulk_update ( self)
Temporarily suspend normalization of the defect list.

Definition at line 209 of file defects.py.

209 def bulk_update(self):
210 """Temporarily suspend normalization of the defect list.
211 """
212 self._bulk_update = True
213 try:
214 yield
215 finally:
216 self._bulk_update = False
217 self._normalize()
218

◆ calibInfoFromDict()

lsst.ip.isr.calibType.IsrCalib.calibInfoFromDict ( self,
dictionary )
inherited
Handle common keywords.

This isn't an ideal solution, but until all calibrations
expect to find everything in the metadata, they still need to
search through dictionaries.

Parameters
----------
dictionary : `dict` or `lsst.daf.base.PropertyList`
    Source for the common keywords.

Raises
------
RuntimeError
    Raised if the dictionary does not match the expected OBSTYPE.

Definition at line 325 of file calibType.py.

325 def calibInfoFromDict(self, dictionary):
326 """Handle common keywords.
327
328 This isn't an ideal solution, but until all calibrations
329 expect to find everything in the metadata, they still need to
330 search through dictionaries.
331
332 Parameters
333 ----------
334 dictionary : `dict` or `lsst.daf.base.PropertyList`
335 Source for the common keywords.
336
337 Raises
338 ------
339 RuntimeError
340 Raised if the dictionary does not match the expected OBSTYPE.
341 """
342
343 def search(haystack, needles):
344 """Search dictionary 'haystack' for an entry in 'needles'
345 """
346 test = [haystack.get(x) for x in needles]
347 test = set([x for x in test if x is not None])
348 if len(test) == 0:
349 if "metadata" in haystack:
350 return search(haystack["metadata"], needles)
351 else:
352 return None
353 elif len(test) == 1:
354 value = list(test)[0]
355 if value == "":
356 return None
357 else:
358 return value
359 else:
360 raise ValueError(f"Too many values found: {len(test)} {test} {needles}")
361
362 if "metadata" in dictionary:
363 metadata = dictionary["metadata"]
364
365 if self._OBSTYPE != metadata["OBSTYPE"]:
366 raise RuntimeError(f"Incorrect calibration supplied. Expected {self._OBSTYPE}, "
367 f"found {metadata['OBSTYPE']}")
368
369 if (value := search(dictionary, ["INSTRUME", "instrument"])) is not None:
370 self._instrument = value
371 if (value := search(dictionary, ["RAFTNAME"])) is not None:
372 self._slotName = value
373 if (value := search(dictionary, ["DETECTOR", "detectorId"])) is not None:
374 self._detectorId = value
375 if (value := search(dictionary, ["DET_NAME", "DETECTOR_NAME", "detectorName"])) is not None:
376 self._detectorName = value
377 if (value := search(dictionary, ["DET_SER", "DETECTOR_SERIAL", "detectorSerial"])) is not None:
378 self._detectorSerial = value
379 if (value := search(dictionary, ["FILTER", "filterName"])) is not None:
380 self._filter = value
381 if (value := search(dictionary, ["CALIB_ID"])) is not None:
382 self._calibId = value
383 if (value := search(dictionary, ["SEQFILE"])) is not None:
384 self._seqfile = value
385 if (value := search(dictionary, ["SEQNAME"])) is not None:
386 self._seqname = value
387 if (value := search(dictionary, ["SEQCKSUM"])) is not None:
388 self._seqcksum = value
389

◆ copy()

lsst.ip.isr.defects.Defects.copy ( self)
Copy the defects to a new list, creating new defects from the
bounding boxes.

Returns
-------
new : `Defects`
    New list with new `Defect` entries.

Notes
-----
This is not a shallow copy in that new `Defect` instances are
created from the original bounding boxes.  It's also not a deep
copy since the bounding boxes are not recreated.

Definition at line 227 of file defects.py.

227 def copy(self):
228 """Copy the defects to a new list, creating new defects from the
229 bounding boxes.
230
231 Returns
232 -------
233 new : `Defects`
234 New list with new `Defect` entries.
235
236 Notes
237 -----
238 This is not a shallow copy in that new `Defect` instances are
239 created from the original bounding boxes. It's also not a deep
240 copy since the bounding boxes are not recreated.
241 """
242 return self.__class__(d.getBBox() for d in self)
243

◆ determineCalibClass()

lsst.ip.isr.calibType.IsrCalib.determineCalibClass ( cls,
metadata,
message )
inherited
Attempt to find calibration class in metadata.

Parameters
----------
metadata : `dict` or `lsst.daf.base.PropertyList`
    Metadata possibly containing a calibration class entry.
message : `str`
    Message to include in any errors.

Returns
-------
calibClass : `object`
    The class to use to read the file contents.  Should be an
    `lsst.ip.isr.IsrCalib` subclass.

Raises
------
ValueError
    Raised if the resulting calibClass is the base
    `lsst.ip.isr.IsrClass` (which does not implement the
    content methods).

Definition at line 391 of file calibType.py.

391 def determineCalibClass(cls, metadata, message):
392 """Attempt to find calibration class in metadata.
393
394 Parameters
395 ----------
396 metadata : `dict` or `lsst.daf.base.PropertyList`
397 Metadata possibly containing a calibration class entry.
398 message : `str`
399 Message to include in any errors.
400
401 Returns
402 -------
403 calibClass : `object`
404 The class to use to read the file contents. Should be an
405 `lsst.ip.isr.IsrCalib` subclass.
406
407 Raises
408 ------
409 ValueError
410 Raised if the resulting calibClass is the base
411 `lsst.ip.isr.IsrClass` (which does not implement the
412 content methods).
413 """
414 calibClassName = metadata.get("CALIBCLS")
415 if calibClassName is None:
416 calibClassName = metadata.get("fileType")
417 if calibClassName == "shutterMotionProfile":
418 calibClassName = "lsst.ip.isr.ShutterMotionProfile"
419 calibClass = doImport(calibClassName) if calibClassName is not None else cls
420 if calibClass is IsrCalib:
421 raise ValueError(f"Cannot use base class to read calibration data: {message}")
422 return calibClass
423

◆ fromDetector()

lsst.ip.isr.calibType.IsrCalib.fromDetector ( self,
detector )
inherited
Modify the calibration parameters to match the supplied detector.

Parameters
----------
detector : `lsst.afw.cameraGeom.Detector`
    Detector to use to set parameters from.

Raises
------
NotImplementedError
    Raised if not implemented by a subclass.
    This needs to be implemented by subclasses for each
    calibration type.

Reimplemented in lsst.ip.isr.crosstalk.CrosstalkCalib, lsst.ip.isr.deferredCharge.DeferredChargeCalib, lsst.ip.isr.linearize.Linearizer, and lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.

Definition at line 586 of file calibType.py.

586 def fromDetector(self, detector):
587 """Modify the calibration parameters to match the supplied detector.
588
589 Parameters
590 ----------
591 detector : `lsst.afw.cameraGeom.Detector`
592 Detector to use to set parameters from.
593
594 Raises
595 ------
596 NotImplementedError
597 Raised if not implemented by a subclass.
598 This needs to be implemented by subclasses for each
599 calibration type.
600 """
601 raise NotImplementedError("Must be implemented by subclass.")
602

◆ fromDict()

lsst.ip.isr.defects.Defects.fromDict ( cls,
dictionary )
Construct a calibration from a dictionary of properties.

Must be implemented by the specific calibration subclasses.

Parameters
----------
dictionary : `dict`
    Dictionary of properties.

Returns
-------
calib : `lsst.ip.isr.CalibType`
    Constructed calibration.

Raises
------
RuntimeError
    Raised if the supplied dictionary is for a different
    calibration.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 357 of file defects.py.

357 def fromDict(cls, dictionary):
358 """Construct a calibration from a dictionary of properties.
359
360 Must be implemented by the specific calibration subclasses.
361
362 Parameters
363 ----------
364 dictionary : `dict`
365 Dictionary of properties.
366
367 Returns
368 -------
369 calib : `lsst.ip.isr.CalibType`
370 Constructed calibration.
371
372 Raises
373 ------
374 RuntimeError
375 Raised if the supplied dictionary is for a different
376 calibration.
377 """
378 calib = cls()
379
380 if calib._OBSTYPE != dictionary['metadata']['OBSTYPE']:
381 raise RuntimeError(f"Incorrect crosstalk supplied. Expected {calib._OBSTYPE}, "
382 f"found {dictionary['metadata']['OBSTYPE']}")
383
384 calib.setMetadata(dictionary['metadata'])
385 calib.calibInfoFromDict(dictionary)
386
387 xCol = dictionary['x0']
388 yCol = dictionary['y0']
389 widthCol = dictionary['width']
390 heightCol = dictionary['height']
391
392 with calib.bulk_update:
393 for x0, y0, width, height in zip(xCol, yCol, widthCol, heightCol):
394 calib.append(lsst.geom.Box2I(lsst.geom.Point2I(x0, y0),
395 lsst.geom.Extent2I(width, height)))
396 return calib
397

◆ fromFootprintList()

lsst.ip.isr.defects.Defects.fromFootprintList ( cls,
fpList )
Compute a defect list from a footprint list, optionally growing
the footprints.

Parameters
----------
fpList : `list` of `lsst.afw.detection.Footprint`
    Footprint list to process.

Returns
-------
defects : `Defects`
    List of defects.

Definition at line 666 of file defects.py.

666 def fromFootprintList(cls, fpList):
667 """Compute a defect list from a footprint list, optionally growing
668 the footprints.
669
670 Parameters
671 ----------
672 fpList : `list` of `lsst.afw.detection.Footprint`
673 Footprint list to process.
674
675 Returns
676 -------
677 defects : `Defects`
678 List of defects.
679 """
680 # normalize_on_init is set to False to avoid recursively calling
681 # fromMask/fromFootprintList in Defects.__init__.
682 return cls(itertools.chain.from_iterable(lsst.afw.detection.footprintToBBoxList(fp)
683 for fp in fpList), normalize_on_init=False)
684
std::vector< lsst::geom::Box2I > footprintToBBoxList(Footprint const &footprint)
Return a list of BBoxs, whose union contains exactly the pixels in the footprint, neither more nor le...
Definition Footprint.cc:366

◆ fromMask()

lsst.ip.isr.defects.Defects.fromMask ( cls,
mask,
maskName )
Compute a defect list from a specified mask plane.

Parameters
----------
mask : `lsst.afw.image.Mask` or `lsst.afw.image.MaskedImage`
    Image to process.
maskName : `str` or `list`
    Mask plane name, or list of names to convert.

Returns
-------
defects : `Defects`
    Defect list constructed from masked pixels.

Definition at line 686 of file defects.py.

686 def fromMask(cls, mask, maskName):
687 """Compute a defect list from a specified mask plane.
688
689 Parameters
690 ----------
691 mask : `lsst.afw.image.Mask` or `lsst.afw.image.MaskedImage`
692 Image to process.
693 maskName : `str` or `list`
694 Mask plane name, or list of names to convert.
695
696 Returns
697 -------
698 defects : `Defects`
699 Defect list constructed from masked pixels.
700 """
701 if hasattr(mask, "getMask"):
702 mask = mask.getMask()
703 thresh = lsst.afw.detection.Threshold(mask.getPlaneBitMask(maskName),
704 lsst.afw.detection.Threshold.BITMASK)
705 fpList = lsst.afw.detection.FootprintSet(mask, thresh).getFootprints()
706 return cls.fromFootprintList(fpList)
A set of Footprints, associated with a MaskedImage.
A Threshold is used to pass a threshold value to detection algorithms.
Definition Threshold.h:43

◆ fromTable()

lsst.ip.isr.defects.Defects.fromTable ( cls,
tableList,
normalize_on_init = True )
Construct a `Defects` from the contents of a
`~lsst.afw.table.BaseCatalog`.

Parameters
----------
table : `lsst.afw.table.BaseCatalog`
    Table with one row per defect.
normalize_on_init : `bool`, optional
    If `True`, normalization is applied to the defects listed in the
    table to remove duplicates, eliminate overlaps, etc. Otherwise
    the defects in the returned object exactly match those in the
    table.

Returns
-------
defects : `Defects`
    A `Defects` list.

Notes
-----
Two table formats are recognized.  The first is the
`FITS regions <https://fits.gsfc.nasa.gov/registry/region.html>`_
definition tabular format written by `toFitsRegionTable` where the
pixel origin is corrected from FITS 1-based to a 0-based origin.
The second is the legacy defects format using columns ``x0``, ``y0``
(bottom left hand pixel of box in 0-based coordinates), ``width``
and ``height``.

The FITS standard regions can only read BOX, POINT, or ROTBOX with
a zero degree rotation.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 517 of file defects.py.

517 def fromTable(cls, tableList, normalize_on_init=True):
518 """Construct a `Defects` from the contents of a
519 `~lsst.afw.table.BaseCatalog`.
520
521 Parameters
522 ----------
523 table : `lsst.afw.table.BaseCatalog`
524 Table with one row per defect.
525 normalize_on_init : `bool`, optional
526 If `True`, normalization is applied to the defects listed in the
527 table to remove duplicates, eliminate overlaps, etc. Otherwise
528 the defects in the returned object exactly match those in the
529 table.
530
531 Returns
532 -------
533 defects : `Defects`
534 A `Defects` list.
535
536 Notes
537 -----
538 Two table formats are recognized. The first is the
539 `FITS regions <https://fits.gsfc.nasa.gov/registry/region.html>`_
540 definition tabular format written by `toFitsRegionTable` where the
541 pixel origin is corrected from FITS 1-based to a 0-based origin.
542 The second is the legacy defects format using columns ``x0``, ``y0``
543 (bottom left hand pixel of box in 0-based coordinates), ``width``
544 and ``height``.
545
546 The FITS standard regions can only read BOX, POINT, or ROTBOX with
547 a zero degree rotation.
548 """
549 table = tableList[0]
550 defectList = []
551
552 schema = table.columns
553 # Check schema to see which definitions we have
554 if "X" in schema and "Y" in schema and "R" in schema and "SHAPE" in schema:
555 # This is a FITS region style table
556 isFitsRegion = True
557 elif "x0" in schema and "y0" in schema and "width" in schema and "height" in schema:
558 # This is a classic LSST-style defect table
559 isFitsRegion = False
560 else:
561 raise ValueError("Unsupported schema for defects extraction")
562
563 for record in table:
564 if isFitsRegion:
565 # Coordinates can be arrays (some shapes in the standard
566 # require this)
567 # Correct for FITS 1-based origin
568 xcen = cls._get_values(record['X']) - 1.0
569 ycen = cls._get_values(record['Y']) - 1.0
570 shape = record['SHAPE'].upper().rstrip()
571 if shape == "BOX":
573 lsst.geom.Extent2I(cls._get_values(record['R'],
574 n=2)))
575 elif shape == "POINT":
576 # Handle the case where we have an externally created
577 # FITS file.
578 box = lsst.geom.Point2I(xcen, ycen)
579 elif shape == "ROTBOX":
580 # Astropy regions always writes ROTBOX
581 rotang = cls._get_values(record['ROTANG'])
582 # We can support 0 or 90 deg
583 if math.isclose(rotang % 90.0, 0.0):
584 # Two values required
585 r = cls._get_values(record['R'], n=2)
586 if math.isclose(rotang % 180.0, 0.0):
587 width = r[0]
588 height = r[1]
589 else:
590 width = r[1]
591 height = r[0]
593 lsst.geom.Extent2I(width, height))
594 else:
595 log.warning("Defect can not be defined using ROTBOX with non-aligned rotation angle")
596 continue
597 else:
598 log.warning("Defect lists can only be defined using BOX or POINT not %s", shape)
599 continue
600
601 else:
602 # This is a classic LSST-style defect table
603 box = lsst.geom.Box2I(lsst.geom.Point2I(record['x0'], record['y0']),
604 lsst.geom.Extent2I(record['width'], record['height']))
605
606 defectList.append(box)
607
608 defects = cls(defectList, normalize_on_init=normalize_on_init)
609 newMeta = dict(table.meta)
610 defects.updateMetadata(setCalibInfo=True, **newMeta)
611
612 return defects
613
static Box2I makeCenteredBox(Point2D const &center, Extent const &size)
Create a box centered as closely as possible on a particular point.
Definition Box.cc:97

◆ getMetadata()

lsst.ip.isr.calibType.IsrCalib.getMetadata ( self)
inherited
Retrieve metadata associated with this calibration.

Returns
-------
meta : `lsst.daf.base.PropertyList`
    Metadata. The returned `~lsst.daf.base.PropertyList` can be
    modified by the caller and the changes will be written to
    external files.

Definition at line 174 of file calibType.py.

174 def getMetadata(self):
175 """Retrieve metadata associated with this calibration.
176
177 Returns
178 -------
179 meta : `lsst.daf.base.PropertyList`
180 Metadata. The returned `~lsst.daf.base.PropertyList` can be
181 modified by the caller and the changes will be written to
182 external files.
183 """
184 return self._metadata
185

◆ insert()

lsst.ip.isr.defects.Defects.insert ( self,
index,
value )

Definition at line 223 of file defects.py.

223 def insert(self, index, value):
224 self._defects.insert(index, self._check_value(value))
225 self._normalize()
226

◆ maskPixels()

lsst.ip.isr.defects.Defects.maskPixels ( self,
mask,
maskName = "BAD" )
Set mask plane based on these defects.

Parameters
----------
maskedImage : `lsst.afw.image.MaskedImage` or `lsst.afw.image.Mask`
    Image to process.  Only the mask plane is updated.
maskName : str, optional
    Mask plane name to use.

Definition at line 261 of file defects.py.

261 def maskPixels(self, mask, maskName="BAD"):
262 """Set mask plane based on these defects.
263
264 Parameters
265 ----------
266 maskedImage : `lsst.afw.image.MaskedImage` or `lsst.afw.image.Mask`
267 Image to process. Only the mask plane is updated.
268 maskName : str, optional
269 Mask plane name to use.
270 """
271 # mask bad pixels
272 if hasattr(mask, "getMask"):
273 mask = mask.getMask()
274 bitmask = mask.getPlaneBitMask(maskName)
275 for defect in self:
276 bbox = defect.getBBox()
277 lsst.afw.geom.SpanSet(bbox).clippedTo(mask.getBBox()).setMask(mask, bitmask)
278
A compact representation of a collection of pixels.
Definition SpanSet.h:78

◆ metadata()

lsst.ip.isr.calibType.IsrCalib.metadata ( self)
inherited

Definition at line 171 of file calibType.py.

171 def metadata(self):
172 return self._metadata
173

◆ readFits()

lsst.ip.isr.calibType.IsrCalib.readFits ( cls,
filename,
** kwargs )
inherited
Read calibration data from a FITS file.

Parameters
----------
filename : `str`
    Filename to read data from.
kwargs : `dict` or collections.abc.Mapping`, optional
    Set of key=value pairs to pass to the ``fromTable``
    method.

Returns
-------
calib : `lsst.ip.isr.IsrCalib`
    Calibration contained within the file.

Definition at line 517 of file calibType.py.

517 def readFits(cls, filename, **kwargs):
518 """Read calibration data from a FITS file.
519
520 Parameters
521 ----------
522 filename : `str`
523 Filename to read data from.
524 kwargs : `dict` or collections.abc.Mapping`, optional
525 Set of key=value pairs to pass to the ``fromTable``
526 method.
527
528 Returns
529 -------
530 calib : `lsst.ip.isr.IsrCalib`
531 Calibration contained within the file.
532 """
533 tableList = []
534 tableList.append(Table.read(filename, hdu=1, mask_invalid=False))
535 extNum = 2 # Fits indices start at 1, we've read one already.
536 keepTrying = True
537
538 while keepTrying:
539 with warnings.catch_warnings():
540 warnings.simplefilter("error")
541 try:
542 newTable = Table.read(filename, hdu=extNum, mask_invalid=False)
543 tableList.append(newTable)
544 extNum += 1
545 except Exception:
546 keepTrying = False
547
548 for table in tableList:
549 for k, v in table.meta.items():
550 if isinstance(v, fits.card.Undefined):
551 table.meta[k] = None
552
553 calibClass = cls.determineCalibClass(tableList[0].meta, "readFits")
554 if calibClass._OBSTYPE in ("PHOTODIODE", ):
555 # Merge primary header, as these types store information
556 # there.
557 with fits.open(filename) as hdul:
558 primaryHeader = hdul[0].header
559 tableList[0].meta = merge_headers([tableList[0].meta, primaryHeader], mode="first")
560
561 return calibClass.fromTable(tableList, **kwargs)
562

◆ readLsstDefectsFile()

lsst.ip.isr.defects.Defects.readLsstDefectsFile ( cls,
filename,
normalize_on_init = False )
Read defects information from a legacy LSST format text file.

Parameters
----------
filename : `str`
    Name of text file containing the defect information.

normalize_on_init : `bool`, optional
    If `True`, normalization is applied to the defects listed in the
    table to remove duplicates, eliminate overlaps, etc. Otherwise
    the defects in the returned object exactly match those in the
    table.

Returns
-------
defects : `Defects`
    The defects.

Notes
-----
These defect text files are used as the human readable definitions
of defects in calibration data definition repositories.  The format
is to use four columns defined as follows:

x0 : `int`
    X coordinate of bottom left corner of box.
y0 : `int`
    Y coordinate of bottom left corner of box.
width : `int`
    X extent of the box.
height : `int`
    Y extent of the box.

Files of this format were used historically to represent defects
in simple text form.  Use `Defects.readText` and `Defects.writeText`
to use the more modern format.

Definition at line 615 of file defects.py.

615 def readLsstDefectsFile(cls, filename, normalize_on_init=False):
616 """Read defects information from a legacy LSST format text file.
617
618 Parameters
619 ----------
620 filename : `str`
621 Name of text file containing the defect information.
622
623 normalize_on_init : `bool`, optional
624 If `True`, normalization is applied to the defects listed in the
625 table to remove duplicates, eliminate overlaps, etc. Otherwise
626 the defects in the returned object exactly match those in the
627 table.
628
629 Returns
630 -------
631 defects : `Defects`
632 The defects.
633
634 Notes
635 -----
636 These defect text files are used as the human readable definitions
637 of defects in calibration data definition repositories. The format
638 is to use four columns defined as follows:
639
640 x0 : `int`
641 X coordinate of bottom left corner of box.
642 y0 : `int`
643 Y coordinate of bottom left corner of box.
644 width : `int`
645 X extent of the box.
646 height : `int`
647 Y extent of the box.
648
649 Files of this format were used historically to represent defects
650 in simple text form. Use `Defects.readText` and `Defects.writeText`
651 to use the more modern format.
652 """
653 # Use loadtxt so that ValueError is thrown if the file contains a
654 # non-integer value. genfromtxt converts bad values to -1.
655 defect_array = np.loadtxt(filename,
656 dtype=[("x0", "int"), ("y0", "int"),
657 ("x_extent", "int"), ("y_extent", "int")])
658
659 defects = (lsst.geom.Box2I(lsst.geom.Point2I(row["x0"], row["y0"]),
660 lsst.geom.Extent2I(row["x_extent"], row["y_extent"]))
661 for row in defect_array)
662
663 return cls(defects, normalize_on_init=normalize_on_init)
664

◆ readText()

lsst.ip.isr.calibType.IsrCalib.readText ( cls,
filename,
** kwargs )
inherited
Read calibration representation from a yaml/ecsv file.

Parameters
----------
filename : `str`
    Name of the file containing the calibration definition.
kwargs : `dict` or collections.abc.Mapping`, optional
    Set of key=value pairs to pass to the ``fromDict`` or
    ``fromTable`` methods.

Returns
-------
calib : `~lsst.ip.isr.IsrCalibType`
    Calibration class.

Raises
------
RuntimeError
    Raised if the filename does not end in ".ecsv" or ".yaml".

Definition at line 425 of file calibType.py.

425 def readText(cls, filename, **kwargs):
426 """Read calibration representation from a yaml/ecsv file.
427
428 Parameters
429 ----------
430 filename : `str`
431 Name of the file containing the calibration definition.
432 kwargs : `dict` or collections.abc.Mapping`, optional
433 Set of key=value pairs to pass to the ``fromDict`` or
434 ``fromTable`` methods.
435
436 Returns
437 -------
438 calib : `~lsst.ip.isr.IsrCalibType`
439 Calibration class.
440
441 Raises
442 ------
443 RuntimeError
444 Raised if the filename does not end in ".ecsv" or ".yaml".
445 """
446 if filename.endswith((".ecsv", ".ECSV")):
447 data = Table.read(filename, format="ascii.ecsv")
448 calibClass = cls.determineCalibClass(data.meta, "readText/ECSV")
449 return calibClass.fromTable([data], **kwargs)
450 elif filename.endswith((".yaml", ".YAML")):
451 with open(filename, "r") as f:
452 data = yaml.load(f, Loader=yaml.CLoader)
453 calibClass = cls.determineCalibClass(data["metadata"], "readText/YAML")
454 return calibClass.fromDict(data, **kwargs)
455 elif filename.endswith((".json", ".JSON")):
456 with open(filename, "r") as f:
457 data = json.load(f)
458 calibClass = cls.determineCalibClass(data, "readText/JSON")
459 return calibClass.fromDict(data, **kwargs)
460 else:
461 raise RuntimeError(f"Unknown filename extension: {filename}")
462

◆ requiredAttributes() [1/2]

lsst.ip.isr.calibType.IsrCalib.requiredAttributes ( self)
inherited

Definition at line 162 of file calibType.py.

162 def requiredAttributes(self):
163 return self._requiredAttributes
164

◆ requiredAttributes() [2/2]

lsst.ip.isr.calibType.IsrCalib.requiredAttributes ( self,
value )
inherited

Definition at line 166 of file calibType.py.

166 def requiredAttributes(self, value):
167 self._requiredAttributes = value
168

◆ setMetadata()

lsst.ip.isr.calibType.IsrCalib.setMetadata ( self,
metadata )
inherited
Store a copy of the supplied metadata with this calibration.

Parameters
----------
metadata : `lsst.daf.base.PropertyList`
    Metadata to associate with the calibration.  Will be copied and
    overwrite existing metadata.

Reimplemented in lsst.ip.isr.transmissionCurve.IntermediateTransmissionCurve.

Definition at line 186 of file calibType.py.

186 def setMetadata(self, metadata):
187 """Store a copy of the supplied metadata with this calibration.
188
189 Parameters
190 ----------
191 metadata : `lsst.daf.base.PropertyList`
192 Metadata to associate with the calibration. Will be copied and
193 overwrite existing metadata.
194 """
195 if metadata is not None:
196 self._metadata.update(metadata)
197
198 # Ensure that we have the obs type required by calibration ingest
199 self._metadata["OBSTYPE"] = self._OBSTYPE
200 self._metadata[self._OBSTYPE + "_SCHEMA"] = self._SCHEMA
201 self._metadata[self._OBSTYPE + "_VERSION"] = self._VERSION
202
203 if isinstance(metadata, dict):
204 self.calibInfoFromDict(metadata)
205 elif isinstance(metadata, PropertyList):
206 self.calibInfoFromDict(metadata.toDict())
207

◆ toDict()

lsst.ip.isr.defects.Defects.toDict ( self)
Return a dictionary containing the calibration properties.

The dictionary should be able to be round-tripped through
`fromDict`.

Returns
-------
dictionary : `dict`
    Dictionary of properties.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 398 of file defects.py.

398 def toDict(self):
399 """Return a dictionary containing the calibration properties.
400
401 The dictionary should be able to be round-tripped through
402 `fromDict`.
403
404 Returns
405 -------
406 dictionary : `dict`
407 Dictionary of properties.
408 """
409 self.updateMetadata()
410
411 outDict = {}
412 metadata = self.getMetadata()
413 outDict['metadata'] = metadata
414
415 xCol = []
416 yCol = []
417 widthCol = []
418 heightCol = []
419
420 nrows = len(self._defects)
421 if nrows:
422 for defect in self._defects:
423 box = defect.getBBox()
424 xCol.append(box.getBeginX())
425 yCol.append(box.getBeginY())
426 widthCol.append(box.getWidth())
427 heightCol.append(box.getHeight())
428
429 outDict['x0'] = xCol
430 outDict['y0'] = yCol
431 outDict['width'] = widthCol
432 outDict['height'] = heightCol
433
434 return outDict
435

◆ toFitsRegionTable()

lsst.ip.isr.defects.Defects.toFitsRegionTable ( self)
Convert defect list to `~lsst.afw.table.BaseCatalog` using the
FITS region standard.

Returns
-------
table : `lsst.afw.table.BaseCatalog`
    Defects in tabular form.

Notes
-----
The table created uses the
`FITS regions <https://fits.gsfc.nasa.gov/registry/region.html>`_
definition tabular format.  The ``X`` and ``Y`` coordinates are
converted to FITS Physical coordinates that have origin pixel (1, 1)
rather than the (0, 0) used in LSST software.

Definition at line 302 of file defects.py.

302 def toFitsRegionTable(self):
303 """Convert defect list to `~lsst.afw.table.BaseCatalog` using the
304 FITS region standard.
305
306 Returns
307 -------
308 table : `lsst.afw.table.BaseCatalog`
309 Defects in tabular form.
310
311 Notes
312 -----
313 The table created uses the
314 `FITS regions <https://fits.gsfc.nasa.gov/registry/region.html>`_
315 definition tabular format. The ``X`` and ``Y`` coordinates are
316 converted to FITS Physical coordinates that have origin pixel (1, 1)
317 rather than the (0, 0) used in LSST software.
318 """
319 self.updateMetadata()
320 nrows = len(self._defects)
321
322 if nrows:
323 # Adding entire columns is more efficient than adding
324 # each element separately
325 xCol = []
326 yCol = []
327 rCol = []
328 shapes = []
329 for i, defect in enumerate(self._defects):
330 box = defect.getBBox()
331 center = box.getCenter()
332 # Correct for the FITS 1-based offset
333 xCol.append(center.getX() + 1.0)
334 yCol.append(center.getY() + 1.0)
335
336 width = box.width
337 height = box.height
338
339 if width == 1 and height == 1:
340 # Call this a point
341 shapeType = "POINT"
342 else:
343 shapeType = "BOX"
344
345 # Strings have to be added per row
346 shapes.append(shapeType)
347
348 rCol.append(np.array([width, height], dtype=np.float64))
349
350 table = astropy.table.Table({'X': xCol, 'Y': yCol, 'SHAPE': shapes,
351 'R': rCol, 'ROTANG': np.zeros(nrows),
352 'COMPONENT': np.arange(nrows)})
353 table.meta = self.getMetadata().toDict()
354 return table
355

◆ toTable()

lsst.ip.isr.defects.Defects.toTable ( self)
Convert defects to a simple table form that we use to write
to text files.

Returns
-------
table : `lsst.afw.table.BaseCatalog`
    Defects in simple tabular form.

Notes
-----
These defect tables are used as the human readable definitions
of defects in calibration data definition repositories.  The format
is to use four columns defined as follows:

x0 : `int`
    X coordinate of bottom left corner of box.
y0 : `int`
    Y coordinate of bottom left corner of box.
width : `int`
    X extent of the box.
height : `int`
    Y extent of the box.

Reimplemented from lsst.ip.isr.calibType.IsrCalib.

Definition at line 436 of file defects.py.

436 def toTable(self):
437 """Convert defects to a simple table form that we use to write
438 to text files.
439
440 Returns
441 -------
442 table : `lsst.afw.table.BaseCatalog`
443 Defects in simple tabular form.
444
445 Notes
446 -----
447 These defect tables are used as the human readable definitions
448 of defects in calibration data definition repositories. The format
449 is to use four columns defined as follows:
450
451 x0 : `int`
452 X coordinate of bottom left corner of box.
453 y0 : `int`
454 Y coordinate of bottom left corner of box.
455 width : `int`
456 X extent of the box.
457 height : `int`
458 Y extent of the box.
459 """
460 tableList = []
461 self.updateMetadata()
462
463 xCol = []
464 yCol = []
465 widthCol = []
466 heightCol = []
467
468 nrows = len(self._defects)
469 if nrows:
470 for defect in self._defects:
471 box = defect.getBBox()
472 xCol.append(box.getBeginX())
473 yCol.append(box.getBeginY())
474 widthCol.append(box.getWidth())
475 heightCol.append(box.getHeight())
476
477 catalog = astropy.table.Table({'x0': xCol, 'y0': yCol, 'width': widthCol, 'height': heightCol})
478 inMeta = self.getMetadata().toDict()
479 outMeta = {k: v for k, v in inMeta.items() if v is not None}
480 catalog.meta = outMeta
481 tableList.append(catalog)
482
483 return tableList
484

◆ transpose()

lsst.ip.isr.defects.Defects.transpose ( self)
Make a transposed copy of this defect list.

Returns
-------
retDefectList : `Defects`
    Transposed list of defects.

Definition at line 244 of file defects.py.

244 def transpose(self):
245 """Make a transposed copy of this defect list.
246
247 Returns
248 -------
249 retDefectList : `Defects`
250 Transposed list of defects.
251 """
252 retDefectList = self.__class__()
253 for defect in self:
254 bbox = defect.getBBox()
255 dimensions = bbox.getDimensions()
256 nbbox = lsst.geom.Box2I(lsst.geom.Point2I(bbox.getMinY(), bbox.getMinX()),
257 lsst.geom.Extent2I(dimensions[1], dimensions[0]))
258 retDefectList.append(nbbox)
259 return retDefectList
260

◆ updateCounters()

lsst.ip.isr.defects.Defects.updateCounters ( self,
columns = None,
hot = None,
cold = None )
Update metadata with pixel and column counts.

Parameters
----------
columns : `int`, optional
    Number of full columns masked.
hot : `dict` [`str`, `int`], optional
    Dictionary with the count of hot pixels, indexed by amplifier name.
cold : `dict` [`str`, `int`], optional
    Dictionary with the count of hot pixels, indexed by amplifier name.

Definition at line 279 of file defects.py.

279 def updateCounters(self, columns=None, hot=None, cold=None):
280 """Update metadata with pixel and column counts.
281
282 Parameters
283 ----------
284 columns : `int`, optional
285 Number of full columns masked.
286 hot : `dict` [`str`, `int`], optional
287 Dictionary with the count of hot pixels, indexed by amplifier name.
288 cold : `dict` [`str`, `int`], optional
289 Dictionary with the count of hot pixels, indexed by amplifier name.
290 """
291 mdSupplemental = dict()
292 if columns:
293 mdSupplemental["LSST CALIB DEFECTS N_BAD_COLUMNS"] = columns
294 if hot:
295 for amp, count in hot.items():
296 mdSupplemental[f"LSST CALIB DEFECTS {amp} N_HOT"] = count
297 if cold:
298 for amp, count in cold.items():
299 mdSupplemental[f"LSST CALIB DEFECTS {amp} N_COLD"] = count
300 self.getMetadata().update(mdSupplemental)
301

◆ updateMetadata()

lsst.ip.isr.calibType.IsrCalib.updateMetadata ( self,
camera = None,
detector = None,
filterName = None,
setCalibId = False,
setCalibInfo = False,
setDate = False,
** kwargs )
inherited
Update metadata keywords with new values.

Parameters
----------
camera : `lsst.afw.cameraGeom.Camera`, optional
    Reference camera to use to set ``_instrument`` field.
detector : `lsst.afw.cameraGeom.Detector`, optional
    Reference detector to use to set ``_detector*`` fields.
filterName : `str`, optional
    Filter name to assign to this calibration.
setCalibId : `bool`, optional
    Construct the ``_calibId`` field from other fields.
setCalibInfo : `bool`, optional
    Set calibration parameters from metadata.
setDate : `bool`, optional
    Ensure the metadata ``CALIBDATE`` fields are set to the current
    datetime.
kwargs : `dict` or `collections.abc.Mapping`, optional
    Set of ``key=value`` pairs to assign to the metadata.

Reimplemented in lsst.ip.isr.brighterFatterKernel.BrighterFatterKernel, lsst.ip.isr.calibType.IsrProvenance, lsst.ip.isr.crosstalk.CrosstalkCalib, lsst.ip.isr.linearize.Linearizer, lsst.ip.isr.photodiodeCorrection.PhotodiodeCorrection, and lsst.ip.isr.ptcDataset.PhotonTransferCurveDataset.

Definition at line 208 of file calibType.py.

210 **kwargs):
211 """Update metadata keywords with new values.
212
213 Parameters
214 ----------
215 camera : `lsst.afw.cameraGeom.Camera`, optional
216 Reference camera to use to set ``_instrument`` field.
217 detector : `lsst.afw.cameraGeom.Detector`, optional
218 Reference detector to use to set ``_detector*`` fields.
219 filterName : `str`, optional
220 Filter name to assign to this calibration.
221 setCalibId : `bool`, optional
222 Construct the ``_calibId`` field from other fields.
223 setCalibInfo : `bool`, optional
224 Set calibration parameters from metadata.
225 setDate : `bool`, optional
226 Ensure the metadata ``CALIBDATE`` fields are set to the current
227 datetime.
228 kwargs : `dict` or `collections.abc.Mapping`, optional
229 Set of ``key=value`` pairs to assign to the metadata.
230 """
231 mdOriginal = self.getMetadata()
232 mdSupplemental = dict()
233
234 for k, v in kwargs.items():
235 if isinstance(v, fits.card.Undefined):
236 kwargs[k] = None
237
238 if setCalibInfo:
239 self.calibInfoFromDict(kwargs)
240
241 if camera:
242 self._instrument = camera.getName()
243
244 if detector:
245 self._detectorName = detector.getName()
246 self._detectorSerial = detector.getSerial()
247 self._detectorId = detector.getId()
248 if "_" in self._detectorName:
249 (self._raftName, self._slotName) = self._detectorName.split("_")
250
251 if filterName:
252 # TOD0 DM-28093: I think this whole comment can go away, if we
253 # always use physicalLabel everywhere in ip_isr.
254 # If set via:
255 # exposure.getInfo().getFilter().getName()
256 # then this will hold the abstract filter.
257 self._filter = filterName
258
259 if setDate:
260 date = datetime.datetime.now()
261 mdSupplemental["CALIBDATE"] = date.isoformat()
262 mdSupplemental["CALIB_CREATION_DATE"] = date.date().isoformat()
263 mdSupplemental["CALIB_CREATION_TIME"] = date.time().isoformat()
264
265 if setCalibId:
266 values = []
267 values.append(f"instrument={self._instrument}") if self._instrument else None
268 values.append(f"raftName={self._raftName}") if self._raftName else None
269 values.append(f"detectorName={self._detectorName}") if self._detectorName else None
270 values.append(f"detector={self._detectorId}") if self._detectorId else None
271 values.append(f"filter={self._filter}") if self._filter else None
272
273 calibDate = mdOriginal.get("CALIBDATE", mdSupplemental.get("CALIBDATE", None))
274 values.append(f"calibDate={calibDate}") if calibDate else None
275
276 self._calibId = " ".join(values)
277
278 self._metadata["INSTRUME"] = self._instrument if self._instrument else None
279 self._metadata["RAFTNAME"] = self._raftName if self._raftName else None
280 self._metadata["SLOTNAME"] = self._slotName if self._slotName else None
281 self._metadata["DETECTOR"] = self._detectorId
282 self._metadata["DET_NAME"] = self._detectorName if self._detectorName else None
283 self._metadata["DET_SER"] = self._detectorSerial if self._detectorSerial else None
284 self._metadata["FILTER"] = self._filter if self._filter else None
285 self._metadata["CALIB_ID"] = self._calibId if self._calibId else None
286 self._metadata["SEQFILE"] = self._seqfile if self._seqfile else None
287 self._metadata["SEQNAME"] = self._seqname if self._seqname else None
288 self._metadata["SEQCKSUM"] = self._seqcksum if self._seqcksum else None
289 self._metadata["CALIBCLS"] = get_full_type_name(self)
290
291 mdSupplemental.update(kwargs)
292 mdOriginal.update(mdSupplemental)
293

◆ updateMetadataFromExposures()

lsst.ip.isr.calibType.IsrCalib.updateMetadataFromExposures ( self,
exposures )
inherited
Extract and unify metadata information.

Parameters
----------
exposures : `list`
    Exposures or other calibrations to scan.

Definition at line 294 of file calibType.py.

294 def updateMetadataFromExposures(self, exposures):
295 """Extract and unify metadata information.
296
297 Parameters
298 ----------
299 exposures : `list`
300 Exposures or other calibrations to scan.
301 """
302 # This list of keywords is the set of header entries that
303 # should be checked and propagated. Not having an entry is
304 # not a failure, as they may not be defined for the exposures
305 # being used.
306 keywords = ["SEQNAME", "SEQFILE", "SEQCKSUM", "ODP", "AP0_RC"]
307 metadata = {}
308
309 for exp in exposures:
310 try:
311 expMeta = exp.getMetadata()
312 except AttributeError:
313 continue
314 for key in keywords:
315 if key in expMeta:
316 if key in metadata:
317 if metadata[key] != expMeta[key]:
318 self.log.warning("Metadata mismatch! Have: %s Found %s",
319 metadata[key], expMeta[key])
320 else:
321 metadata[key] = expMeta[key]
322
323 self.updateMetadata(**metadata, setCalibInfo=True)
324

◆ validate()

lsst.ip.isr.calibType.IsrCalib.validate ( self,
other = None )
inherited
Validate that this calibration is defined and can be used.

Parameters
----------
other : `object`, optional
    Thing to validate against.

Returns
-------
valid : `bool`
    Returns true if the calibration is valid and appropriate.

Reimplemented in lsst.ip.isr.linearize.Linearizer, and lsst.ip.isr.photodiodeCorrection.PhotodiodeCorrection.

Definition at line 689 of file calibType.py.

689 def validate(self, other=None):
690 """Validate that this calibration is defined and can be used.
691
692 Parameters
693 ----------
694 other : `object`, optional
695 Thing to validate against.
696
697 Returns
698 -------
699 valid : `bool`
700 Returns true if the calibration is valid and appropriate.
701 """
702 return False
703

◆ writeFits()

lsst.ip.isr.calibType.IsrCalib.writeFits ( self,
filename )
inherited
Write calibration data to a FITS file.

Parameters
----------
filename : `str`
    Filename to write data to.

Returns
-------
used : `str`
    The name of the file used to write the data.

Reimplemented in lsst.ip.isr.transmissionCurve.IntermediateTransmissionCurve.

Definition at line 563 of file calibType.py.

563 def writeFits(self, filename):
564 """Write calibration data to a FITS file.
565
566 Parameters
567 ----------
568 filename : `str`
569 Filename to write data to.
570
571 Returns
572 -------
573 used : `str`
574 The name of the file used to write the data.
575 """
576 tableList = self.toTable()
577 with warnings.catch_warnings():
578 warnings.filterwarnings("ignore", category=Warning, module="astropy.io")
579 astropyList = [fits.table_to_hdu(table) for table in tableList]
580 astropyList.insert(0, fits.PrimaryHDU())
581
582 writer = fits.HDUList(astropyList)
583 writer.writeto(filename, overwrite=True)
584 return filename
585

◆ writeText()

lsst.ip.isr.calibType.IsrCalib.writeText ( self,
filename,
format = "auto" )
inherited
Write the calibration data to a text file.

Parameters
----------
filename : `str`
    Name of the file to write.
format : `str`
    Format to write the file as.  Supported values are:
        ``"auto"`` : Determine filetype from filename.
        ``"yaml"`` : Write as yaml.
        ``"ecsv"`` : Write as ecsv.

Returns
-------
used : `str`
    The name of the file used to write the data.  This may
    differ from the input if the format is explicitly chosen.

Raises
------
RuntimeError
    Raised if filename does not end in a known extension, or
    if all information cannot be written.

Notes
-----
The file is written to YAML/ECSV format and will include any
associated metadata.

Definition at line 463 of file calibType.py.

463 def writeText(self, filename, format="auto"):
464 """Write the calibration data to a text file.
465
466 Parameters
467 ----------
468 filename : `str`
469 Name of the file to write.
470 format : `str`
471 Format to write the file as. Supported values are:
472 ``"auto"`` : Determine filetype from filename.
473 ``"yaml"`` : Write as yaml.
474 ``"ecsv"`` : Write as ecsv.
475
476 Returns
477 -------
478 used : `str`
479 The name of the file used to write the data. This may
480 differ from the input if the format is explicitly chosen.
481
482 Raises
483 ------
484 RuntimeError
485 Raised if filename does not end in a known extension, or
486 if all information cannot be written.
487
488 Notes
489 -----
490 The file is written to YAML/ECSV format and will include any
491 associated metadata.
492 """
493 if format == "yaml" or (format == "auto" and filename.lower().endswith((".yaml", ".YAML"))):
494 outDict = self.toDict()
495 path, ext = os.path.splitext(filename)
496 filename = path + ".yaml"
497 with open(filename, "w") as f:
498 yaml.dump(outDict, f)
499 elif format == "ecsv" or (format == "auto" and filename.lower().endswith((".ecsv", ".ECSV"))):
500 tableList = self.toTable()
501 if len(tableList) > 1:
502 # ECSV doesn't support multiple tables per file, so we
503 # can only write the first table.
504 raise RuntimeError(f"Unable to persist {len(tableList)}tables in ECSV format.")
505
506 table = tableList[0]
507 path, ext = os.path.splitext(filename)
508 filename = path + ".ecsv"
509 table.write(filename, format="ascii.ecsv")
510 else:
511 raise RuntimeError(f"Attempt to write to a file {filename} "
512 "that does not end in '.yaml' or '.ecsv'")
513
514 return filename
515

Member Data Documentation

◆ _bulk_update

bool lsst.ip.isr.defects.Defects._bulk_update = True
protected

Definition at line 87 of file defects.py.

◆ _calibId

str lsst.ip.isr.calibType.IsrCalib._calibId = None
protectedinherited

Definition at line 76 of file calibType.py.

◆ _defects

lsst.ip.isr.defects.Defects._defects = []
protected

Definition at line 84 of file defects.py.

◆ _detectorId

lsst.ip.isr.calibType.IsrCalib._detectorId = None
protectedinherited

Definition at line 74 of file calibType.py.

◆ _detectorName

lsst.ip.isr.calibType.IsrCalib._detectorName = None
protectedinherited

Definition at line 72 of file calibType.py.

◆ _detectorSerial

lsst.ip.isr.calibType.IsrCalib._detectorSerial = None
protectedinherited

Definition at line 73 of file calibType.py.

◆ _filter

lsst.ip.isr.calibType.IsrCalib._filter = None
protectedinherited

Definition at line 75 of file calibType.py.

◆ _instrument

lsst.ip.isr.calibType.IsrCalib._instrument = None
protectedinherited

Definition at line 69 of file calibType.py.

◆ _metadata

lsst.ip.isr.calibType.IsrCalib._metadata = PropertyList()
protectedinherited

Definition at line 80 of file calibType.py.

◆ _OBSTYPE

str lsst.ip.isr.calibType.IsrCalib._OBSTYPE = "generic"
staticprotectedinherited

Definition at line 64 of file calibType.py.

◆ _raftName

lsst.ip.isr.calibType.IsrCalib._raftName = None
protectedinherited

Definition at line 70 of file calibType.py.

◆ _requiredAttributes

lsst.ip.isr.calibType.IsrCalib._requiredAttributes
protectedinherited

Definition at line 115 of file calibType.py.

◆ _SCHEMA

str lsst.ip.isr.calibType.IsrCalib._SCHEMA = "NO SCHEMA"
staticprotectedinherited

Definition at line 65 of file calibType.py.

◆ _seqcksum

lsst.ip.isr.calibType.IsrCalib._seqcksum = None
protectedinherited

Definition at line 79 of file calibType.py.

◆ _seqfile

lsst.ip.isr.calibType.IsrCalib._seqfile = None
protectedinherited

Definition at line 77 of file calibType.py.

◆ _seqname

lsst.ip.isr.calibType.IsrCalib._seqname = None
protectedinherited

Definition at line 78 of file calibType.py.

◆ _slotName

lsst.ip.isr.calibType.IsrCalib._slotName = None
protectedinherited

Definition at line 71 of file calibType.py.

◆ _VERSION

int lsst.ip.isr.calibType.IsrCalib._VERSION = 0
staticprotectedinherited

Definition at line 66 of file calibType.py.

◆ log

lsst.ip.isr.calibType.IsrCalib.log = log if log else logging.getLogger(__name__)
inherited

Definition at line 96 of file calibType.py.

◆ requiredAttributes

lsst.ip.isr.calibType.IsrCalib.requiredAttributes = set(["_OBSTYPE", "_SCHEMA", "_VERSION"])
inherited

Definition at line 90 of file calibType.py.


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