LSST Applications g0da5cf3356+25b44625d0,g17e5ecfddb+50a5ac4092,g1c76d35bf8+585f0f68a2,g295839609d+8ef6456700,g2e2c1a68ba+cc1f6f037e,g38293774b4+62d12e78cb,g3b44f30a73+2891c76795,g48ccf36440+885b902d19,g4b2f1765b6+0c565e8f25,g5320a0a9f6+bd4bf1dc76,g56364267ca+403c24672b,g56b687f8c9+585f0f68a2,g5c4744a4d9+78cd207961,g5ffd174ac0+bd4bf1dc76,g6075d09f38+3075de592a,g667d525e37+cacede5508,g6f3e93b5a3+da81c812ee,g71f27ac40c+cacede5508,g7212e027e3+eb621d73aa,g774830318a+18d2b9fa6c,g7985c39107+62d12e78cb,g79ca90bc5c+fa2cc03294,g881bdbfe6c+cacede5508,g91fc1fa0cf+82a115f028,g961520b1fb+2534687f64,g96f01af41f+f2060f23b6,g9ca82378b8+cacede5508,g9d27549199+78cd207961,gb065e2a02a+ad48cbcda4,gb1df4690d6+585f0f68a2,gb35d6563ee+62d12e78cb,gbc3249ced9+bd4bf1dc76,gbec6a3398f+bd4bf1dc76,gd01420fc67+bd4bf1dc76,gd59336e7c4+c7bb92e648,gf46e8334de+81c9a61069,gfed783d017+bd4bf1dc76,v25.0.1.rc3
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__ = ['VisualizeBinExpConfig', 'VisualizeBinExpTask',
23 'VisualizeMosaicExpConfig', 'VisualizeMosaicExpTask']
24
25import numpy as np
26
27import lsst.pex.config as pexConfig
28import lsst.pipe.base as pipeBase
29import lsst.pipe.base.connectionTypes as cT
30import lsst.afw.math as afwMath
31import lsst.afw.image as afwImage
32import lsst.afw.cameraGeom.utils as afwUtils
33
34
35class VisualizeBinExpConnections(pipeBase.PipelineTaskConnections,
36 dimensions=("instrument", "detector")):
37 inputExp = cT.Input(
38 name="calexp",
39 doc="Input exposure data to mosaic.",
40 storageClass="ExposureF",
41 dimensions=("instrument", "detector"),
42 )
43 camera = cT.PrerequisiteInput(
44 name="camera",
45 doc="Input camera to use for mosaic geometry.",
46 storageClass="Camera",
47 dimensions=("instrument",),
48 isCalibration=True,
49 )
50
51 outputExp = cT.Output(
52 name="calexpBin",
53 doc="Output binned image.",
54 storageClass="ExposureF",
55 dimensions=("instrument", "detector"),
56 )
57
58
59class VisualizeBinExpConfig(pipeBase.PipelineTaskConfig,
60 pipelineConnections=VisualizeBinExpConnections):
61 """Configuration for focal plane visualization.
62 """
63 binning = pexConfig.Field(
64 dtype=int,
65 default=8,
66 doc="Binning factor to apply to each input exposure's image data.",
67 )
68 detectorKeyword = pexConfig.Field(
69 dtype=str,
70 default='DET-ID',
71 doc="Metadata keyword to use to find detector if not available from input.",
72 )
73
74
75class VisualizeBinExpTask(pipeBase.PipelineTask):
76 """Bin the detectors of an exposure.
77
78 The outputs of this task should be passed to
79 VisualizeMosaicExpTask to be mosaicked into a full focal plane
80 visualization image.
81 """
82 ConfigClass = VisualizeBinExpConfig
83 _DefaultName = 'VisualizeBinExp'
84
85 def run(self, inputExp, camera):
86 """Bin input image, attach associated detector.
87
88 Parameters
89 ----------
90 inputExp : `lsst.afw.image.Exposure`
91 Input exposure data to bin.
93 Input camera to use for mosaic geometry.
94
95 Returns
96 -------
97 output : `lsst.pipe.base.Struct`
98 Results struct with attribute:
99
100 ``outputExp``
101 Binned version of input image (`lsst.afw.image.Exposure`).
102 """
103 if inputExp.getDetector() is None:
104 detectorId = inputExp.getMetadata().get(self.config.detectorKeyword)
105 if detectorId is not None:
106 inputExp.setDetector(camera[detectorId])
107
108 binned = inputExp.getMaskedImage()
109 binned = afwMath.binImage(binned, self.config.binning)
110 outputExp = afwImage.makeExposure(binned)
111
112 outputExp.setInfo(inputExp.getInfo())
113
114 return pipeBase.Struct(
115 outputExp=outputExp,
116 )
117
118
119class VisualizeMosaicExpConnections(pipeBase.PipelineTaskConnections,
120 dimensions=("instrument", )):
121 inputExps = cT.Input(
122 name="calexpBin",
123 doc="Input binned images mosaic.",
124 storageClass="ExposureF",
125 dimensions=("instrument", "detector"),
126 multiple=True,
127 )
128 camera = cT.PrerequisiteInput(
129 name="camera",
130 doc="Input camera to use for mosaic geometry.",
131 storageClass="Camera",
132 dimensions=("instrument",),
133 isCalibration=True,
134 )
135
136 outputData = cT.Output(
137 name="calexpFocalPlane",
138 doc="Output binned mosaicked frame.",
139 storageClass="ImageF",
140 dimensions=("instrument", ),
141 )
142
143
144class VisualizeMosaicExpConfig(pipeBase.PipelineTaskConfig,
145 pipelineConnections=VisualizeMosaicExpConnections):
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 ConfigClass = VisualizeMosaicExpConfig
164 _DefaultName = 'VisualizeMosaicExp'
165
166 def makeCameraImage(self, inputExps, camera, binning):
167 """Make an image of an entire focal plane.
168
169 Parameters
170 ----------
171 exposures: `dict` [`int`, `lsst.afw.image.Exposure`]
172 CCD exposures, binned by `binning`. The keys are the
173 detectorIDs, with the values the binned image exposure.
174
175 Returns
176 -------
177 image : `lsst.afw.image.Image`
178 Image mosaicked from the individual binned images for each
179 detector.
180 """
181 image = afwUtils.makeImageFromCamera(
182 camera,
183 imageSource=ImageSource(inputExps),
184 imageFactory=afwImage.ImageF,
185 binSize=binning
186 )
187 return image
188
189 def run(self, inputExps, camera):
190 """Mosaic inputs together to create focal plane image.
191
192 Parameters
193 ----------
194 inputExp : `list` [`lsst.afw.image.Exposure`]
195 Input exposure data to bin.
197 Input camera to use for mosaic geometry.
198
199 Returns
200 -------
201 output : `lsst.pipe.base.Struct`
202 Results struct with attribute:
203
204 ``outputExp``
205 Binned version of input image (`lsst.afw.image.Exposure`).
206 """
207 expDict = {exp.getDetector().getId(): exp for exp in inputExps}
208 image = self.makeCameraImage(expDict, camera, self.config.binning)
209
210 return pipeBase.Struct(
211 outputData=image,
212 )
213
214
216 """Source of images for makeImageFromCamera"""
217 def __init__(self, exposures):
218 self.exposures = exposures
219 self.isTrimmed = True
220 self.background = np.nan
221
222 def getCcdImage(self, detector, imageFactory, binSize):
223 """Provide image of CCD to makeImageFromCamera
224
225 Parameters
226 ----------
227 detector : `int`
228 Detector ID to get image data for.
229 imageFactory : `lsst.afw.image.Image`
230 Type of image to construct.
231 binSize : `int`
232 Binsize to use to recompute dimensions.
233
234 Returns
235 -------
236 image : `lsst.afw.image.Image`
237 Appropriately rotated, binned, and transformed
238 image to be mosaicked.
240 Camera detector that the returned image data
241 belongs to.
242 """
243 detId = detector.getId()
244
245 if detId not in self.exposures:
246 dims = detector.getBBox().getDimensions()/binSize
247 image = imageFactory(*[int(xx) for xx in dims])
248 image.set(self.background)
249 else:
250 image = self.exposures[detector.getId()]
251 if hasattr(image, "getMaskedImage"):
252 image = image.getMaskedImage()
253 if hasattr(image, "getMask"):
254 mask = image.getMask()
255 isBad = mask.getArray() & mask.getPlaneBitMask("NO_DATA") > 0
256 image = image.clone()
257 image.getImage().getArray()[isBad] = self.background
258 if hasattr(image, "getImage"):
259 image = image.getImage()
260
261 # afwMath.rotateImageBy90 checks NQuarter values,
262 # so we don't need to here.
263 image = afwMath.rotateImageBy90(image, detector.getOrientation().getNQuarter())
264 return image, detector
An immutable representation of a camera.
Definition: Camera.h:43
A representation of a detector in a mosaic camera.
Definition: Detector.h:185
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition: Exposure.h:72
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:51
def getCcdImage(self, detector, imageFactory, binSize)
def makeCameraImage(self, inputExps, camera, binning)
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:445
std::shared_ptr< ImageT > rotateImageBy90(ImageT const &image, int nQuarter)
Rotate an image by an integral number of quarter turns.
Definition: rotateImage.cc:39
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