Skip to content

Commit

Permalink
Allow using external cals even if calexp WCS is None
Browse files Browse the repository at this point in the history
This also reorders the selection of suitable calexps such that the
selection based on patch overlap is based on the final calibrated
WCS (i.e. if an external calibration is being applied, this one will
be used instead of the calibration based on single frame measurement).
  • Loading branch information
laurenam committed Jul 20, 2022
1 parent 06f9e8c commit 9315fef
Showing 1 changed file with 34 additions and 17 deletions.
51 changes: 34 additions & 17 deletions python/lsst/pipe/tasks/makeCoaddTempExp.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import lsst.pipe.base.connectionTypes as connectionTypes
import lsst.utils as utils
import lsst.geom
from lsst.daf.butler import DeferredDatasetHandle
from lsst.meas.algorithms import CoaddPsf, CoaddPsfConfig
from lsst.skymap import BaseSkyMap
from lsst.utils.timer import timeMethod
Expand Down Expand Up @@ -790,20 +791,6 @@ def runQuantum(self, butlerQC, inputRefs, outputRefs):
# 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")
Expand All @@ -825,13 +812,25 @@ def runQuantum(self, butlerQC, inputRefs, outputRefs):
else:
finalizedPsfApCorrCatalog = None

# Do an initial selection on inputs with complete wcs/photoCalib info.
# Qualifying calexps will be read in the following call.
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)

# Do another selection based on the configured selection task
# (using updated WCSs to determine patch overlap if an external
# calibration was applied).
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)

# Extract integer visitId requested by `run`
visitId = dataIdList[0]["visit"]

results = self.run(**inputs, visitId=visitId,
ccdIdList=[ccdIdList[i] for i in goodIndices],
dataIdList=[dataIdList[i] for i in goodIndices],
Expand All @@ -855,16 +854,23 @@ def filterInputs(self, indices, inputs):
inputs[key] = [inputs[key][ind] for ind in indices]
return inputs

def prepareCalibratedExposures(self, calExpList, backgroundList=None, skyCorrList=None,
def prepareCalibratedExposures(self, calExpList, wcsList, backgroundList=None, skyCorrList=None,
externalSkyWcsCatalog=None, externalPhotoCalibCatalog=None,
finalizedPsfApCorrCatalog=None,
**kwargs):
"""Calibrate and add backgrounds to input calExpList in place
Parameters
----------
calExpList : `list` of `lsst.afw.image.Exposure`
calExpList : `list` of `lsst.afw.image.Exposure` or
`lsst.daf.butler.DeferredDatasetHandle`
Sequence of calexps to be modified in place
wcsList : `list` of `lsst.afw.geom.SkyWcs`
The WCSs of the calexps in ``calExpList``. When
``externalSkyCatalog`` is `None`, these are used to determine if
the calexp should be included in the warp, namely checking that it
is not `None`. If ``externalSkyCatalog`` is not `None`, this list
will be dynamically updates with the external sky WCS.
backgroundList : `list` of `lsst.afw.math.backgroundList`, optional
Sequence of backgrounds to be added back in if bgSubtracted=False
skyCorrList : `list` of `lsst.afw.math.backgroundList`, optional
Expand Down Expand Up @@ -896,6 +902,14 @@ def prepareCalibratedExposures(self, calExpList, backgroundList=None, skyCorrLis
for index, (calexp, background, skyCorr) in enumerate(zip(calExpList,
backgroundList,
skyCorrList)):
if externalSkyWcsCatalog is None and wcsList[index] is None:
self.log.warning("Detector id %d for visit %d has None for skyWcs and will not be "
"used in the warp", calexp.dataId["detector"], calexp.dataId["visit"])
continue

if isinstance(calexp, DeferredDatasetHandle):
calexp = calexp.get()

if not self.config.bgSubtracted:
calexp.maskedImage += background.getImage()

Expand Down Expand Up @@ -929,13 +943,15 @@ def prepareCalibratedExposures(self, calExpList, backgroundList=None, skyCorrLis
"and will not be used in the warp.", detectorId)
continue
skyWcs = row.getWcs()
wcsList[index] = skyWcs
if skyWcs is None:
self.log.warning("Detector id %s has None for skyWcs in externalSkyWcsCatalog "
"and will not be used in the warp.", detectorId)
continue
calexp.setWcs(skyWcs)
else:
skyWcs = calexp.getWcs()
wcsList[index] = skyWcs
if skyWcs is None:
self.log.warning("Detector id %s has None for skyWcs in the calexp "
"and will not be used in the warp.", detectorId)
Expand Down Expand Up @@ -973,6 +989,7 @@ def prepareCalibratedExposures(self, calExpList, backgroundList=None, skyCorrLis
calexp.maskedImage -= skyCorr.getImage()

indices.append(index)
calExpList[index] = calexp

return indices

Expand Down

0 comments on commit 9315fef

Please sign in to comment.