22__all__ = [
"BinExposureTask",
27import lsst.pipe.base.connectionTypes
as cT
30from lsst.utils.timer
import timeMethod
35 pipeBase.PipelineTaskConnections,
36 dimensions=(
"instrument",
"exposure",
"detector"),
37 defaultTemplates={
"inputName":
"postISRCCD",
"outputName":
"postISRCCDBin"}
40 inputExposure = cT.Input(
42 doc=
"Input exposure to bin.",
43 storageClass=
"Exposure",
44 dimensions=[
"instrument",
"exposure",
"detector"],
46 binnedExposure = cT.Output(
48 doc=
"Binned exsposure.",
49 storageClass=
"Exposure",
50 dimensions=[
"instrument",
"exposure",
"detector"],
53 def __init__(self, *, config=None):
54 """Customize the connections and storageClass for a specific
55 instance. This enables both to be dynamically set at runtime,
56 allowing BinExposureTask to work with different types of
57 Exposures such as postISRCCD, calexp, deepCoadd_calexp, etc.
61 config : `BinExposureConfig`
62 A config for `BinExposureTask`.
64 super().__init__(config=config)
65 if config
and config.exposureDimensions != self.inputExposure.dimensions:
66 self.dimensions.clear()
67 self.dimensions.update(config.exposureDimensions)
68 self.inputExposure = cT.Input(
69 name=self.inputExposure.name,
70 doc=self.inputExposure.doc,
71 storageClass=self.inputExposure.storageClass,
72 dimensions=frozenset(config.exposureDimensions),
74 self.binnedExposure = cT.Output(
75 name=self.binnedExposure.name,
76 doc=self.binnedExposure.doc,
77 storageClass=self.binnedExposure.storageClass,
78 dimensions=frozenset(config.exposureDimensions),
80 if config
and config.exposureStorageClass != self.inputExposure.storageClass:
81 self.inputExposure = cT.Input(
82 name=self.inputExposure.name,
83 doc=self.inputExposure.doc,
84 storageClass=config.exposureStorageClass,
85 dimensions=self.inputExposure.dimensions,
87 self.binnedExposure = cT.Output(
88 name=self.binnedExposure.name,
89 doc=self.binnedExposure.doc,
90 storageClass=config.exposureStorageClass,
91 dimensions=self.binnedExposure.dimensions,
95class BinExposureConfig(
96 pipeBase.PipelineTaskConfig,
97 pipelineConnections=BinExposureConnections
99 """Config for BinExposureTask"""
100 exposureDimensions = pexConfig.ListField(
102 default=sorted(BinExposureConnections.dimensions),
104 doc=
"Override for the dimensions of the input and binned exposures.",
106 exposureStorageClass = pexConfig.Field(
110 "Override the storageClass of the input and binned exposures. "
111 "Must be of type lsst.afw.Image.Exposure, or one of its subtypes."
114 binFactor = pexConfig.Field(
116 doc=
"Binning factor applied to both spatial dimensions.",
118 check=
lambda x: x > 1,
122class BinExposureTask(pipeBase.PipelineTask):
123 """Perform an nxn binning of an Exposure dataset type.
125 The binning factor is the same in both spatial dimensions (i.e.,
126 an nxn binning is performed). Each of the input Exposure's image
127 arrays are binned by the same factor.
130 ConfigClass = BinExposureConfig
131 _DefaultName =
"binExposure"
134 def run(self, inputExposure, binFactor=None):
135 """Perform an nxn binning of an Exposure.
139 inputExposure : `lsst.afw.image.Exposure` or one of its
141 Exposure to spatially bin
142 binFactor : `int`, optional.
143 nxn binning factor. If not provided then self.config.binFactor
148 result : `lsst.pipe.base.Struct`
149 Results as a struct with attributes:
152 Binned exposure (`lsst.afw.image.Exposure` or one of its
153 sub-types. The type matches that of the inputExposure).
156 binFactor = self.config.binFactor
157 return pipeBase.Struct(
158 binnedExposure=binExposure(inputExposure, binFactor)
162def binExposure(inputExposure, binFactor=8):
163 """Bin an exposure to reduce its spatial dimensions.
165 Performs an nxn binning of the input exposure, reducing both spatial
166 dimensions of each of the input exposure's image data by the provided
171 inputExposure: `lsst.afw.image.Exposure` or one of its sub-types.
172 Input exposure data to bin.
174 Binning factor to apply to each input exposure's image data.
179 binnedExposure: `lsst.afw.image.Exposure` or one of its sub-types.
180 Binned version of input image.
185 Raised if either the binning factor is not of type `int`, or if the
186 input data to be binned is not of type `lsst.afw.image.Exposure`
187 or one of its sub-types.
190 if not isinstance(binFactor, int):
191 raise TypeError(
"binFactor must be of type int")
193 raise TypeError(
"inputExp must be of type lsst.afw.image.Exposure or one of its sub-tyoes.")
195 binned = inputExposure.getMaskedImage()
199 binnedExposure.setInfo(inputExposure.getInfo())
201 return binnedExposure
A class to contain the data, WCS, and other information needed to describe an image of the sky.
std::shared_ptr< Exposure< ImagePixelT, MaskPixelT, VariancePixelT > > makeExposure(MaskedImage< ImagePixelT, MaskPixelT, VariancePixelT > &mimage, std::shared_ptr< geom::SkyWcs const > wcs=std::shared_ptr< geom::SkyWcs const >())
A function to return an Exposure of the correct type (cf.
std::shared_ptr< ImageT > binImage(ImageT const &inImage, int const binX, int const binY, lsst::afw::math::Property const flags=lsst::afw::math::MEAN)