6 __all__ = [
'CalexpCutoutTaskConfig',
'CalexpCutoutTask']
7 DETECTOR_DIMENSIONS = (
'instrument',
'visit',
'detector')
11 dimensions=DETECTOR_DIMENSIONS,
13 """Connections class for CalexpCutoutTask
15 in_table = pipeBase.connectionTypes.Input(
16 doc=
"Locations for cutouts",
17 name=
"cutout_positions",
18 storageClass=
"AstropyQTable",
19 dimensions=DETECTOR_DIMENSIONS,
21 calexp = pipeBase.connectionTypes.Input(
24 storageClass=
"ExposureF",
25 dimensions=DETECTOR_DIMENSIONS,
27 cutouts = pipeBase.connectionTypes.Output(
29 name=
"calexp_cutouts",
30 storageClass=
"Stamps",
31 dimensions=DETECTOR_DIMENSIONS,
36 pipelineConnections=CalexpCutoutTaskConnections):
37 """Configuration for CalexpCutoutTask
39 max_cutouts = Field(dtype=int, default=100, doc=
'Maximum number of entries to process. '
40 'The result will be the first N in the input table.')
41 skip_bad = Field(dtype=bool, default=
True, doc=
'Skip cutouts that do not fall completely within'
42 ' the calexp bounding box? If set to False a ValueError'
43 ' is raised instead.')
47 """Task for computing cutouts on a specific calexp given
48 positions and sizes of the stamps.
50 ConfigClass = CalexpCutoutTaskConfig
51 _DefaultName =
"calexpCutoutTask"
53 def run(self, in_table, calexp):
54 """Compute and return the cutouts.
58 in_table : `astropy.QTable`
59 A table containing at least the following columns: position, size.
60 The position should be an `astropy.SkyCoord`. The size is
61 the size of the cutout in pixels. All cutouts are square in pixel
63 calexp : `lsst.afw.image.ExposureF`
64 The calibrated exposure from which to extract cutouts
68 output : `lsst.pipe.base.Struct`
71 * cutouts: an `lsst.meas.algorithms.Stamps` object
72 that wraps a list of masked images of the cutouts and a
73 `PropertyList` containing the metadata to be persisted
74 with the cutouts. The exposure metadata is preserved and,
75 in addition, arrays holding the RA and Dec of each stamp
76 in degrees are added to the metadata. Note: the origin
77 of the output stamps is `lsst.afw.image.PARENT`.
78 * skipped_positions: a `list` of `lsst.geom.SpherePoint` objects for
79 stamps that were skiped for being off the image
80 or partially off the image
85 If the input catalog doesn't have the required columns,
86 a ValueError is raised
88 if 'position' not in in_table.colnames
or 'size' not in in_table.colnames:
89 raise ValueError(
'Required column missing from the input table. '
90 'Required columns are "position" and "size".'
91 f
'The column names are: {in_table.colnames}')
92 max_idx = self.config.max_cutouts
95 mim = calexp.getMaskedImage()
98 skipped_positions = []
99 for rec
in in_table[:max_idx]:
100 ra = rec[
'position'].ra.degree
101 dec = rec[
'position'].dec.degree
106 pix = wcs.skyToPixel(pt)
107 size = rec[
'size'].value
111 if not mim.getBBox().contains(box):
112 if not self.config.skip_bad:
113 raise ValueError(f
'Cutout bounding box is not completely contained in the image: {box}')
115 skipped_positions.append(pt)
117 sub = mim.Factory(mim, box)
118 stamp = Stamp(stamp_im=sub, position=pt)
119 cutout_list.append(stamp)
120 metadata = calexp.getMetadata()
121 metadata[
'RA_DEG'] = ras
122 metadata[
'DEC_DEG'] = decs
123 return pipeBase.Struct(cutouts=Stamps(cutout_list, metadata=metadata),
124 skipped_positions=skipped_positions)