31from lsst.daf.butler
import DeferredDatasetHandle
35__all__ = [
"GetCoaddAsTemplateTask",
"GetCoaddAsTemplateConfig",
36 "GetTemplateTask",
"GetTemplateConfig",
37 "GetDcrTemplateTask",
"GetDcrTemplateConfig",
38 "GetMultiTractCoaddTemplateTask",
"GetMultiTractCoaddTemplateConfig"]
42 templateBorderSize = pexConfig.Field(
45 doc=
"Number of pixels to grow the requested template image to account for warping"
47 coaddName = pexConfig.Field(
48 doc=
"coadd name: typically one of 'deep', 'goodSeeing', or 'dcr'",
52 warpType = pexConfig.Field(
53 doc=
"Warp type of the coadd template: one of 'direct' or 'psfMatched'",
60 """Subtask to retrieve coadd for use as an image difference template.
62 This is the default getTemplate Task to be run
as a subtask by
63 ``pipe.tasks.ImageDifferenceTask``.
67 From the given skymap, the closest tract
is selected; multiple tracts are
68 not supported. The assembled template inherits the WCS of the selected
69 skymap tract
and the resolution of the template exposures. Overlapping box
70 regions of the input template patches are pixel by pixel copied into the
71 assembled template image. There
is no warping
or pixel resampling.
73 Pixels
with no overlap of any available input patches are set to ``nan``
74 value
and ``NO_DATA`` flagged.
77 ConfigClass = GetCoaddAsTemplateConfig
78 _DefaultName = "GetCoaddAsTemplateTask"
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.
87 The science exposure to define the sky region of the template
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.
98 result : `lsst.pipe.base.Struct`
99 A struct with attibutes:
102 Template coadd exposure assembled out of patches
103 (`lsst.afw.image.ExposureF`).
105 Always `
None`
for this subtask.
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]]
115 raise RuntimeError(
"Templates constructed from multiple Tracts not supported by this task. "
116 "Use GetTemplateTask instead.")
118 detectorWcs = exposure.getWcs()
119 if detectorWcs
is None:
120 templateExposure =
None
122 self.log.info(
"Exposure has no WCS, so cannot create associated template.")
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)
129 availableCoaddRefs = dict()
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())
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)
145 availableCoaddRefs[dataId[
'patch']] = [coaddRef, ]
147 self.log.info(
"Using template input tract=%s, patch=%s",
148 dataId[
'tract'], dataId[
'patch'])
149 availableCoaddRefs[dataId[
'patch']] = coaddRef
151 if overlappingArea == 0:
152 templateExposure =
None
154 self.log.warning(
"No overlapping template patches found")
156 patchList = [tractInfo[patch]
for patch
in availableCoaddRefs.keys()]
157 templateExposure = self.
run(tractInfo, patchList, detectorCorners, availableCoaddRefs,
158 visitInfo=exposure.getInfo().getVisitInfo())
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)
170 """Select the relevant tract and its patches that overlap with the
176 The science exposure to define the sky region of the template
180 SkyMap object that corresponds to the template coadd.
188 List of all overlap patches of the selected tract.
190 Corners of the exposure in the sky
in the order given by
191 `lsst.geom.Box2D.getCorners`.
193 expWcs = exposure.getWcs()
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)
203 raise RuntimeError(
"No suitable tract found")
205 self.log.info(
"Assembling %d coadd patches", len(patchList))
206 self.log.info(
"exposure dimensions=%s", exposure.getDimensions())
208 return (tractInfo, patchList, skyCorners)
210 def run(self, tractInfo, patchList, skyCorners, availableCoaddRefs,
211 sensorRef=None, visitInfo=None):
212 """Determination of exposure dimensions and copying of pixels from
213 overlapping patch regions.
218 SkyMap object that corresponds to the template coadd.
222 Patches to consider for making the template exposure.
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.
230 Must always be `
None`. Gen2 parameters are no longer used.
232 VisitInfo to make dcr model.
236 templateExposure : `lsst.afw.image.ExposureF`
237 The created template exposure.
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()
246 for skyPos
in skyCorners:
247 coaddBBox.include(coaddWcs.skyToPixel(skyPos))
249 self.log.info(
"coadd dimensions=%s", coaddBBox.getDimensions())
251 coaddExposure = afwImage.ExposureF(coaddBBox, coaddWcs)
252 coaddExposure.maskedImage.set(np.nan, afwImage.Mask.getPlaneBitMask(
"NO_DATA"), np.nan)
254 coaddFilterLabel =
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)
264 if patchSubBBox.isEmpty():
265 if isinstance(availableCoaddRefs[patchNumber], DeferredDatasetHandle):
266 tract = availableCoaddRefs[patchNumber].dataId[
'tract']
268 tract = availableCoaddRefs[patchNumber][
'tract']
269 self.log.info(
"skip tract=%d patch=%d; no overlapping pixels", tract, patchNumber)
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])
279 self.log.info(
"Constructing DCR-matched template for patch %s",
280 availableCoaddRefs[patchNumber])
282 dcrModel = DcrModel.fromQuantum(availableCoaddRefs[patchNumber],
283 self.config.effectiveWavelength,
284 self.config.bandwidth)
292 dcrBBox.grow(-self.config.templateBorderSize)
293 dcrBBox.include(patchInnerBBox)
294 coaddPatch = dcrModel.buildMatchedExposure(bbox=dcrBBox,
297 coaddPatch = availableCoaddRefs[patchNumber].get()
303 overlapBox = coaddPatch.getBBox()
304 overlapBox.clip(coaddBBox)
305 coaddExposure.maskedImage.assign(coaddPatch.maskedImage[overlapBox], overlapBox)
307 if coaddFilterLabel
is None:
308 coaddFilterLabel = coaddPatch.getFilter()
311 if coaddPsf
is None and coaddPatch.hasPsf():
312 coaddPsf = coaddPatch.getPsf()
316 if coaddPhotoCalib
is None:
317 coaddPhotoCalib = coaddPatch.getPhotoCalib()
319 if coaddPhotoCalib
is None:
320 raise RuntimeError(
"No coadd PhotoCalib found!")
321 if nPatchesFound == 0:
322 raise RuntimeError(
"No patches found!")
324 raise RuntimeError(
"No coadd Psf found!")
326 coaddExposure.setPhotoCalib(coaddPhotoCalib)
327 coaddExposure.setPsf(coaddPsf)
328 coaddExposure.setFilter(coaddFilterLabel)
332 """Return coadd name for given task config
336 CoaddDatasetName : `string`
338 TODO: This nearly duplicates a method in CoaddBaseTask (DM-11985)
340 warpType = self.config.warpType
341 suffix = "" if warpType ==
"direct" else warpType[0].upper() + warpType[1:]
342 return self.config.coaddName +
"Coadd" + suffix
346 dimensions=(
"instrument",
"visit",
"detector",
"skymap"),
347 defaultTemplates={
"coaddName":
"goodSeeing",
348 "warpTypeSuffix":
"",
350 bbox = pipeBase.connectionTypes.Input(
351 doc=
"BBoxes of calexp used determine geometry of output template",
352 name=
"{fakesType}calexp.bbox",
353 storageClass=
"Box2I",
354 dimensions=(
"instrument",
"visit",
"detector"),
356 wcs = pipeBase.connectionTypes.Input(
357 doc=
"WCS of the calexp that we want to fetch the template for",
358 name=
"{fakesType}calexp.wcs",
360 dimensions=(
"instrument",
"visit",
"detector"),
362 skyMap = pipeBase.connectionTypes.Input(
363 doc=
"Input definition of geometry/bbox and projection/wcs for template exposures",
364 name=BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
365 dimensions=(
"skymap", ),
366 storageClass=
"SkyMap",
370 coaddExposures = pipeBase.connectionTypes.Input(
371 doc=
"Input template to match and subtract from the exposure",
372 dimensions=(
"tract",
"patch",
"skymap",
"band"),
373 storageClass=
"ExposureF",
374 name=
"{fakesType}{coaddName}Coadd{warpTypeSuffix}",
378 template = pipeBase.connectionTypes.Output(
379 doc=
"Warped template used to create `subtractedExposure`.",
380 dimensions=(
"instrument",
"visit",
"detector"),
381 storageClass=
"ExposureF",
382 name=
"{fakesType}{coaddName}Diff_templateExp{warpTypeSuffix}",
386class GetTemplateConfig(pipeBase.PipelineTaskConfig,
387 pipelineConnections=GetTemplateConnections):
388 templateBorderSize = pexConfig.Field(
391 doc=
"Number of pixels to grow the requested template image to account for warping"
393 warp = pexConfig.ConfigField(
394 dtype=afwMath.Warper.ConfigClass,
395 doc=
"warper configuration",
397 coaddPsf = pexConfig.ConfigField(
398 doc=
"Configuration for CoaddPsf",
399 dtype=CoaddPsfConfig,
402 def setDefaults(self):
403 self.warp.warpingKernelName =
'lanczos5'
404 self.coaddPsf.warpingKernelName =
'lanczos5'
407class GetTemplateTask(pipeBase.PipelineTask):
408 ConfigClass = GetTemplateConfig
409 _DefaultName =
"getTemplate"
411 def __init__(self, *args, **kwargs):
412 super().__init__(*args, **kwargs)
413 self.warper = afwMath.Warper.fromConfig(self.config.warp)
415 def runQuantum(self, butlerQC, inputRefs, outputRefs):
417 inputs = butlerQC.get(inputRefs)
418 results = self.getOverlappingExposures(inputs)
419 inputs[
"coaddExposures"] = results.coaddExposures
420 inputs[
"dataIds"] = results.dataIds
421 outputs = self.run(**inputs)
422 butlerQC.put(outputs, outputRefs)
424 def getOverlappingExposures(self, inputs):
425 """Return lists of coadds and their corresponding dataIds that overlap
428 The spatial index in the registry has generous padding
and often
429 supplies patches near, but
not directly overlapping the detector.
430 Filters inputs so that we don
't have to read in all input coadds.
434 inputs : `dict` of task Inputs, containing:
435 - coaddExposureRefs : `list`
436 [`lsst.daf.butler.DeferredDatasetHandle` of
438 Data references to exposures that might overlap the detector.
440 Template Bounding box of the detector geometry onto which to
441 resample the coaddExposures.
442 - skyMap : `lsst.skymap.SkyMap`
443 Input definition of geometry/bbox and projection/wcs
for
446 Template WCS onto which to resample the coaddExposures.
450 result : `lsst.pipe.base.Struct`
451 A struct
with attributes:
454 List of Coadd exposures that overlap the detector (`list`
457 List of data IDs of the coadd exposures that overlap the
458 detector (`list` [`lsst.daf.butler.DataCoordinate`]).
463 Raised
if no patches overlap the input detector bbox.
469 coaddExposureList = []
471 for coaddRef
in inputs[
'coaddExposures']:
472 dataId = coaddRef.dataId
473 patchWcs = inputs[
'skyMap'][dataId[
'tract']].getWcs()
474 patchBBox = inputs[
'skyMap'][dataId[
'tract']][dataId[
'patch']].getOuterBBox()
475 patchCorners = patchWcs.pixelToSky(
geom.Box2D(patchBBox).getCorners())
476 inputsWcs = inputs[
'wcs']
477 if inputsWcs
is not None:
479 if patchPolygon.intersection(detectorPolygon):
480 overlappingArea += patchPolygon.intersectionSingle(detectorPolygon).calculateArea()
481 self.log.info(
"Using template input tract=%s, patch=%s" %
482 (dataId[
'tract'], dataId[
'patch']))
483 coaddExposureList.append(coaddRef.get())
484 dataIds.append(dataId)
486 self.log.info(
"Exposure has no WCS, so cannot create associated template.")
488 if not overlappingArea:
489 raise pipeBase.NoWorkFound(
'No patches overlap detector')
491 return pipeBase.Struct(coaddExposures=coaddExposureList,
494 def run(self, coaddExposures, bbox, wcs, dataIds, **kwargs):
495 """Warp coadds from multiple tracts to form a template for image diff.
497 Where the tracts overlap, the resulting template image is averaged.
498 The PSF on the template
is created by combining the CoaddPsf on each
499 template image into a meta-CoaddPsf.
504 Coadds to be mosaicked.
506 Template Bounding box of the detector geometry onto which to
507 resample the ``coaddExposures``.
509 Template WCS onto which to resample the ``coaddExposures``.
510 dataIds : `list` [`lsst.daf.butler.DataCoordinate`]
511 Record of the tract
and patch of each coaddExposure.
513 Any additional keyword parameters.
517 result : `lsst.pipe.base.Struct`
518 A struct
with attributes:
521 A template coadd exposure assembled out of patches
522 (`lsst.afw.image.ExposureF`).
525 tractsSchema = afwTable.ExposureTable.makeMinimalSchema()
526 tractKey = tractsSchema.addField(
'tract', type=np.int32, doc=
'Which tract')
527 patchKey = tractsSchema.addField(
'patch', type=np.int32, doc=
'Which patch')
528 weightKey = tractsSchema.addField(
'weight', type=float, doc=
'Weight for each tract, should be 1')
532 bbox.grow(self.config.templateBorderSize)
539 for coaddExposure, dataId
in zip(coaddExposures, dataIds):
542 warped = self.warper.warpExposure(finalWcs, coaddExposure, maxBBox=finalBBox)
545 if not np.any(np.isfinite(warped.image.array)):
546 self.log.info(
"No overlap for warped %s. Skipping" % dataId)
549 exp = afwImage.ExposureF(finalBBox, finalWcs)
550 exp.maskedImage.set(np.nan, afwImage.Mask.getPlaneBitMask(
"NO_DATA"), np.nan)
551 exp.maskedImage.assign(warped.maskedImage, warped.getBBox())
553 maskedImageList.append(exp.maskedImage)
555 record = tractsCatalog.addNew()
556 record.setPsf(coaddExposure.getPsf())
557 record.setWcs(coaddExposure.getWcs())
558 record.setPhotoCalib(coaddExposure.getPhotoCalib())
559 record.setBBox(coaddExposure.getBBox())
561 record.set(tractKey, dataId[
'tract'])
562 record.set(patchKey, dataId[
'patch'])
563 record.set(weightKey, 1.)
566 if nPatchesFound == 0:
567 raise pipeBase.NoWorkFound(
"No patches found to overlap detector")
572 statsCtrl.setNanSafe(
True)
573 statsCtrl.setWeighted(
True)
574 statsCtrl.setCalcErrorMosaicMode(
True)
576 templateExposure = afwImage.ExposureF(finalBBox, finalWcs)
577 templateExposure.maskedImage.set(np.nan, afwImage.Mask.getPlaneBitMask(
"NO_DATA"), np.nan)
578 xy0 = templateExposure.getXY0()
581 weightList, clipped=0, maskMap=[])
582 templateExposure.maskedImage.setXY0(xy0)
586 boolmask = templateExposure.mask.array & templateExposure.mask.getPlaneBitMask(
'NO_DATA') == 0
588 centerCoord = afwGeom.SpanSet.fromMask(maskx, 1).computeCentroid()
590 ctrl = self.config.coaddPsf.makeControl()
591 coaddPsf =
CoaddPsf(tractsCatalog, finalWcs, centerCoord, ctrl.warpingKernelName, ctrl.cacheSize)
593 raise RuntimeError(
"CoaddPsf could not be constructed")
595 templateExposure.setPsf(coaddPsf)
596 templateExposure.setFilter(coaddExposure.getFilter())
597 templateExposure.setPhotoCalib(coaddExposure.getPhotoCalib())
598 return pipeBase.Struct(template=templateExposure)
602 dimensions=(
"instrument",
"visit",
"detector",
"skymap"),
603 defaultTemplates={
"coaddName":
"dcr",
604 "warpTypeSuffix":
"",
606 visitInfo = pipeBase.connectionTypes.Input(
607 doc=
"VisitInfo of calexp used to determine observing conditions.",
608 name=
"{fakesType}calexp.visitInfo",
609 storageClass=
"VisitInfo",
610 dimensions=(
"instrument",
"visit",
"detector"),
612 dcrCoadds = pipeBase.connectionTypes.Input(
613 doc=
"Input DCR template to match and subtract from the exposure",
614 name=
"{fakesType}dcrCoadd{warpTypeSuffix}",
615 storageClass=
"ExposureF",
616 dimensions=(
"tract",
"patch",
"skymap",
"band",
"subfilter"),
621 def __init__(self, *, config=None):
622 super().__init__(config=config)
623 self.inputs.remove(
"coaddExposures")
626class GetDcrTemplateConfig(GetTemplateConfig,
627 pipelineConnections=GetDcrTemplateConnections):
628 numSubfilters = pexConfig.Field(
629 doc=
"Number of subfilters in the DcrCoadd.",
633 effectiveWavelength = pexConfig.Field(
634 doc=
"Effective wavelength of the filter.",
638 bandwidth = pexConfig.Field(
639 doc=
"Bandwidth of the physical filter.",
645 if self.effectiveWavelength
is None or self.bandwidth
is None:
646 raise ValueError(
"The effective wavelength and bandwidth of the physical filter "
647 "must be set in the getTemplate config for DCR coadds. "
648 "Required until transmission curves are used in DM-13668.")
651class GetDcrTemplateTask(GetTemplateTask):
652 ConfigClass = GetDcrTemplateConfig
653 _DefaultName =
"getDcrTemplate"
655 def getOverlappingExposures(self, inputs):
656 """Return lists of coadds and their corresponding dataIds that overlap
659 The spatial index in the registry has generous padding
and often
660 supplies patches near, but
not directly overlapping the detector.
661 Filters inputs so that we don
't have to read in all input coadds.
665 inputs : `dict` of task Inputs, containing:
666 - coaddExposureRefs : `list`
667 [`lsst.daf.butler.DeferredDatasetHandle` of
669 Data references to exposures that might overlap the detector.
671 Template Bounding box of the detector geometry onto which to
672 resample the coaddExposures.
673 - skyMap : `lsst.skymap.SkyMap`
674 Input definition of geometry/bbox and projection/wcs
for
677 Template WCS onto which to resample the coaddExposures.
679 Metadata
for the science image.
683 result : `lsst.pipe.base.Struct`
684 A struct
with attibutes:
687 Coadd exposures that overlap the detector (`list`
690 Data IDs of the coadd exposures that overlap the detector
691 (`list` [`lsst.daf.butler.DataCoordinate`]).
696 Raised
if no patches overlatp the input detector bbox.
702 coaddExposureRefList = []
705 for coaddRef
in inputs[
"dcrCoadds"]:
706 dataId = coaddRef.dataId
707 patchWcs = inputs[
"skyMap"][dataId[
'tract']].getWcs()
708 patchBBox = inputs[
"skyMap"][dataId[
'tract']][dataId[
'patch']].getOuterBBox()
709 patchCorners = patchWcs.pixelToSky(
geom.Box2D(patchBBox).getCorners())
711 if patchPolygon.intersection(detectorPolygon):
712 overlappingArea += patchPolygon.intersectionSingle(detectorPolygon).calculateArea()
713 self.log.info(
"Using template input tract=%s, patch=%s, subfilter=%s" %
714 (dataId[
'tract'], dataId[
'patch'], dataId[
"subfilter"]))
715 coaddExposureRefList.append(coaddRef)
716 if dataId[
'tract']
in patchList:
717 patchList[dataId[
'tract']].append(dataId[
'patch'])
719 patchList[dataId[
'tract']] = [dataId[
'patch'], ]
720 dataIds.append(dataId)
722 if not overlappingArea:
723 raise pipeBase.NoWorkFound(
'No patches overlap detector')
725 self.checkPatchList(patchList)
727 coaddExposures = self.getDcrModel(patchList, inputs[
'dcrCoadds'], inputs[
'visitInfo'])
728 return pipeBase.Struct(coaddExposures=coaddExposures,
732 """Check that all of the DcrModel subfilters are present for each
738 Dict of the patches containing valid data for each tract.
743 If the number of exposures found
for a patch does
not match the
744 number of subfilters.
746 for tract
in patchList:
747 for patch
in set(patchList[tract]):
748 if patchList[tract].count(patch) != self.config.numSubfilters:
749 raise RuntimeError(
"Invalid number of DcrModel subfilters found: %d vs %d expected",
750 patchList[tract].count(patch), self.config.numSubfilters)
753 """Build DCR-matched coadds from a list of exposure references.
758 Dict of the patches containing valid data for each tract.
759 coaddRefs : `list` [`lsst.daf.butler.DeferredDatasetHandle`]
761 DcrModels that overlap the detector.
763 Metadata
for the science image.
768 Coadd exposures that overlap the detector.
770 coaddExposureList = []
771 for tract
in patchList:
772 for patch
in set(patchList[tract]):
773 coaddRefList = [coaddRef
for coaddRef
in coaddRefs
774 if _selectDataRef(coaddRef, tract, patch)]
776 dcrModel = DcrModel.fromQuantum(coaddRefList,
777 self.config.effectiveWavelength,
778 self.config.bandwidth,
779 self.config.numSubfilters)
780 coaddExposureList.append(dcrModel.buildMatchedExposure(visitInfo=visitInfo))
781 return coaddExposureList
784def _selectDataRef(coaddRef, tract, patch):
785 condition = (coaddRef.dataId[
'tract'] == tract) & (coaddRef.dataId[
'patch'] == patch)
793class GetMultiTractCoaddTemplateTask(GetTemplateTask):
794 ConfigClass = GetMultiTractCoaddTemplateConfig
795 _DefaultName =
"getMultiTractCoaddTemplate"
799 self.log.warning(
"GetMultiTractCoaddTemplateTask is deprecated. Use GetTemplateTask instead.")
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Information about a single exposure of an imaging camera.
Pass parameters to a Statistics object.
Custom catalog class for ExposureRecord/Table.
A floating-point coordinate rectangle geometry.
An integer coordinate rectangle.
Point in an unspecified spherical coordinate system.
def getCoaddDatasetName(self)
def getOverlapPatchList(self, exposure, skyMap)
def run(self, tractInfo, patchList, skyCorners, availableCoaddRefs, sensorRef=None, visitInfo=None)
def runQuantum(self, exposure, butlerQC, skyMapRef, coaddExposureRefs)
def __init__(self, *args, **kwargs)
CoaddPsf is the Psf derived to be used for non-PSF-matched Coadd images.
daf::base::PropertySet * set
std::shared_ptr< lsst::afw::image::Image< PixelT > > statisticsStack(std::vector< std::shared_ptr< lsst::afw::image::Image< PixelT > > > &images, Property flags, StatisticsControl const &sctrl=StatisticsControl(), std::vector< lsst::afw::image::VariancePixel > const &wvector=std::vector< lsst::afw::image::VariancePixel >(0))
A function to compute some statistics of a stack of Images.
Property stringToStatisticsProperty(std::string const property)
Conversion function to switch a string to a Property (see Statistics.h)
def checkPatchList(self, patchList)
def getDcrModel(self, patchList, coaddRefs, visitInfo)