22 """Collection of small images (stamps).
25 __all__ = [
"Stamp",
"Stamps",
"StampsBase",
"writeFits",
"readFitsWithOptions"]
27 from collections.abc
import Sequence
29 from dataclasses
import dataclass
34 from lsst.geom import Box2I, Point2I, Extent2I, Angle, degrees, SpherePoint
38 def writeFits(filename, stamp_ims, metadata, write_mask, write_variance):
39 """Write a single FITS file containing all stamps.
44 A string indicating the output filename
45 stamps_ims : iterable of `lsst.afw.image.MaskedImageF`
46 An iterable of masked images
47 metadata : `PropertyList`
48 A collection of key, value metadata pairs to be
49 written to the primary header
51 Write the mask data to the output file?
52 write_variance : `bool`
53 Write the variance data to the output file?
55 metadata[
'HAS_MASK'] = write_mask
56 metadata[
'HAS_VARIANCE'] = write_variance
57 metadata[
'N_STAMPS'] = len(stamp_ims)
59 fitsPrimary = afwFits.Fits(filename,
"w")
60 fitsPrimary.createEmpty()
61 fitsPrimary.writeMetadata(metadata)
62 fitsPrimary.closeFile()
65 for i, stamp
in enumerate(stamp_ims):
68 metadata.update({
'EXTVER': i+1,
'EXTNAME':
'IMAGE'})
69 stamp.getImage().
writeFits(filename, metadata=metadata, mode=
'a')
72 metadata.update({
'EXTVER': i+1,
'EXTNAME':
'MASK'})
73 stamp.getMask().
writeFits(filename, metadata=metadata, mode=
'a')
76 metadata.update({
'EXTVER': i+1,
'EXTNAME':
'VARIANCE'})
77 stamp.getVariance().
writeFits(filename, metadata=metadata, mode=
'a')
82 """Read stamps from FITS file, allowing for only a
83 subregion of the stamps to be read.
88 A string indicating the file to read
89 stamp_factory : classmethod
90 A factory function defined on a dataclass for constructing
91 stamp objects a la `lsst.meas.alrogithm.Stamp`
92 options : `PropertyList` or `dict`
93 A collection of parameters. If it contains a bounding box
94 (``bbox`` key), or if certain other keys (``llcX``, ``llcY``,
95 ``width``, ``height``) are available for one to be constructed,
96 the bounding box is passed to the ``FitsReader`` in order to
101 stamps : `list` of dataclass objects like `Stamp`, PropertyList
102 A tuple of a list of `Stamp`-like objects
103 metadata : `PropertyList`
107 metadata = afwFits.readMetadata(filename, hdu=0)
108 f = afwFits.Fits(filename,
'r')
109 nExtensions = f.countHdus()
110 nStamps = metadata[
"N_STAMPS"]
115 if "bbox" in options.keys():
116 kwargs[
"bbox"] = options[
"bbox"]
118 elif "llcX" in options.keys():
119 llcX = options[
"llcX"]
120 llcY = options[
"llcY"]
121 width = options[
"width"]
122 height = options[
"height"]
124 kwargs[
"bbox"] = bbox
128 for idx
in range(nExtensions-1):
129 md = afwFits.readMetadata(filename, hdu=idx+1)
130 if md[
'EXTNAME']
in (
'IMAGE',
'VARIANCE'):
131 reader = afwImage.ImageFitsReader(filename, hdu=idx+1)
132 elif md[
'EXTNAME'] ==
'MASK':
133 reader = afwImage.MaskFitsReader(filename, hdu=idx+1)
135 raise ValueError(f
"Unknown extension type: {md['EXTNAME']}")
136 stamp_parts.setdefault(md[
'EXTVER'], {})[md[
'EXTNAME'].lower()] = reader.read(**kwargs)
137 if len(stamp_parts) != nStamps:
138 raise ValueError(f
'Number of stamps read ({len(stamp_parts)}) does not agree with the '
139 f
'number of stamps recorded in the metadata ({nStamps}).')
142 for k
in range(nStamps):
144 maskedImage = afwImage.MaskedImageF(**stamp_parts[k+1])
145 stamps.append(stamp_factory(maskedImage, metadata, k))
147 return stamps, metadata
152 """Single abstract stamp
156 Inherit from this class to add metadata to the stamp
162 """This method is needed to service the FITS reader.
163 We need a standard interface to construct objects like this.
164 Parameters needed to construct this object are passed in via
165 a metadata dictionary and then passed to the constructor of
170 stamp : `lsst.afw.image.MaskedImage`
171 Pixel data to pass to the constructor
173 Dictionary containing the information
174 needed by the constructor.
176 Index into the lists in ``metadata``
180 stamp : `AbstractStamp`
181 An instance of this class
183 raise NotImplementedError
192 stamp_im : `lsst.afw.image.MaskedImageF`
193 The actual pixel values for the postage stamp
194 position : `lsst.geom.SpherePoint`
195 Position of the center of the stamp. Note the user
196 must keep track of the coordinate system
198 stamp_im: afwImage.maskedImage.MaskedImageF
199 position: SpherePoint
203 """This method is needed to service the FITS reader.
204 We need a standard interface to construct objects like this.
205 Parameters needed to construct this object are passed in via
206 a metadata dictionary and then passed to the constructor of
207 this class. If lists of values are passed with the following
208 keys, they will be passed to the constructor, otherwise dummy
209 values will be passed: RA_DEG, DEC_DEG. They should
210 each point to lists of values.
214 stamp : `lsst.afw.image.MaskedImage`
215 Pixel data to pass to the constructor
217 Dictionary containing the information
218 needed by the constructor.
220 Index into the lists in ``metadata``
225 An instance of this class
227 if 'RA_DEG' in metadata
and 'DEC_DEG' in metadata:
228 return cls(stamp_im=stamp_im,
230 Angle(metadata.getArray(
'DEC_DEG')[index], degrees)))
236 """Collection of stamps and associated metadata.
241 This should be an iterable of dataclass objects
242 a la ``lsst.meas.algorithms.Stamp``.
243 metadata : `lsst.daf.base.PropertyList`, optional
244 Metadata associated with the bright stars.
245 use_mask : `bool`, optional
246 If ``True`` read and write the mask data. Default ``True``.
247 use_variance : `bool`, optional
248 If ``True`` read and write the variance data. Default ``True``.
252 A butler can be used to read only a part of the stamps,
255 >>> starSubregions = butler.get("brightStarStamps_sub", dataId, bbox=bbox)
258 def __init__(self, stamps, metadata=None, use_mask=True, use_variance=True):
259 if not hasattr(stamps,
'__iter__'):
260 raise ValueError(
'The stamps parameter must be iterable.')
262 if not isinstance(stamp, AbstractStamp):
263 raise ValueError(
'The entries in stamps must inherit from AbstractStamp. '
264 f
'Got {type(stamp)}.')
273 """Build an instance of this class from a file.
278 Name of the file to read
280 raise NotImplementedError
285 """Build an instance of this class with options.
290 Name of the file to read
291 options : `PropertyList`
292 Collection of metadata parameters
294 raise NotImplementedError
297 def _refresh_metadata(self):
298 """Make sure metadata is up to date since this object
301 raise NotImplementedError
304 """Write this object to a file.
309 Name of file to write
316 return len(self.
_stamps_stamps)
319 return self.
_stamps_stamps[index]
322 return iter(self.
_stamps_stamps)
325 """Retrieve star images.
330 `list` [`lsst.afw.image.maskedImage.maskedImage.MaskedImageF`]
332 return [stamp.stamp_im
for stamp
in self.
_stamps_stamps]
340 def _refresh_metadata(self):
342 self.
_metadata_metadata[
'RA_DEG'] = [p.getRa().asDegrees()
for p
in positions]
343 self.
_metadata_metadata[
'DEC_DEG'] = [p.getDec().asDegrees()
for p
in positions]
346 return [s.position
for s
in self.
_stamps_stamps]
349 """Add an additional stamp.
354 Stamp object to append.
356 if not isinstance(item, Stamp):
357 raise ValueError(
"Ojbects added must be a Stamp object.")
362 """Extend Stamps instance by appending elements from another instance.
366 stamps_list : `list` [`Stamp`]
367 List of Stamp object to append.
370 if not isinstance(s, Stamp):
371 raise ValueError(
'Can only extend with Stamp objects')
372 self.
_stamps_stamps += stamp_list
376 """Build an instance of this class from a file.
381 Name of the file to read
386 An instance of this class
392 """Build an instance of this class with options.
397 Name of the file to read
398 options : `PropertyList` or `dict`
399 Collection of metadata parameters
404 An instance of this class
407 return cls(stamps, metadata=metadata, use_mask=metadata[
'HAS_MASK'],
408 use_variance=metadata[
'HAS_VARIANCE'])
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)
def writeFits(filename, stamp_ims, metadata, write_mask, write_variance)
def readFitsWithOptions(filename, stamp_factory, options)