22 """Collection of small images (stamps).
25 __all__ = [
"Stamp",
"Stamps",
"StampsBase",
"writeFits",
"readFitsWithOptions"]
29 from dataclasses
import dataclass
34 from lsst.geom import Box2I, Point2I, Extent2I, Angle, degrees, SpherePoint
36 from lsst.daf.butler.core.utils
import getFullTypeName
40 def writeFits(filename, stamp_ims, metadata, type_name, write_mask, write_variance):
41 """Write a single FITS file containing all stamps.
46 A string indicating the output filename
47 stamps_ims : iterable of `lsst.afw.image.MaskedImageF`
48 An iterable of masked images
49 metadata : `PropertyList`
50 A collection of key, value metadata pairs to be
51 written to the primary header
53 Python type name of the StampsBase subclass to use
55 Write the mask data to the output file?
56 write_variance : `bool`
57 Write the variance data to the output file?
59 metadata[
'HAS_MASK'] = write_mask
60 metadata[
'HAS_VARIANCE'] = write_variance
61 metadata[
'N_STAMPS'] = len(stamp_ims)
62 metadata[
'STAMPCLS'] = type_name
64 metadata[
'VERSION'] = 1
66 fitsPrimary = afwFits.Fits(filename,
"w")
67 fitsPrimary.createEmpty()
68 fitsPrimary.writeMetadata(metadata)
69 fitsPrimary.closeFile()
72 for i, stamp
in enumerate(stamp_ims):
75 metadata.update({
'EXTVER': i+1,
'EXTNAME':
'IMAGE'})
76 stamp.getImage().
writeFits(filename, metadata=metadata, mode=
'a')
79 metadata.update({
'EXTVER': i+1,
'EXTNAME':
'MASK'})
80 stamp.getMask().
writeFits(filename, metadata=metadata, mode=
'a')
83 metadata.update({
'EXTVER': i+1,
'EXTNAME':
'VARIANCE'})
84 stamp.getVariance().
writeFits(filename, metadata=metadata, mode=
'a')
89 """Read stamps from FITS file, allowing for only a
90 subregion of the stamps to be read.
95 A string indicating the file to read
96 stamp_factory : classmethod
97 A factory function defined on a dataclass for constructing
98 stamp objects a la `lsst.meas.alrogithm.Stamp`
99 options : `PropertyList` or `dict`
100 A collection of parameters. If it contains a bounding box
101 (``bbox`` key), or if certain other keys (``llcX``, ``llcY``,
102 ``width``, ``height``) are available for one to be constructed,
103 the bounding box is passed to the ``FitsReader`` in order to
108 stamps : `list` of dataclass objects like `Stamp`, PropertyList
109 A tuple of a list of `Stamp`-like objects
110 metadata : `PropertyList`
114 metadata = afwFits.readMetadata(filename, hdu=0)
115 f = afwFits.Fits(filename,
'r')
116 nExtensions = f.countHdus()
117 nStamps = metadata[
"N_STAMPS"]
122 if "bbox" in options.keys():
123 kwargs[
"bbox"] = options[
"bbox"]
125 elif "llcX" in options.keys():
126 llcX = options[
"llcX"]
127 llcY = options[
"llcY"]
128 width = options[
"width"]
129 height = options[
"height"]
131 kwargs[
"bbox"] = bbox
135 for idx
in range(nExtensions-1):
136 md = afwFits.readMetadata(filename, hdu=idx+1)
137 if md[
'EXTNAME']
in (
'IMAGE',
'VARIANCE'):
139 elif md[
'EXTNAME'] ==
'MASK':
142 raise ValueError(f
"Unknown extension type: {md['EXTNAME']}")
143 stamp_parts.setdefault(md[
'EXTVER'], {})[md[
'EXTNAME'].lower()] = reader.read(**kwargs)
144 if len(stamp_parts) != nStamps:
145 raise ValueError(f
'Number of stamps read ({len(stamp_parts)}) does not agree with the '
146 f
'number of stamps recorded in the metadata ({nStamps}).')
149 for k
in range(nStamps):
151 maskedImage = afwImage.MaskedImageF(**stamp_parts[k+1])
152 stamps.append(stamp_factory(maskedImage, metadata, k))
154 return stamps, metadata
159 """Single abstract stamp
163 Inherit from this class to add metadata to the stamp
169 """This method is needed to service the FITS reader.
170 We need a standard interface to construct objects like this.
171 Parameters needed to construct this object are passed in via
172 a metadata dictionary and then passed to the constructor of
177 stamp : `lsst.afw.image.MaskedImage`
178 Pixel data to pass to the constructor
180 Dictionary containing the information
181 needed by the constructor.
183 Index into the lists in ``metadata``
187 stamp : `AbstractStamp`
188 An instance of this class
190 raise NotImplementedError
199 stamp_im : `lsst.afw.image.MaskedImageF`
200 The actual pixel values for the postage stamp
201 position : `lsst.geom.SpherePoint`
202 Position of the center of the stamp. Note the user
203 must keep track of the coordinate system
205 stamp_im: afwImage.maskedImage.MaskedImageF
206 position: SpherePoint
210 """This method is needed to service the FITS reader.
211 We need a standard interface to construct objects like this.
212 Parameters needed to construct this object are passed in via
213 a metadata dictionary and then passed to the constructor of
214 this class. If lists of values are passed with the following
215 keys, they will be passed to the constructor, otherwise dummy
216 values will be passed: RA_DEG, DEC_DEG. They should
217 each point to lists of values.
221 stamp : `lsst.afw.image.MaskedImage`
222 Pixel data to pass to the constructor
224 Dictionary containing the information
225 needed by the constructor.
227 Index into the lists in ``metadata``
232 An instance of this class
234 if 'RA_DEG' in metadata
and 'DEC_DEG' in metadata:
235 return cls(stamp_im=stamp_im,
237 Angle(metadata.getArray(
'DEC_DEG')[index], degrees)))
243 """Collection of stamps and associated metadata.
248 This should be an iterable of dataclass objects
249 a la ``lsst.meas.algorithms.Stamp``.
250 metadata : `lsst.daf.base.PropertyList`, optional
251 Metadata associated with the bright stars.
252 use_mask : `bool`, optional
253 If ``True`` read and write the mask data. Default ``True``.
254 use_variance : `bool`, optional
255 If ``True`` read and write the variance data. Default ``True``.
259 A butler can be used to read only a part of the stamps,
262 >>> starSubregions = butler.get("brightStarStamps_sub", dataId, bbox=bbox)
265 def __init__(self, stamps, metadata=None, use_mask=True, use_variance=True):
266 if not hasattr(stamps,
'__iter__'):
267 raise ValueError(
'The stamps parameter must be iterable.')
269 if not isinstance(stamp, AbstractStamp):
270 raise ValueError(
'The entries in stamps must inherit from AbstractStamp. '
271 f
'Got {type(stamp)}.')
279 """Build an instance of this class from a file.
284 Name of the file to read
291 """Build an instance of this class with options.
296 Name of the file to read
297 options : `PropertyList`
298 Collection of metadata parameters
301 if cls
is not StampsBase:
302 raise NotImplementedError(
303 f
"Please implement specific FITS reader for class {cls}"
307 metadata = afwFits.readMetadata(filename, hdu=0)
308 type_name = metadata.get(
"STAMPCLS")
309 if type_name
is None:
311 f
"No class name in file {filename}. Unable to instantiate correct"
312 " stamps subclass. Is this an old version format Stamps file?"
322 def _refresh_metadata(self):
323 """Make sure metadata is up to date since this object
326 raise NotImplementedError
329 """Write this object to a file.
334 Name of file to write
338 type_name = getFullTypeName(self)
342 return len(self.
_stamps_stamps)
345 return self.
_stamps_stamps[index]
351 """Retrieve star images.
356 `list` [`lsst.afw.image.maskedImage.maskedImage.MaskedImageF`]
358 return [stamp.stamp_im
for stamp
in self.
_stamps_stamps]
366 def _refresh_metadata(self):
368 self.
_metadata_metadata[
'RA_DEG'] = [p.getRa().asDegrees()
for p
in positions]
369 self.
_metadata_metadata[
'DEC_DEG'] = [p.getDec().asDegrees()
for p
in positions]
372 return [s.position
for s
in self.
_stamps_stamps]
375 """Add an additional stamp.
380 Stamp object to append.
382 if not isinstance(item, Stamp):
383 raise ValueError(
"Objects added must be a Stamp object.")
388 """Extend Stamps instance by appending elements from another instance.
392 stamps_list : `list` [`Stamp`]
393 List of Stamp object to append.
396 if not isinstance(s, Stamp):
397 raise ValueError(
'Can only extend with Stamp objects')
398 self.
_stamps_stamps += stamp_list
402 """Build an instance of this class from a file.
407 Name of the file to read
412 An instance of this class
418 """Build an instance of this class with options.
423 Name of the file to read
424 options : `PropertyList` or `dict`
425 Collection of metadata parameters
430 An instance of this class
433 return cls(stamps, metadata=metadata, use_mask=metadata[
'HAS_MASK'],
434 use_variance=metadata[
'HAS_VARIANCE'])
A FITS reader class for regular Images.
A FITS reader class for Masks.
Class for storing ordered metadata with comments.
A class representing an angle.
An integer coordinate rectangle.
Point in an unspecified spherical coordinate system.
def factory(cls, stamp_im, metadata, index)
def factory(cls, stamp_im, metadata, index)
def readFits(cls, filename)
def __init__(self, stamps, metadata=None, use_mask=True, use_variance=True)
def __getitem__(self, index)
def writeFits(self, filename)
def _refresh_metadata(self)
def readFitsWithOptions(cls, filename, options)
def getMaskedImages(self)
def extend(self, stamp_list)
def readFits(cls, filename)
def readFitsWithOptions(cls, filename, options)
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Extent< int, 2 > Extent2I
def writeFits(filename, stamp_ims, metadata, type_name, write_mask, write_variance)
def readFitsWithOptions(filename, stamp_factory, options)