33 from lsst.daf.butler 
import DeferredDatasetHandle
 
   37 __all__ = [
"GetCoaddAsTemplateTask", 
"GetCoaddAsTemplateConfig",
 
   38            "GetCalexpAsTemplateTask", 
"GetCalexpAsTemplateConfig",
 
   39            "GetMultiTractCoaddTemplateTask", 
"GetMultiTractCoaddTemplateConfig"]
 
   43     templateBorderSize = pexConfig.Field(
 
   46         doc=
"Number of pixels to grow the requested template image to account for warping" 
   48     coaddName = pexConfig.Field(
 
   49         doc=
"coadd name: typically one of 'deep', 'goodSeeing', or 'dcr'",
 
   53     numSubfilters = pexConfig.Field(
 
   54         doc=
"Number of subfilters in the DcrCoadd. Used only if ``coaddName``='dcr'",
 
   58     effectiveWavelength = pexConfig.Field(
 
   59         doc=
"Effective wavelength of the filter. Used only if ``coaddName``='dcr'",
 
   63     bandwidth = pexConfig.Field(
 
   64         doc=
"Bandwidth of the physical filter. Used only if ``coaddName``='dcr'",
 
   68     warpType = pexConfig.Field(
 
   69         doc=
"Warp type of the coadd template: one of 'direct' or 'psfMatched'",
 
   77                 raise ValueError(
"The effective wavelength and bandwidth of the physical filter " 
   78                                  "must be set in the getTemplate config for DCR coadds. " 
   79                                  "Required until transmission curves are used in DM-13668.")
 
   83     """Subtask to retrieve coadd for use as an image difference template. 
   85     This is the default getTemplate Task to be run as a subtask by 
   86     ``pipe.tasks.ImageDifferenceTask``. The main methods are ``run()`` and 
   91     From the given skymap, the closest tract is selected;  multiple tracts  are 
   92     not supported. The assembled template inherits the WCS of the selected 
   93     skymap tract and the resolution of the template exposures. Overlapping box 
   94     regions of the input template patches are pixel by pixel copied into the 
   95     assembled template image. There is no warping or pixel resampling. 
   97     Pixels with no overlap of any available input patches are set to ``nan`` value 
   98     and ``NO_DATA`` flagged. 
  101     ConfigClass = GetCoaddAsTemplateConfig
 
  102     _DefaultName = 
"GetCoaddAsTemplateTask" 
  104     def runDataRef(self, exposure, sensorRef, templateIdList=None):
 
  105         """Gen2 task entry point. Retrieve and mosaic a template coadd exposure 
  106         that overlaps the science exposure. 
  110         exposure: `lsst.afw.image.Exposure` 
  111             an exposure for which to generate an overlapping template 
  113             a Butler data reference that can be used to obtain coadd data 
  114         templateIdList : TYPE, optional 
  115             list of data ids, unused here, in the case of coadd template 
  119         result : `lsst.pipe.base.Struct` 
  120             - ``exposure`` : `lsst.afw.image.ExposureF` 
  121                 a template coadd exposure assembled out of patches 
  122             - ``sources`` :  None for this subtask 
  124         skyMap = sensorRef.get(datasetType=self.config.coaddName + 
"Coadd_skyMap")
 
  125         tractInfo, patchList, skyCorners = self.
getOverlapPatchListgetOverlapPatchList(exposure, skyMap)
 
  127         availableCoaddRefs = dict()
 
  128         for patchInfo 
in patchList:
 
  129             patchNumber = tractInfo.getSequentialPatchIndex(patchInfo)
 
  132                 bbox=patchInfo.getOuterBBox(),
 
  133                 tract=tractInfo.getId(),
 
  134                 patch=
"%s,%s" % (patchInfo.getIndex()[0], patchInfo.getIndex()[1]),
 
  136                 numSubfilters=self.config.numSubfilters,
 
  139             if sensorRef.datasetExists(**patchArgDict):
 
  140                 self.log.
info(
"Reading patch %s", patchArgDict)
 
  141                 availableCoaddRefs[patchNumber] = patchArgDict
 
  143         templateExposure = self.
runrun(
 
  144             tractInfo, patchList, skyCorners, availableCoaddRefs,
 
  145             sensorRef=sensorRef, visitInfo=exposure.getInfo().getVisitInfo()
 
  147         return pipeBase.Struct(exposure=templateExposure, sources=
None)
 
  149     def runQuantum(self, exposure, butlerQC, skyMapRef, coaddExposureRefs):
 
  150         """Gen3 task entry point. Retrieve and mosaic a template coadd exposure 
  151         that overlaps the science exposure. 
  155         exposure : `lsst.afw.image.Exposure` 
  156             The science exposure to define the sky region of the template coadd. 
  157         butlerQC : `lsst.pipe.base.ButlerQuantumContext` 
  158             Butler like object that supports getting data by DatasetRef. 
  159         skyMapRef : `lsst.daf.butler.DatasetRef` 
  160             Reference to SkyMap object that corresponds to the template coadd. 
  161         coaddExposureRefs : iterable of `lsst.daf.butler.DeferredDatasetRef` 
  162             Iterable of references to the available template coadd patches. 
  166         result : `lsst.pipe.base.Struct` 
  167             - ``exposure`` : `lsst.afw.image.ExposureF` 
  168                 a template coadd exposure assembled out of patches 
  169             - ``sources`` :  `None` for this subtask 
  171         skyMap = butlerQC.get(skyMapRef)
 
  172         coaddExposureRefs = butlerQC.get(coaddExposureRefs)
 
  173         tracts = [ref.dataId[
'tract'] 
for ref 
in coaddExposureRefs]
 
  174         if tracts.count(tracts[0]) == len(tracts):
 
  175             tractInfo = skyMap[tracts[0]]
 
  177             raise RuntimeError(
"Templates constructed from multiple Tracts not supported by this task. " 
  178                                "Use GetMultiTractCoaddTemplateTask instead.")
 
  180         detectorBBox = exposure.getBBox()
 
  181         detectorWcs = exposure.getWcs()
 
  182         detectorCorners = detectorWcs.pixelToSky(
geom.Box2D(detectorBBox).getCorners())
 
  183         validPolygon = exposure.getInfo().getValidPolygon()
 
  184         detectorPolygon = validPolygon 
if validPolygon 
else geom.Box2D(detectorBBox)
 
  186         availableCoaddRefs = dict()
 
  188         for coaddRef 
in coaddExposureRefs:
 
  189             dataId = coaddRef.dataId
 
  190             patchWcs = skyMap[dataId[
'tract']].getWcs()
 
  191             patchBBox = skyMap[dataId[
'tract']][dataId[
'patch']].getOuterBBox()
 
  192             patchCorners = patchWcs.pixelToSky(
geom.Box2D(patchBBox).getCorners())
 
  194             if patchPolygon.intersection(detectorPolygon):
 
  195                 overlappingArea += patchPolygon.intersectionSingle(detectorPolygon).calculateArea()
 
  196                 if self.config.coaddName == 
'dcr':
 
  197                     self.log.
info(
"Using template input tract=%s, patch=%s, subfilter=%s",
 
  198                                   dataId[
'tract'], dataId[
'patch'], dataId[
'subfilter'])
 
  199                     if dataId[
'patch'] 
in availableCoaddRefs:
 
  200                         availableCoaddRefs[dataId[
'patch']].
append(coaddRef)
 
  202                         availableCoaddRefs[dataId[
'patch']] = [coaddRef, ]
 
  204                     self.log.
info(
"Using template input tract=%s, patch=%s",
 
  205                                   dataId[
'tract'], dataId[
'patch'])
 
  206                     availableCoaddRefs[dataId[
'patch']] = coaddRef
 
  208         if overlappingArea == 0:
 
  209             templateExposure = 
None 
  211             self.log.
warning(
"No overlapping template patches found")
 
  213             patchList = [tractInfo[patch] 
for patch 
in availableCoaddRefs.keys()]
 
  214             templateExposure = self.
runrun(tractInfo, patchList, detectorCorners, availableCoaddRefs,
 
  215                                         visitInfo=exposure.getInfo().getVisitInfo())
 
  218             pixNoData = np.count_nonzero(templateExposure.mask.array
 
  219                                          & templateExposure.mask.getPlaneBitMask(
'NO_DATA'))
 
  220             pixGood = templateExposure.getBBox().getArea() - pixNoData
 
  221             self.log.
info(
"template has %d good pixels (%.1f%%)", pixGood,
 
  222                           100*pixGood/templateExposure.getBBox().getArea())
 
  223         return pipeBase.Struct(exposure=templateExposure, sources=
None, area=pixGood)
 
  226         """Select the relevant tract and its patches that overlap with the science exposure. 
  230         exposure : `lsst.afw.image.Exposure` 
  231             The science exposure to define the sky region of the template coadd. 
  233         skyMap : `lsst.skymap.BaseSkyMap` 
  234             SkyMap object that corresponds to the template coadd. 
  239          - ``tractInfo`` : `lsst.skymap.TractInfo` 
  241          - ``patchList`` : `list` of `lsst.skymap.PatchInfo` 
  242              List of all overlap patches of the selected tract. 
  243          - ``skyCorners`` : `list` of `lsst.geom.SpherePoint` 
  244              Corners of the exposure in the sky in the order given by `lsst.geom.Box2D.getCorners`. 
  246         expWcs = exposure.getWcs()
 
  248         expBoxD.grow(self.config.templateBorderSize)
 
  249         ctrSkyPos = expWcs.pixelToSky(expBoxD.getCenter())
 
  250         tractInfo = skyMap.findTract(ctrSkyPos)
 
  251         self.log.
info(
"Using skyMap tract %s", tractInfo.getId())
 
  252         skyCorners = [expWcs.pixelToSky(pixPos) 
for pixPos 
in expBoxD.getCorners()]
 
  253         patchList = tractInfo.findPatchList(skyCorners)
 
  256             raise RuntimeError(
"No suitable tract found")
 
  258         self.log.
info(
"Assembling %d coadd patches", len(patchList))
 
  259         self.log.
info(
"exposure dimensions=%s", exposure.getDimensions())
 
  261         return (tractInfo, patchList, skyCorners)
 
  263     def run(self, tractInfo, patchList, skyCorners, availableCoaddRefs,
 
  264             sensorRef=None, visitInfo=None):
 
  265         """Gen2 and gen3 shared code: determination of exposure dimensions and 
  266         copying of pixels from overlapping patch regions. 
  270         skyMap : `lsst.skymap.BaseSkyMap` 
  271             SkyMap object that corresponds to the template coadd. 
  272         tractInfo : `lsst.skymap.TractInfo` 
  274         patchList : iterable of `lsst.skymap.patchInfo.PatchInfo` 
  275             Patches to consider for making the template exposure. 
  276         skyCorners : list of `lsst.geom.SpherePoint` 
  277             Sky corner coordinates to be covered by the template exposure. 
  278         availableCoaddRefs : `dict` [`int`] 
  279             Dictionary of spatially relevant retrieved coadd patches, 
  280             indexed by their sequential patch number. In Gen3 mode, values are 
  281             `lsst.daf.butler.DeferredDatasetHandle` and ``.get()`` is called, 
  282             in Gen2 mode, ``sensorRef.get(**coaddef)`` is called to retrieve the coadd. 
  283         sensorRef : `lsst.daf.persistence.ButlerDataRef`, Gen2 only 
  284             Butler data reference to get coadd data. 
  285             Must be `None` for Gen3. 
  286         visitInfo : `lsst.afw.image.VisitInfo`, Gen2 only 
  287             VisitInfo to make dcr model. 
  291         templateExposure: `lsst.afw.image.ExposureF` 
  292             The created template exposure. 
  294         coaddWcs = tractInfo.getWcs()
 
  298         for skyPos 
in skyCorners:
 
  299             coaddBBox.include(coaddWcs.skyToPixel(skyPos))
 
  301         self.log.
info(
"coadd dimensions=%s", coaddBBox.getDimensions())
 
  303         coaddExposure = afwImage.ExposureF(coaddBBox, coaddWcs)
 
  304         coaddExposure.maskedImage.set(np.nan, afwImage.Mask.getPlaneBitMask(
"NO_DATA"), np.nan)
 
  306         coaddFilterLabel = 
None 
  308         coaddPhotoCalib = 
None 
  309         for patchInfo 
in patchList:
 
  310             patchNumber = tractInfo.getSequentialPatchIndex(patchInfo)
 
  311             patchSubBBox = patchInfo.getOuterBBox()
 
  312             patchSubBBox.clip(coaddBBox)
 
  313             if patchNumber 
not in availableCoaddRefs:
 
  314                 self.log.
warning(
"skip patch=%d; patch does not exist for this coadd", patchNumber)
 
  316             if patchSubBBox.isEmpty():
 
  317                 if isinstance(availableCoaddRefs[patchNumber], DeferredDatasetHandle):
 
  318                     tract = availableCoaddRefs[patchNumber].dataId[
'tract']
 
  320                     tract = availableCoaddRefs[patchNumber][
'tract']
 
  321                 self.log.
info(
"skip tract=%d patch=%d; no overlapping pixels", tract, patchNumber)
 
  324             if self.config.coaddName == 
'dcr':
 
  325                 patchInnerBBox = patchInfo.getInnerBBox()
 
  326                 patchInnerBBox.clip(coaddBBox)
 
  327                 if np.min(patchInnerBBox.getDimensions()) <= 2*self.config.templateBorderSize:
 
  328                     self.log.
info(
"skip tract=%(tract)s, patch=%(patch)s; too few pixels.",
 
  329                                   availableCoaddRefs[patchNumber])
 
  331                 self.log.
info(
"Constructing DCR-matched template for patch %s",
 
  332                               availableCoaddRefs[patchNumber])
 
  335                     dcrModel = DcrModel.fromDataRef(sensorRef,
 
  336                                                     self.config.effectiveWavelength,
 
  337                                                     self.config.bandwidth,
 
  338                                                     **availableCoaddRefs[patchNumber])
 
  340                     dcrModel = DcrModel.fromQuantum(availableCoaddRefs[patchNumber],
 
  341                                                     self.config.effectiveWavelength,
 
  342                                                     self.config.bandwidth)
 
  350                 dcrBBox.grow(-self.config.templateBorderSize)
 
  351                 dcrBBox.include(patchInnerBBox)
 
  352                 coaddPatch = dcrModel.buildMatchedExposure(bbox=dcrBBox,
 
  356                 if sensorRef 
is None:
 
  358                     coaddPatch = availableCoaddRefs[patchNumber].get()
 
  361                     coaddPatch = sensorRef.get(**availableCoaddRefs[patchNumber])
 
  366             overlapBox = coaddPatch.getBBox()
 
  367             overlapBox.clip(coaddBBox)
 
  368             coaddExposure.maskedImage.assign(coaddPatch.maskedImage[overlapBox], overlapBox)
 
  370             if coaddFilterLabel 
is None:
 
  371                 coaddFilterLabel = coaddPatch.getFilterLabel()
 
  374             if coaddPsf 
is None and coaddPatch.hasPsf():
 
  375                 coaddPsf = coaddPatch.getPsf()
 
  378             if coaddPhotoCalib 
is None:
 
  379                 coaddPhotoCalib = coaddPatch.getPhotoCalib()
 
  381         if coaddPhotoCalib 
is None:
 
  382             raise RuntimeError(
"No coadd PhotoCalib found!")
 
  383         if nPatchesFound == 0:
 
  384             raise RuntimeError(
"No patches found!")
 
  386             raise RuntimeError(
"No coadd Psf found!")
 
  388         coaddExposure.setPhotoCalib(coaddPhotoCalib)
 
  389         coaddExposure.setPsf(coaddPsf)
 
  390         coaddExposure.setFilterLabel(coaddFilterLabel)
 
  394         """Return coadd name for given task config 
  398         CoaddDatasetName : `string` 
  400         TODO: This nearly duplicates a method in CoaddBaseTask (DM-11985) 
  402         warpType = self.config.warpType
 
  403         suffix = 
"" if warpType == 
"direct" else warpType[0].upper() + warpType[1:]
 
  404         return self.config.coaddName + 
"Coadd" + suffix
 
  408     doAddCalexpBackground = pexConfig.Field(
 
  411         doc=
"Add background to calexp before processing it." 
  416     """Subtask to retrieve calexp of the same ccd number as the science image SensorRef 
  417     for use as an image difference template. Only gen2 supported. 
  419     To be run as a subtask by pipe.tasks.ImageDifferenceTask. 
  420     Intended for use with simulations and surveys that repeatedly visit the same pointing. 
  421     This code was originally part of Winter2013ImageDifferenceTask. 
  424     ConfigClass = GetCalexpAsTemplateConfig
 
  425     _DefaultName = 
"GetCalexpAsTemplateTask" 
  427     def run(self, exposure, sensorRef, templateIdList):
 
  428         """Return a calexp exposure with based on input sensorRef. 
  430         Construct a dataId based on the sensorRef.dataId combined 
  431         with the specifications from the first dataId in templateIdList 
  435         exposure :  `lsst.afw.image.Exposure` 
  437         sensorRef : `list` of `lsst.daf.persistence.ButlerDataRef` 
  438             Data reference of the calexp(s) to subtract from. 
  439         templateIdList : `list` of `lsst.daf.persistence.ButlerDataRef` 
  440             Data reference of the template calexp to be subtraced. 
  441             Can be incomplete, fields are initialized from `sensorRef`. 
  442             If there are multiple items, only the first one is used. 
  448             return a pipeBase.Struct: 
  450                 - ``exposure`` : a template calexp 
  451                 - ``sources`` : source catalog measured on the template 
  454         if len(templateIdList) == 0:
 
  455             raise RuntimeError(
"No template data reference supplied.")
 
  456         if len(templateIdList) > 1:
 
  457             self.log.
warning(
"Multiple template data references supplied. Using the first one only.")
 
  459         templateId = sensorRef.dataId.copy()
 
  460         templateId.update(templateIdList[0])
 
  462         self.log.
info(
"Fetching calexp (%s) as template.", templateId)
 
  464         butler = sensorRef.getButler()
 
  465         template = butler.get(datasetType=
"calexp", dataId=templateId)
 
  466         if self.config.doAddCalexpBackground:
 
  467             templateBg = butler.get(datasetType=
"calexpBackground", dataId=templateId)
 
  468             mi = template.getMaskedImage()
 
  469             mi += templateBg.getImage()
 
  471         if not template.hasPsf():
 
  472             raise pipeBase.TaskError(
"Template has no psf")
 
  474         templateSources = butler.get(datasetType=
"src", dataId=templateId)
 
  475         return pipeBase.Struct(exposure=template,
 
  476                                sources=templateSources)
 
  479         return self.
runrun(*args, **kwargs)
 
  482         raise NotImplementedError(
"Calexp template is not supported with gen3 middleware")
 
  486                                             dimensions=(
"instrument", 
"visit", 
"detector", 
"skymap"),
 
  487                                             defaultTemplates={
"coaddName": 
"goodSeeing",
 
  488                                                               "warpTypeSuffix": 
"",
 
  490     bbox = pipeBase.connectionTypes.Input(
 
  491         doc=
"BBoxes of calexp used determine geometry of output template",
 
  492         name=
"{fakesType}calexp.bbox",
 
  493         storageClass=
"Box2I",
 
  494         dimensions=(
"instrument", 
"visit", 
"detector"),
 
  496     wcs = pipeBase.connectionTypes.Input(
 
  497         doc=
"WCSs of calexps that we want to fetch the template for",
 
  498         name=
"{fakesType}calexp.wcs",
 
  500         dimensions=(
"instrument", 
"visit", 
"detector"),
 
  502     skyMap = pipeBase.connectionTypes.Input(
 
  503         doc=
"Input definition of geometry/bbox and projection/wcs for template exposures",
 
  504         name=BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
 
  505         dimensions=(
"skymap", ),
 
  506         storageClass=
"SkyMap",
 
  510     coaddExposures = pipeBase.connectionTypes.Input(
 
  511         doc=
"Input template to match and subtract from the exposure",
 
  512         dimensions=(
"tract", 
"patch", 
"skymap", 
"band"),
 
  513         storageClass=
"ExposureF",
 
  514         name=
"{fakesType}{coaddName}Coadd{warpTypeSuffix}",
 
  518     outputExposure = pipeBase.connectionTypes.Output(
 
  519         doc=
"Warped template used to create `subtractedExposure`.",
 
  520         dimensions=(
"instrument", 
"visit", 
"detector"),
 
  521         storageClass=
"ExposureF",
 
  522         name=
"{fakesType}{coaddName}Diff_templateExp{warpTypeSuffix}",
 
  527                                        pipelineConnections=GetMultiTractCoaddTemplateConnections):
 
  528     warp = pexConfig.ConfigField(
 
  529         dtype=afwMath.Warper.ConfigClass,
 
  530         doc=
"warper configuration",
 
  532     coaddPsf = pexConfig.ConfigField(
 
  533         doc=
"Configuration for CoaddPsf",
 
  534         dtype=CoaddPsfConfig,
 
  538         self.warp.warpingKernelName = 
'lanczos5' 
  539         self.coaddPsf.warpingKernelName = 
'lanczos5' 
  542 class GetMultiTractCoaddTemplateTask(pipeBase.PipelineTask):
 
  543     ConfigClass = GetMultiTractCoaddTemplateConfig
 
  544     _DefaultName = 
"getMultiTractCoaddTemplateTask" 
  546     def __init__(self, *args, **kwargs):
 
  547         super().__init__(*args, **kwargs)
 
  548         self.warper = afwMath.Warper.fromConfig(self.config.warp)
 
  550     def runQuantum(self, butlerQC, inputRefs, outputRefs):
 
  552         inputs = butlerQC.get(inputRefs)
 
  553         inputs[
'coaddExposures'] = self.getOverlappingExposures(inputs)
 
  556         outputs = self.run(**inputs)
 
  557         butlerQC.put(outputs, outputRefs)
 
  559     def getOverlappingExposures(self, inputs):
 
  560         """Return list of coaddExposure DeferredDatasetHandles that overlap detector 
  562         The spatial index in the registry has generous padding and often supplies 
  563         patches near, but not directly overlapping the detector. 
  564         Filters inputs so that we don't have to read in all input coadds. 
  568         inputs : `dict` of task Inputs 
  572         coaddExposures : list of elements of type 
  573                          `lsst.daf.butler.DeferredDatasetHandle` of 
  574                          `lsst.afw.image.Exposure` 
  579             Raised if no patches overlap the input detector bbox 
  585         coaddExposureList = []
 
  586         for coaddRef 
in inputs[
'coaddExposures']:
 
  587             dataId = coaddRef.dataId
 
  588             patchWcs = inputs[
'skyMap'][dataId[
'tract']].getWcs()
 
  589             patchBBox = inputs[
'skyMap'][dataId[
'tract']][dataId[
'patch']].getOuterBBox()
 
  590             patchCorners = patchWcs.pixelToSky(
geom.Box2D(patchBBox).getCorners())
 
  592             if patchPolygon.intersection(detectorPolygon):
 
  593                 overlappingArea += patchPolygon.intersectionSingle(detectorPolygon).calculateArea()
 
  594                 self.log.
info(
"Using template input tract=%s, patch=%s" %
 
  595                               (dataId[
'tract'], dataId[
'patch']))
 
  596                 coaddExposureList.append(coaddRef)
 
  598         if not overlappingArea:
 
  599             raise pipeBase.NoWorkFound(
'No patches overlap detector')
 
  601         return coaddExposureList
 
  603     def run(self, coaddExposures, bbox, wcs):
 
  604         """Warp coadds from multiple tracts to form a template for image diff. 
  606         Where the tracts overlap, the resulting template image is averaged. 
  607         The PSF on the template is created by combining the CoaddPsf on each 
  608         template image into a meta-CoaddPsf. 
  612         coaddExposures: list of DeferredDatasetHandle to `lsst.afw.image.Exposure` 
  613             Coadds to be mosaicked 
  614         bbox : `lsst.geom.Box2I` 
  615             Template Bounding box of the detector geometry onto which to 
  616             resample the coaddExposures 
  617         wcs : `lsst.afw.geom.SkyWcs` 
  618             Template WCS onto which to resample the coaddExposures 
  623             return a pipeBase.Struct: 
  624             - ``outputExposure`` : a template coadd exposure assembled out of patches 
  630             Raised if no patches overlatp the input detector bbox 
  634         tractsSchema = afwTable.ExposureTable.makeMinimalSchema()
 
  635         tractKey = tractsSchema.addField(
'tract', type=np.int32, doc=
'Which tract')
 
  636         patchKey = tractsSchema.addField(
'patch', type=np.int32, doc=
'Which patch')
 
  637         weightKey = tractsSchema.addField(
'weight', type=float, doc=
'Weight for each tract, should be 1')
 
  641         bbox.grow(self.config.templateBorderSize)
 
  648         for coaddExposure 
in coaddExposures:
 
  649             coaddPatch = coaddExposure.get()
 
  652             warped = self.warper.
warpExposure(finalWcs, coaddPatch, maxBBox=finalBBox)
 
  655             if not np.any(np.isfinite(warped.image.array)):
 
  656                 self.log.
info(
"No overlap for warped %s. Skipping" % coaddExposure.ref.dataId)
 
  659             exp = afwImage.ExposureF(finalBBox, finalWcs)
 
  660             exp.maskedImage.set(np.nan, afwImage.Mask.getPlaneBitMask(
"NO_DATA"), np.nan)
 
  661             exp.maskedImage.assign(warped.maskedImage, warped.getBBox())
 
  663             maskedImageList.append(exp.maskedImage)
 
  665             record = tractsCatalog.addNew()
 
  666             record.setPsf(coaddPatch.getPsf())
 
  667             record.setWcs(coaddPatch.getWcs())
 
  668             record.setPhotoCalib(coaddPatch.getPhotoCalib())
 
  669             record.setBBox(coaddPatch.getBBox())
 
  671             record.set(tractKey, coaddExposure.ref.dataId[
'tract'])
 
  672             record.set(patchKey, coaddExposure.ref.dataId[
'patch'])
 
  673             record.set(weightKey, 1.)
 
  676         if nPatchesFound == 0:
 
  677             raise pipeBase.NoWorkFound(
"No patches found to overlap detector")
 
  682         statsCtrl.setNanSafe(
True)
 
  683         statsCtrl.setWeighted(
True)
 
  684         statsCtrl.setCalcErrorFromInputVariance(
True)
 
  686         templateExposure = afwImage.ExposureF(finalBBox, finalWcs)
 
  687         templateExposure.maskedImage.set(np.nan, afwImage.Mask.getPlaneBitMask(
"NO_DATA"), np.nan)
 
  688         xy0 = templateExposure.getXY0()
 
  691                                                                weightList, clipped=0, maskMap=[])
 
  692         templateExposure.maskedImage.setXY0(xy0)
 
  696         boolmask = templateExposure.mask.array & templateExposure.mask.getPlaneBitMask(
'NO_DATA') == 0
 
  698         centerCoord = afwGeom.SpanSet.fromMask(maskx, 1).computeCentroid()
 
  700         ctrl = self.config.coaddPsf.makeControl()
 
  701         coaddPsf = 
CoaddPsf(tractsCatalog, finalWcs, centerCoord, ctrl.warpingKernelName, ctrl.cacheSize)
 
  703             raise RuntimeError(
"CoaddPsf could not be constructed")
 
  705         templateExposure.setPsf(coaddPsf)
 
  706         templateExposure.setFilterLabel(coaddPatch.getFilterLabel())
 
  707         templateExposure.setPhotoCalib(coaddPatch.getPhotoCalib())
 
  708         return pipeBase.Struct(outputExposure=templateExposure)
 
Pass parameters to a Statistics object.
 
Custom catalog class for ExposureRecord/Table.
 
A floating-point coordinate rectangle geometry.
 
An integer coordinate rectangle.
 
def runDataRef(self, *args, **kwargs)
 
def runQuantum(self, **kwargs)
 
def run(self, exposure, sensorRef, templateIdList)
 
def runDataRef(self, exposure, sensorRef, templateIdList=None)
 
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)
 
CoaddPsf is the Psf derived to be used for non-PSF-matched Coadd images.
 
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
 
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
 
Property stringToStatisticsProperty(std::string const property)
Conversion function to switch a string to a Property (see Statistics.h)
 
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.
 
int warpExposure(DestExposureT &destExposure, SrcExposureT const &srcExposure, WarpingControl const &control, typename DestExposureT::MaskedImageT::SinglePixel padValue=lsst::afw::math::edgePixel< typename DestExposureT::MaskedImageT >(typename lsst::afw::image::detail::image_traits< typename DestExposureT::MaskedImageT >::image_category()))
Warp (remap) one exposure to another.
 
def run(self, coaddExposures, bbox, wcs)
 
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations.