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
Public Member Functions | Static Public Attributes | List of all members
lsst.ip.diffim.getTemplate.GetCoaddAsTemplateTask Class Reference
Inheritance diagram for lsst.ip.diffim.getTemplate.GetCoaddAsTemplateTask:

Public Member Functions

def runQuantum (self, exposure, butlerQC, skyMapRef, coaddExposureRefs)
 
def getOverlapPatchList (self, exposure, skyMap)
 
def run (self, tractInfo, patchList, skyCorners, availableCoaddRefs, sensorRef=None, visitInfo=None)
 
def getCoaddDatasetName (self)
 

Static Public Attributes

 ConfigClass = GetCoaddAsTemplateConfig
 

Detailed Description

Subtask to retrieve coadd for use as an image difference template.

This is the default getTemplate Task to be run as a subtask by
``pipe.tasks.ImageDifferenceTask``.

Notes
-----
From the given skymap, the closest tract is selected; multiple tracts are
not supported. The assembled template inherits the WCS of the selected
skymap tract and the resolution of the template exposures. Overlapping box
regions of the input template patches are pixel by pixel copied into the
assembled template image. There is no warping or pixel resampling.

Pixels with no overlap of any available input patches are set to ``nan``
value and ``NO_DATA`` flagged.

Definition at line 59 of file getTemplate.py.

Member Function Documentation

◆ getCoaddDatasetName()

def lsst.ip.diffim.getTemplate.GetCoaddAsTemplateTask.getCoaddDatasetName (   self)
Return coadd name for given task config

Returns
-------
CoaddDatasetName : `string`

TODO: This nearly duplicates a method in CoaddBaseTask (DM-11985)

Definition at line 331 of file getTemplate.py.

331 def getCoaddDatasetName(self):
332 """Return coadd name for given task config
333
334 Returns
335 -------
336 CoaddDatasetName : `string`
337
338 TODO: This nearly duplicates a method in CoaddBaseTask (DM-11985)
339 """
340 warpType = self.config.warpType
341 suffix = "" if warpType == "direct" else warpType[0].upper() + warpType[1:]
342 return self.config.coaddName + "Coadd" + suffix
343
344

◆ getOverlapPatchList()

def lsst.ip.diffim.getTemplate.GetCoaddAsTemplateTask.getOverlapPatchList (   self,
  exposure,
  skyMap 
)
Select the relevant tract and its patches that overlap with the
science exposure.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    The science exposure to define the sky region of the template
    coadd.

skyMap : `lsst.skymap.BaseSkyMap`
    SkyMap object that corresponds to the template coadd.

Returns
-------
result : `tuple` of
 - ``tractInfo`` : `lsst.skymap.TractInfo`
     The selected tract.
 - ``patchList`` : `list` [`lsst.skymap.PatchInfo`]
     List of all overlap patches of the selected tract.
 - ``skyCorners`` : `list` [`lsst.geom.SpherePoint`]
     Corners of the exposure in the sky in the order given by
     `lsst.geom.Box2D.getCorners`.

Definition at line 169 of file getTemplate.py.

169 def getOverlapPatchList(self, exposure, skyMap):
170 """Select the relevant tract and its patches that overlap with the
171 science exposure.
172
173 Parameters
174 ----------
175 exposure : `lsst.afw.image.Exposure`
176 The science exposure to define the sky region of the template
177 coadd.
178
179 skyMap : `lsst.skymap.BaseSkyMap`
180 SkyMap object that corresponds to the template coadd.
181
182 Returns
183 -------
184 result : `tuple` of
185 - ``tractInfo`` : `lsst.skymap.TractInfo`
186 The selected tract.
187 - ``patchList`` : `list` [`lsst.skymap.PatchInfo`]
188 List of all overlap patches of the selected tract.
189 - ``skyCorners`` : `list` [`lsst.geom.SpherePoint`]
190 Corners of the exposure in the sky in the order given by
191 `lsst.geom.Box2D.getCorners`.
192 """
193 expWcs = exposure.getWcs()
194 expBoxD = geom.Box2D(exposure.getBBox())
195 expBoxD.grow(self.config.templateBorderSize)
196 ctrSkyPos = expWcs.pixelToSky(expBoxD.getCenter())
197 tractInfo = skyMap.findTract(ctrSkyPos)
198 self.log.info("Using skyMap tract %s", tractInfo.getId())
199 skyCorners = [expWcs.pixelToSky(pixPos) for pixPos in expBoxD.getCorners()]
200 patchList = tractInfo.findPatchList(skyCorners)
201
202 if not patchList:
203 raise RuntimeError("No suitable tract found")
204
205 self.log.info("Assembling %d coadd patches", len(patchList))
206 self.log.info("exposure dimensions=%s", exposure.getDimensions())
207
208 return (tractInfo, patchList, skyCorners)
209
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Definition: Exposure.h:72
A floating-point coordinate rectangle geometry.
Definition: Box.h:413
Point in an unspecified spherical coordinate system.
Definition: SpherePoint.h:57

◆ run()

def lsst.ip.diffim.getTemplate.GetCoaddAsTemplateTask.run (   self,
  tractInfo,
  patchList,
  skyCorners,
  availableCoaddRefs,
  sensorRef = None,
  visitInfo = None 
)
Determination of exposure dimensions and copying of pixels from
overlapping patch regions.

Parameters
----------
skyMap : `lsst.skymap.BaseSkyMap`
    SkyMap object that corresponds to the template coadd.
tractInfo : `lsst.skymap.TractInfo`
    The selected tract.
patchList : iterable of `lsst.skymap.patchInfo.PatchInfo`
    Patches to consider for making the template exposure.
skyCorners : `list` [`lsst.geom.SpherePoint`]
    Sky corner coordinates to be covered by the template exposure.
availableCoaddRefs : `dict` [`int`]
    Dictionary of spatially relevant retrieved coadd patches,
    indexed by their sequential patch number. Values are
    `lsst.daf.butler.DeferredDatasetHandle` and ``.get()`` is called.
sensorRef : `None`
    Must always be `None`. Gen2 parameters are no longer used.
visitInfo : `lsst.afw.image.VisitInfo`
    VisitInfo to make dcr model.

Returns
-------
templateExposure : `lsst.afw.image.ExposureF`
    The created template exposure.

Definition at line 210 of file getTemplate.py.

211 sensorRef=None, visitInfo=None):
212 """Determination of exposure dimensions and copying of pixels from
213 overlapping patch regions.
214
215 Parameters
216 ----------
217 skyMap : `lsst.skymap.BaseSkyMap`
218 SkyMap object that corresponds to the template coadd.
219 tractInfo : `lsst.skymap.TractInfo`
220 The selected tract.
221 patchList : iterable of `lsst.skymap.patchInfo.PatchInfo`
222 Patches to consider for making the template exposure.
223 skyCorners : `list` [`lsst.geom.SpherePoint`]
224 Sky corner coordinates to be covered by the template exposure.
225 availableCoaddRefs : `dict` [`int`]
226 Dictionary of spatially relevant retrieved coadd patches,
227 indexed by their sequential patch number. Values are
228 `lsst.daf.butler.DeferredDatasetHandle` and ``.get()`` is called.
229 sensorRef : `None`
230 Must always be `None`. Gen2 parameters are no longer used.
231 visitInfo : `lsst.afw.image.VisitInfo`
232 VisitInfo to make dcr model.
233
234 Returns
235 -------
236 templateExposure : `lsst.afw.image.ExposureF`
237 The created template exposure.
238 """
239 if sensorRef is not None:
240 raise ValueError("sensorRef parameter is a Gen2 parameter that is no longer usable."
241 " Please move to Gen3 middleware.")
242 coaddWcs = tractInfo.getWcs()
243
244 # compute coadd bbox
245 coaddBBox = geom.Box2D()
246 for skyPos in skyCorners:
247 coaddBBox.include(coaddWcs.skyToPixel(skyPos))
248 coaddBBox = geom.Box2I(coaddBBox)
249 self.log.info("coadd dimensions=%s", coaddBBox.getDimensions())
250
251 coaddExposure = afwImage.ExposureF(coaddBBox, coaddWcs)
252 coaddExposure.maskedImage.set(np.nan, afwImage.Mask.getPlaneBitMask("NO_DATA"), np.nan)
253 nPatchesFound = 0
254 coaddFilterLabel = None
255 coaddPsf = None
256 coaddPhotoCalib = None
257 for patchInfo in patchList:
258 patchNumber = tractInfo.getSequentialPatchIndex(patchInfo)
259 patchSubBBox = patchInfo.getOuterBBox()
260 patchSubBBox.clip(coaddBBox)
261 if patchNumber not in availableCoaddRefs:
262 self.log.warning("skip patch=%d; patch does not exist for this coadd", patchNumber)
263 continue
264 if patchSubBBox.isEmpty():
265 if isinstance(availableCoaddRefs[patchNumber], DeferredDatasetHandle):
266 tract = availableCoaddRefs[patchNumber].dataId['tract']
267 else:
268 tract = availableCoaddRefs[patchNumber]['tract']
269 self.log.info("skip tract=%d patch=%d; no overlapping pixels", tract, patchNumber)
270 continue
271
272 if self.config.coaddName == 'dcr':
273 patchInnerBBox = patchInfo.getInnerBBox()
274 patchInnerBBox.clip(coaddBBox)
275 if np.min(patchInnerBBox.getDimensions()) <= 2*self.config.templateBorderSize:
276 self.log.info("skip tract=%(tract)s, patch=%(patch)s; too few pixels.",
277 availableCoaddRefs[patchNumber])
278 continue
279 self.log.info("Constructing DCR-matched template for patch %s",
280 availableCoaddRefs[patchNumber])
281
282 dcrModel = DcrModel.fromQuantum(availableCoaddRefs[patchNumber],
283 self.config.effectiveWavelength,
284 self.config.bandwidth)
285 # The edge pixels of the DcrCoadd may contain artifacts due to
286 # missing data. Each patch has significant overlap, and the
287 # contaminated edge pixels in a new patch will overwrite good
288 # pixels in the overlap region from previous patches.
289 # Shrink the BBox to remove the contaminated pixels,
290 # but make sure it is only the overlap region that is reduced.
291 dcrBBox = geom.Box2I(patchSubBBox)
292 dcrBBox.grow(-self.config.templateBorderSize)
293 dcrBBox.include(patchInnerBBox)
294 coaddPatch = dcrModel.buildMatchedExposure(bbox=dcrBBox,
295 visitInfo=visitInfo)
296 else:
297 coaddPatch = availableCoaddRefs[patchNumber].get()
298
299 nPatchesFound += 1
300
301 # Gen2 get() seems to clip based on bbox kwarg but we removed bbox
302 # calculation from caller code. Gen3 also does not do this.
303 overlapBox = coaddPatch.getBBox()
304 overlapBox.clip(coaddBBox)
305 coaddExposure.maskedImage.assign(coaddPatch.maskedImage[overlapBox], overlapBox)
306
307 if coaddFilterLabel is None:
308 coaddFilterLabel = coaddPatch.getFilter()
309
310 # Retrieve the PSF for this coadd tract, if not already retrieved.
311 if coaddPsf is None and coaddPatch.hasPsf():
312 coaddPsf = coaddPatch.getPsf()
313
314 # Retrieve the calibration for this coadd tract, if not already
315 # retrieved>
316 if coaddPhotoCalib is None:
317 coaddPhotoCalib = coaddPatch.getPhotoCalib()
318
319 if coaddPhotoCalib is None:
320 raise RuntimeError("No coadd PhotoCalib found!")
321 if nPatchesFound == 0:
322 raise RuntimeError("No patches found!")
323 if coaddPsf is None:
324 raise RuntimeError("No coadd Psf found!")
325
326 coaddExposure.setPhotoCalib(coaddPhotoCalib)
327 coaddExposure.setPsf(coaddPsf)
328 coaddExposure.setFilter(coaddFilterLabel)
329 return coaddExposure
330
Information about a single exposure of an imaging camera.
Definition: VisitInfo.h:68
An integer coordinate rectangle.
Definition: Box.h:55

◆ runQuantum()

def lsst.ip.diffim.getTemplate.GetCoaddAsTemplateTask.runQuantum (   self,
  exposure,
  butlerQC,
  skyMapRef,
  coaddExposureRefs 
)
Gen3 task entry point. Retrieve and mosaic a template coadd exposure
that overlaps the science exposure.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    The science exposure to define the sky region of the template
    coadd.
butlerQC : `lsst.pipe.base.ButlerQuantumContext`
    Butler like object that supports getting data by DatasetRef.
skyMapRef : `lsst.daf.butler.DatasetRef`
    Reference to SkyMap object that corresponds to the template coadd.
coaddExposureRefs : iterable of `lsst.daf.butler.DeferredDatasetRef`
    Iterable of references to the available template coadd patches.

Returns
-------
result : `lsst.pipe.base.Struct`
   A struct with attibutes:

    ``exposure``
        Template coadd exposure assembled out of patches
        (`lsst.afw.image.ExposureF`).
    ``sources``
        Always `None` for this subtask.

Definition at line 80 of file getTemplate.py.

80 def runQuantum(self, exposure, butlerQC, skyMapRef, coaddExposureRefs):
81 """Gen3 task entry point. Retrieve and mosaic a template coadd exposure
82 that overlaps the science exposure.
83
84 Parameters
85 ----------
86 exposure : `lsst.afw.image.Exposure`
87 The science exposure to define the sky region of the template
88 coadd.
89 butlerQC : `lsst.pipe.base.ButlerQuantumContext`
90 Butler like object that supports getting data by DatasetRef.
91 skyMapRef : `lsst.daf.butler.DatasetRef`
92 Reference to SkyMap object that corresponds to the template coadd.
93 coaddExposureRefs : iterable of `lsst.daf.butler.DeferredDatasetRef`
94 Iterable of references to the available template coadd patches.
95
96 Returns
97 -------
98 result : `lsst.pipe.base.Struct`
99 A struct with attibutes:
100
101 ``exposure``
102 Template coadd exposure assembled out of patches
103 (`lsst.afw.image.ExposureF`).
104 ``sources``
105 Always `None` for this subtask.
106
107 """
108 self.log.warning("GetCoaddAsTemplateTask is deprecated. Use GetTemplateTask instead.")
109 skyMap = butlerQC.get(skyMapRef)
110 coaddExposureRefs = butlerQC.get(coaddExposureRefs)
111 tracts = [ref.dataId['tract'] for ref in coaddExposureRefs]
112 if tracts.count(tracts[0]) == len(tracts):
113 tractInfo = skyMap[tracts[0]]
114 else:
115 raise RuntimeError("Templates constructed from multiple Tracts not supported by this task. "
116 "Use GetTemplateTask instead.")
117
118 detectorWcs = exposure.getWcs()
119 if detectorWcs is None:
120 templateExposure = None
121 pixGood = 0
122 self.log.info("Exposure has no WCS, so cannot create associated template.")
123 else:
124 detectorBBox = exposure.getBBox()
125 detectorCorners = detectorWcs.pixelToSky(geom.Box2D(detectorBBox).getCorners())
126 validPolygon = exposure.getInfo().getValidPolygon()
127 detectorPolygon = validPolygon if validPolygon else geom.Box2D(detectorBBox)
128
129 availableCoaddRefs = dict()
130 overlappingArea = 0
131 for coaddRef in coaddExposureRefs:
132 dataId = coaddRef.dataId
133 patchWcs = skyMap[dataId['tract']].getWcs()
134 patchBBox = skyMap[dataId['tract']][dataId['patch']].getOuterBBox()
135 patchCorners = patchWcs.pixelToSky(geom.Box2D(patchBBox).getCorners())
136 patchPolygon = afwGeom.Polygon(detectorWcs.skyToPixel(patchCorners))
137 if patchPolygon.intersection(detectorPolygon):
138 overlappingArea += patchPolygon.intersectionSingle(detectorPolygon).calculateArea()
139 if self.config.coaddName == 'dcr':
140 self.log.info("Using template input tract=%s, patch=%s, subfilter=%s",
141 dataId['tract'], dataId['patch'], dataId['subfilter'])
142 if dataId['patch'] in availableCoaddRefs:
143 availableCoaddRefs[dataId['patch']].append(coaddRef)
144 else:
145 availableCoaddRefs[dataId['patch']] = [coaddRef, ]
146 else:
147 self.log.info("Using template input tract=%s, patch=%s",
148 dataId['tract'], dataId['patch'])
149 availableCoaddRefs[dataId['patch']] = coaddRef
150
151 if overlappingArea == 0:
152 templateExposure = None
153 pixGood = 0
154 self.log.warning("No overlapping template patches found")
155 else:
156 patchList = [tractInfo[patch] for patch in availableCoaddRefs.keys()]
157 templateExposure = self.run(tractInfo, patchList, detectorCorners, availableCoaddRefs,
158 visitInfo=exposure.getInfo().getVisitInfo())
159 # Count the number of pixels with the NO_DATA mask bit set.
160 # Counting NaN pixels is insufficient because pixels without
161 # data are often intepolated over.
162 pixNoData = np.count_nonzero(templateExposure.mask.array
163 & templateExposure.mask.getPlaneBitMask('NO_DATA'))
164 pixGood = templateExposure.getBBox().getArea() - pixNoData
165 self.log.info("template has %d good pixels (%.1f%%)", pixGood,
166 100*pixGood/templateExposure.getBBox().getArea())
167 return pipeBase.Struct(exposure=templateExposure, sources=None, area=pixGood)
168
Cartesian polygons.
Definition: Polygon.h:59

Member Data Documentation

◆ ConfigClass

lsst.ip.diffim.getTemplate.GetCoaddAsTemplateTask.ConfigClass = GetCoaddAsTemplateConfig
static

Definition at line 77 of file getTemplate.py.


The documentation for this class was generated from the following file: