LSST Applications 27.0.0,g0265f82a02+469cd937ee,g02d81e74bb+21ad69e7e1,g1470d8bcf6+cbe83ee85a,g2079a07aa2+e67c6346a6,g212a7c68fe+04a9158687,g2305ad1205+94392ce272,g295015adf3+81dd352a9d,g2bbee38e9b+469cd937ee,g337abbeb29+469cd937ee,g3939d97d7f+72a9f7b576,g487adcacf7+71499e7cba,g50ff169b8f+5929b3527e,g52b1c1532d+a6fc98d2e7,g591dd9f2cf+df404f777f,g5a732f18d5+be83d3ecdb,g64a986408d+21ad69e7e1,g858d7b2824+21ad69e7e1,g8a8a8dda67+a6fc98d2e7,g99cad8db69+f62e5b0af5,g9ddcbc5298+d4bad12328,ga1e77700b3+9c366c4306,ga8c6da7877+71e4819109,gb0e22166c9+25ba2f69a1,gb6a65358fc+469cd937ee,gbb8dafda3b+69d3c0e320,gc07e1c2157+a98bf949bb,gc120e1dc64+615ec43309,gc28159a63d+469cd937ee,gcf0d15dbbd+72a9f7b576,gdaeeff99f8+a38ce5ea23,ge6526c86ff+3a7c1ac5f1,ge79ae78c31+469cd937ee,gee10cc3b42+a6fc98d2e7,gf1cff7945b+21ad69e7e1,gfbcc870c63+9a11dc8c8f
LSST Data Management Base Package
Loading...
Searching...
No Matches
visualizeVisit.py
Go to the documentation of this file.
1# This file is part of pipe_tasks.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22__all__ = [
23 "VisualizeBinExpConfig",
24 "VisualizeBinExpTask",
25 "VisualizeMosaicExpConfig",
26 "VisualizeMosaicExpTask",
27]
28
29import lsst.afw.cameraGeom.utils as afwUtils
30import lsst.afw.image as afwImage
31import lsst.afw.math as afwMath
32import lsst.pex.config as pexConfig
33import lsst.pipe.base as pipeBase
34import lsst.pipe.base.connectionTypes as cT
35import numpy as np
36
37
38class VisualizeBinExpConnections(pipeBase.PipelineTaskConnections, dimensions=("instrument", "detector")):
39 inputExp = cT.Input(
40 name="calexp",
41 doc="Input exposure data to mosaic.",
42 storageClass="ExposureF",
43 dimensions=("instrument", "detector"),
44 )
45 camera = cT.PrerequisiteInput(
46 name="camera",
47 doc="Input camera to use for mosaic geometry.",
48 storageClass="Camera",
49 dimensions=("instrument",),
50 isCalibration=True,
51 )
52
53 outputExp = cT.Output(
54 name="calexpBin",
55 doc="Output binned image.",
56 storageClass="ExposureF",
57 dimensions=("instrument", "detector"),
58 )
59
60
61class VisualizeBinExpConfig(pipeBase.PipelineTaskConfig, pipelineConnections=VisualizeBinExpConnections):
62 """Configuration for focal plane visualization."""
63
64 binning = pexConfig.Field(
65 dtype=int,
66 default=8,
67 doc="Binning factor to apply to each input exposure's image data.",
68 )
69 detectorKeyword = pexConfig.Field(
70 dtype=str,
71 default="DET-ID",
72 doc="Metadata keyword to use to find detector if not available from input.",
73 )
74
75
76class VisualizeBinExpTask(pipeBase.PipelineTask):
77 """Bin the detectors of an exposure.
78
79 The outputs of this task should be passed to
80 VisualizeMosaicExpTask to be mosaicked into a full focal plane
81 visualization image.
82 """
83
84 ConfigClass = VisualizeBinExpConfig
85 _DefaultName = "VisualizeBinExp"
86
87 def run(self, inputExp, camera):
88 """Bin input image, attach associated detector.
89
90 Parameters
91 ----------
92 inputExp : `lsst.afw.image.Exposure`
93 Input exposure data to bin.
94 camera : `lsst.afw.cameraGeom.Camera`
95 Input camera to use for mosaic geometry.
96
97 Returns
98 -------
99 output : `lsst.pipe.base.Struct`
100 Results struct with attribute:
101
102 ``outputExp``
103 Binned version of input image (`lsst.afw.image.Exposure`).
104 """
105 if inputExp.getDetector() is None:
106 detectorId = inputExp.getMetadata().get(self.config.detectorKeyword)
107 if detectorId is not None:
108 inputExp.setDetector(camera[detectorId])
109
110 binned = inputExp.getMaskedImage()
111 binned = afwMath.binImage(binned, self.config.binning)
112 outputExp = afwImage.makeExposure(binned)
113
114 outputExp.setInfo(inputExp.getInfo())
115
116 return pipeBase.Struct(outputExp=outputExp)
117
118
119class VisualizeMosaicExpConnections(pipeBase.PipelineTaskConnections, dimensions=("instrument",)):
120 inputExps = cT.Input(
121 name="calexpBin",
122 doc="Input binned images mosaic.",
123 storageClass="ExposureF",
124 dimensions=("instrument", "detector"),
125 multiple=True,
126 )
127 camera = cT.PrerequisiteInput(
128 name="camera",
129 doc="Input camera to use for mosaic geometry.",
130 storageClass="Camera",
131 dimensions=("instrument",),
132 isCalibration=True,
133 )
134
135 outputData = cT.Output(
136 name="calexpFocalPlane",
137 doc="Output binned mosaicked frame.",
138 storageClass="ImageF",
139 dimensions=("instrument",),
140 )
141
142
144 pipeBase.PipelineTaskConfig, pipelineConnections=VisualizeMosaicExpConnections
145):
146 """Configuration for focal plane visualization."""
147
148 binning = pexConfig.Field(
149 dtype=int,
150 default=8,
151 doc="Binning factor previously applied to input exposures.",
152 )
153
154
155class VisualizeMosaicExpTask(pipeBase.PipelineTask):
156 """Task to mosaic binned products.
157
158 The config.binning parameter must match that used in the
159 VisualizeBinExpTask. Otherwise there will be a mismatch between
160 the input image size and the expected size of that image in the
161 full focal plane frame.
162 """
163
164 ConfigClass = VisualizeMosaicExpConfig
165 _DefaultName = "VisualizeMosaicExp"
166
167 def makeCameraImage(self, inputExps, camera, binning):
168 """Make an image of an entire focal plane.
169
170 Parameters
171 ----------
172 exposures: `dict` [`int`, `lsst.afw.image.Exposure`]
173 CCD exposures, binned by `binning`. The keys are the
174 detectorIDs, with the values the binned image exposure.
175
176 Returns
177 -------
178 image : `lsst.afw.image.Image`
179 Image mosaicked from the individual binned images for each
180 detector.
181 """
182 image = afwUtils.makeImageFromCamera(
183 camera, imageSource=ImageSource(inputExps), imageFactory=afwImage.ImageF, binSize=binning
184 )
185 return image
186
187 def run(self, inputExps, camera, inputIds=None):
188 """Mosaic inputs together to create focal plane image.
189
190 Parameters
191 ----------
192 inputExps : `list` [`lsst.afw.image.Exposure`]
193 Input exposure data to bin.
194 camera : `lsst.afw.cameraGeom.Camera`
195 Input camera to use for mosaic geometry.
196 inputIds : `list` [`int`], optional
197 Optional list providing exposure IDs corresponding to input
198 exposures. Will be generated via the exposure data `getDetector`
199 method if not provided.
200
201 Returns
202 -------
203 output : `lsst.pipe.base.Struct`
204 Results struct with attribute:
205
206 ``outputExp``
207 Binned version of input image (`lsst.afw.image.Exposure`).
208 """
209 if not inputIds:
210 inputIds = [exp.getDetector().getId() for exp in inputExps]
211 expDict = {id: exp for id, exp in zip(inputIds, inputExps)}
212 image = self.makeCameraImage(expDict, camera, self.config.binning)
213
214 return pipeBase.Struct(outputData=image)
215
216
218 """Source of images for makeImageFromCamera"""
219
220 def __init__(self, exposures):
221 self.exposures = exposures
222 self.isTrimmed = True
223 self.background = np.nan
224
225 def getCcdImage(self, detector, imageFactory, binSize):
226 """Provide image of CCD to makeImageFromCamera
227
228 Parameters
229 ----------
230 detector : `int`
231 Detector ID to get image data for.
232 imageFactory : `lsst.afw.image.Image`
233 Type of image to construct.
234 binSize : `int`
235 Binsize to use to recompute dimensions.
236
237 Returns
238 -------
239 image : `lsst.afw.image.Image`
240 Appropriately rotated, binned, and transformed
241 image to be mosaicked.
242 detector : `lsst.afw.cameraGeom.Detector`
243 Camera detector that the returned image data
244 belongs to.
245 """
246 detId = detector.getId()
247
248 if detId not in self.exposures:
249 dims = detector.getBBox().getDimensions() / binSize
250 image = imageFactory(*[int(xx) for xx in dims])
251 image.set(self.background)
252 else:
253 image = self.exposures[detector.getId()]
254 if hasattr(image, "getMaskedImage"):
255 image = image.getMaskedImage()
256 if hasattr(image, "getMask"):
257 mask = image.getMask()
258 isBad = mask.getArray() & mask.getPlaneBitMask("NO_DATA") > 0
259 image = image.clone()
260 image.getImage().getArray()[isBad] = self.background
261 if hasattr(image, "getImage"):
262 image = image.getImage()
263
264 # afwMath.rotateImageBy90 checks NQuarter values,
265 # so we don't need to here.
266 image = afwMath.rotateImageBy90(image, detector.getOrientation().getNQuarter())
267 return image, detector
getCcdImage(self, detector, imageFactory, binSize)
makeCameraImage(self, inputExps, camera, binning)
run(self, inputExps, camera, inputIds=None)
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.
Definition Exposure.h:484
std::shared_ptr< ImageT > rotateImageBy90(ImageT const &image, int nQuarter)
Rotate an image by an integral number of quarter turns.
std::shared_ptr< ImageT > binImage(ImageT const &inImage, int const binX, int const binY, lsst::afw::math::Property const flags=lsst::afw::math::MEAN)
Definition binImage.cc:44