lsst.pipe.tasks gb1bf645dd1+9231f36432
Classes | Variables
lsst.pipe.tasks.makeWarp Namespace Reference

Classes

class  MakeWarpConnections
 

Variables

 log = logging.getLogger(__name__)
 
 bgSubtracted
 
 doApplySkyCorr
 
 doApplyExternalSkyWcs
 
 doApplyExternalPhotoCalib
 
 doApplyFinalizedPsf
 

Variable Documentation

◆ bgSubtracted

lsst.pipe.tasks.makeWarp.bgSubtracted
    warpAndPsfMatch = pexConfig.ConfigurableField(
        target=WarpAndPsfMatchTask,
        doc="Task to warp and PSF-match calexp",
    )
    doWrite = pexConfig.Field(
        doc="persist <coaddName>Coadd_<warpType>Warp",
        dtype=bool,
        default=True,
    )
    bgSubtracted = pexConfig.Field(
        doc="Work with a background subtracted calexp?",
        dtype=bool,
        default=True,
    )
    coaddPsf = pexConfig.ConfigField(
        doc="Configuration for CoaddPsf",
        dtype=CoaddPsfConfig,
    )
    makeDirect = pexConfig.Field(
        doc="Make direct Warp/Coadds",
        dtype=bool,
        default=True,
    )
    makePsfMatched = pexConfig.Field(
        doc="Make Psf-Matched Warp/Coadd?",
        dtype=bool,
        default=False,
    )
    doWriteEmptyWarps = pexConfig.Field(
        dtype=bool,
        default=False,
        doc="Write out warps even if they are empty"
    )
    hasFakes = pexConfig.Field(
        doc="Should be set to True if fake sources have been inserted into the input data.",
        dtype=bool,
        default=False,
    )
    doApplySkyCorr = pexConfig.Field(
        dtype=bool,
        default=False,
        doc="Apply sky correction?",
    )
    doApplyFinalizedPsf = pexConfig.Field(
        doc="Whether to apply finalized psf models and aperture correction map.",
        dtype=bool,
        default=True,
    )

    def validate(self):
        CoaddBaseTask.ConfigClass.validate(self)

        if not self.makePsfMatched and not self.makeDirect:
            raise RuntimeError("At least one of config.makePsfMatched and config.makeDirect must be True")
        if self.doPsfMatch:
            # Backwards compatibility.
            log.warning("Config doPsfMatch deprecated. Setting makePsfMatched=True and makeDirect=False")
            self.makePsfMatched = True
            self.makeDirect = False

    def setDefaults(self):
        CoaddBaseTask.ConfigClass.setDefaults(self)
        self.warpAndPsfMatch.psfMatch.kernel.active.kernelSize = self.matchingKernelSize


class MakeWarpTask(CoaddBaseTask):
ConfigClass = MakeWarpConfig
_DefaultName = "makeWarp"

def __init__(self, **kwargs):
    CoaddBaseTask.__init__(self, **kwargs)
    self.makeSubtask("warpAndPsfMatch")
    if self.config.hasFakes:
        self.calexpType = "fakes_calexp"
    else:
        self.calexpType = "calexp"

@utils.inheritDoc(pipeBase.PipelineTask)
def runQuantum(self, butlerQC, inputRefs, outputRefs):
# Obtain the list of input detectors from calExpList.  Sort them by
# detector order (to ensure reproducibility).  Then ensure all input
# lists are in the same sorted detector order.
detectorOrder = [ref.datasetRef.dataId['detector'] for ref in inputRefs.calExpList]
detectorOrder.sort()
inputRefs = reorderRefs(inputRefs, detectorOrder, dataIdKey='detector')

# Read in all inputs.
inputs = butlerQC.get(inputRefs)

# Construct skyInfo expected by `run`.  We remove the SkyMap itself
# from the dictionary so we can pass it as kwargs later.
skyMap = inputs.pop("skyMap")
quantumDataId = butlerQC.quantum.dataId
skyInfo = makeSkyInfo(skyMap, tractId=quantumDataId['tract'], patchId=quantumDataId['patch'])

# Construct list of input DataIds expected by `run`
dataIdList = [ref.datasetRef.dataId for ref in inputRefs.calExpList]
# Construct list of packed integer IDs expected by `run`
ccdIdList = [dataId.pack("visit_detector") for dataId in dataIdList]

# Run the selector and filter out calexps that were not selected
# primarily because they do not overlap the patch
cornerPosList = lsst.geom.Box2D(skyInfo.bbox).getCorners()
coordList = [skyInfo.wcs.pixelToSky(pos) for pos in cornerPosList]
goodIndices = self.select.run(**inputs, coordList=coordList, dataIds=dataIdList)
inputs = self.filterInputs(indices=goodIndices, inputs=inputs)

# Read from disk only the selected calexps
inputs['calExpList'] = [ref.get() for ref in inputs['calExpList']]

# Extract integer visitId requested by `run`
visits = [dataId['visit'] for dataId in dataIdList]
visitId = visits[0]

if self.config.doApplyExternalSkyWcs:
    if self.config.useGlobalExternalSkyWcs:
        externalSkyWcsCatalog = inputs.pop("externalSkyWcsGlobalCatalog")
    else:
        externalSkyWcsCatalog = inputs.pop("externalSkyWcsTractCatalog")
else:
    externalSkyWcsCatalog = None

if self.config.doApplyExternalPhotoCalib:
    if self.config.useGlobalExternalPhotoCalib:
        externalPhotoCalibCatalog = inputs.pop("externalPhotoCalibGlobalCatalog")
    else:
        externalPhotoCalibCatalog = inputs.pop("externalPhotoCalibTractCatalog")
else:
    externalPhotoCalibCatalog = None

if self.config.doApplyFinalizedPsf:
    finalizedPsfApCorrCatalog = inputs.pop("finalizedPsfApCorrCatalog")
else:
    finalizedPsfApCorrCatalog = None

completeIndices = self.prepareCalibratedExposures(**inputs,
                                                  externalSkyWcsCatalog=externalSkyWcsCatalog,
                                                  externalPhotoCalibCatalog=externalPhotoCalibCatalog,
                                                  finalizedPsfApCorrCatalog=finalizedPsfApCorrCatalog)
# Redo the input selection with inputs with complete wcs/photocalib info.
inputs = self.filterInputs(indices=completeIndices, inputs=inputs)

results = self.run(**inputs, visitId=visitId,
                   ccdIdList=[ccdIdList[i] for i in goodIndices],
                   dataIdList=[dataIdList[i] for i in goodIndices],
                   skyInfo=skyInfo)
if self.config.makeDirect and results.exposures["direct"] is not None:
    butlerQC.put(results.exposures["direct"], outputRefs.direct)
if self.config.makePsfMatched and results.exposures["psfMatched"] is not None:
    butlerQC.put(results.exposures["psfMatched"], outputRefs.psfMatched)

@timeMethod
def run(self, calExpList, ccdIdList, skyInfo, visitId=0, dataIdList=None, **kwargs):
warpTypeList = self.getWarpTypeList()

totGoodPix = {warpType: 0 for warpType in warpTypeList}
didSetMetadata = {warpType: False for warpType in warpTypeList}
warps = {warpType: self._prepareEmptyExposure(skyInfo) for warpType in warpTypeList}
inputRecorder = {warpType: self.inputRecorder.makeCoaddTempExpRecorder(visitId, len(calExpList))
                 for warpType in warpTypeList}

modelPsf = self.config.modelPsf.apply() if self.config.makePsfMatched else None
if dataIdList is None:
    dataIdList = ccdIdList

for calExpInd, (calExp, ccdId, dataId) in enumerate(zip(calExpList, ccdIdList, dataIdList)):
    self.log.info("Processing calexp %d of %d for this Warp: id=%s",
                  calExpInd+1, len(calExpList), dataId)

    try:
        warpedAndMatched = self.warpAndPsfMatch.run(calExp, modelPsf=modelPsf,
                                                    wcs=skyInfo.wcs, maxBBox=skyInfo.bbox,
                                                    makeDirect=self.config.makeDirect,
                                                    makePsfMatched=self.config.makePsfMatched)
    except Exception as e:
        self.log.warning("WarpAndPsfMatch failed for calexp %s; skipping it: %s", dataId, e)
        continue
    try:
        numGoodPix = {warpType: 0 for warpType in warpTypeList}
        for warpType in warpTypeList:
            exposure = warpedAndMatched.getDict()[warpType]
            if exposure is None:
                continue
            warp = warps[warpType]
            if didSetMetadata[warpType]:
                mimg = exposure.getMaskedImage()
                mimg *= (warp.getPhotoCalib().getInstFluxAtZeroMagnitude()
                         / exposure.getPhotoCalib().getInstFluxAtZeroMagnitude())
                del mimg
            numGoodPix[warpType] = coaddUtils.copyGoodPixels(
                warp.getMaskedImage(), exposure.getMaskedImage(), self.getBadPixelMask())
            totGoodPix[warpType] += numGoodPix[warpType]
            self.log.debug("Calexp %s has %d good pixels in this patch (%.1f%%) for %s",
                           dataId, numGoodPix[warpType],
                           100.0*numGoodPix[warpType]/skyInfo.bbox.getArea(), warpType)
            if numGoodPix[warpType] > 0 and not didSetMetadata[warpType]:
                warp.info.id = exposure.info.id
                warp.setPhotoCalib(exposure.getPhotoCalib())
                warp.setFilter(exposure.getFilter())
                warp.getInfo().setVisitInfo(exposure.getInfo().getVisitInfo())
                # PSF replaced with CoaddPsf after loop if and only if creating direct warp
                warp.setPsf(exposure.getPsf())
                didSetMetadata[warpType] = True

            # Need inputRecorder for CoaddApCorrMap for both direct and PSF-matched
            inputRecorder[warpType].addCalExp(calExp, ccdId, numGoodPix[warpType])

    except Exception as e:
        self.log.warning("Error processing calexp %s; skipping it: %s", dataId, e)
        continue

for warpType in warpTypeList:
    self.log.info("%sWarp has %d good pixels (%.1f%%)",
                  warpType, totGoodPix[warpType], 100.0*totGoodPix[warpType]/skyInfo.bbox.getArea())

    if totGoodPix[warpType] > 0 and didSetMetadata[warpType]:
        inputRecorder[warpType].finish(warps[warpType], totGoodPix[warpType])
        if warpType == "direct":
            warps[warpType].setPsf(
                CoaddPsf(inputRecorder[warpType].coaddInputs.ccds, skyInfo.wcs,
                         self.config.coaddPsf.makeControl()))
    else:
        if not self.config.doWriteEmptyWarps:
            # No good pixels. Exposure still empty
            warps[warpType] = None
            # NoWorkFound is unnecessary as the downstream tasks will
            # adjust the quantum accordingly.

result = pipeBase.Struct(exposures=warps)
return result

def filterInputs(self, indices, inputs):
for key in inputs.keys():
    # Only down-select on list inputs
    if isinstance(inputs[key], list):
        inputs[key] = [inputs[key][ind] for ind in indices]
return inputs

def prepareCalibratedExposures(self, calExpList, backgroundList=None, skyCorrList=None,
                           externalSkyWcsCatalog=None, externalPhotoCalibCatalog=None,
                           finalizedPsfApCorrCatalog=None,
                           **kwargs):

Definition at line 59 of file makeWarp.py.

◆ doApplyExternalPhotoCalib

lsst.pipe.tasks.makeWarp.doApplyExternalPhotoCalib

Definition at line 481 of file makeWarp.py.

◆ doApplyExternalSkyWcs

lsst.pipe.tasks.makeWarp.doApplyExternalSkyWcs

Definition at line 477 of file makeWarp.py.

◆ doApplyFinalizedPsf

lsst.pipe.tasks.makeWarp.doApplyFinalizedPsf

Definition at line 485 of file makeWarp.py.

◆ doApplySkyCorr

lsst.pipe.tasks.makeWarp.doApplySkyCorr

Definition at line 474 of file makeWarp.py.

◆ log

lsst.pipe.tasks.makeWarp.log = logging.getLogger(__name__)

Definition at line 41 of file makeWarp.py.