From 8dfbe5e4380cdb96bcab189fe82d6fcf88ffadc9 Mon Sep 17 00:00:00 2001 From: Aaron Watkins Date: Wed, 10 Jul 2024 01:10:25 -0700 Subject: [PATCH] Change output from Struct to BackgroundList Code is now functional, in that it accepts images and returns difference image background models as "psfMatchedWarpBackground_diff" (name likely to be altered later). Uses a fit to a blank image for that corresponding to the reference image. --- python/lsst/pipe/tasks/matchBackgrounds.py | 58 ++++++++++++++-------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/python/lsst/pipe/tasks/matchBackgrounds.py b/python/lsst/pipe/tasks/matchBackgrounds.py index 2a78aa49e..a9bfc84a2 100644 --- a/python/lsst/pipe/tasks/matchBackgrounds.py +++ b/python/lsst/pipe/tasks/matchBackgrounds.py @@ -62,8 +62,8 @@ class MatchBackgroundsConnections(PipelineTaskConnections, # This needs to be the models of each differential BG in warped coords backgroundInfoList = cT.Output( doc="List of differential backgrounds, w/goodness of fit params", - name="calexpBackground_diff", # This needs to change - dimensions=("visit", "detector",), + name="psfMatchedWarpBackground_diff", # This needs to change + dimensions=("tract", "patch", "skymap", "visit"), storageClass="Background", multiple=True, ) @@ -280,16 +280,35 @@ def run(self, psfMatchedWarps): self.log.info("Matching %d Exposures", numExp) + # Creating a null BackgroundList object by fitting a blank image + statsFlag = getattr(afwMath, self.config.gridStatistic) + self.sctrl.setNumSigmaClip(self.config.numSigmaClip) + self.sctrl.setNumIter(self.config.numIter) + + # TODO: refactor below to construct blank bg model + im = refExposure.getMaskedImage() + blankIm = im.Factory(im, True) # Don't do this + blankIm.image.array *= 0 + + width = blankIm.getWidth() + height = blankIm.getHeight() + nx = width // self.config.binSize + if width % self.config.binSize != 0: + nx += 1 + ny = height // self.config.binSize + if height % self.config.binSize != 0: + ny += 1 + + bctrl = afwMath.BackgroundControl(nx, ny, self.sctrl, statsFlag) + bctrl.setUndersampleStyle(self.config.undersampleStyle) + + bkgd = afwMath.makeBackground(blankIm, bctrl) + + backgroundInfoList = [] for ind, exp in enumerate(psfMatchedWarps): if ind in refIndSet: - backgroundInfoStruct = pipeBase.Struct( - isReference=True, - backgroundModel=None, - fitRMS=0.0, - matchedMSE=None, - diffImVar=None, - ) + backgroundInfoStruct = afwMath.BackgroundList(bkgd,) else: self.log.info("Matching background of %s to %s", exp.dataId, refMatchedWarp.dataId) toMatchExposure = exp.get() @@ -307,13 +326,7 @@ def run(self, psfMatchedWarps): backgroundInfoStruct.isReference = False except Exception as e: # self.log.warning("Failed to fit background %s: %s", toMatchRef.dataId, e) - backgroundInfoStruct = pipeBase.Struct( - isReference=False, - backgroundModel=None, - fitRMS=None, - matchedMSE=None, - diffImVar=None, - ) + backgroundInfoStruct = afwMath.BackgroundList(bkgd,) backgroundInfoList.append(backgroundInfoStruct) @@ -545,11 +558,14 @@ def matchBackgrounds(self, refExposure, sciExposure): outBkgd = approx if self.config.usePolynomial else bkgd - return pipeBase.Struct( - backgroundModel=outBkgd, - fitRMS=rms, - matchedMSE=mse, - diffImVar=meanVar) + # Type `Background` can't use a struct. Should fitRMS &c. be added to + # a log instead of output? + # return pipeBase.Struct( + # backgroundModel=afwMath.BackgroundList(outBkgd), + # fitRMS=rms, + # matchedMSE=mse, + # diffImVar=meanVar) + return afwMath.BackgroundList(outBkgd,) def _fluxScale(self, exposure): """Scales image to nJy flux using photometric calibration.