LSST Applications g00274db5b6+edbf708997,g00d0e8bbd7+edbf708997,g199a45376c+5137f08352,g1fd858c14a+1d4b6db739,g262e1987ae+f4d9505c4f,g29ae962dfc+7156fb1a53,g2cef7863aa+73c82f25e4,g35bb328faa+edbf708997,g3e17d7035e+5b3adc59f5,g3fd5ace14f+852fa6fbcb,g47891489e3+6dc8069a4c,g53246c7159+edbf708997,g64539dfbff+9f17e571f4,g67b6fd64d1+6dc8069a4c,g74acd417e5+ae494d68d9,g786e29fd12+af89c03590,g7ae74a0b1c+a25e60b391,g7aefaa3e3d+536efcc10a,g7cc15d900a+d121454f8d,g87389fa792+a4172ec7da,g89139ef638+6dc8069a4c,g8d7436a09f+28c28d8d6d,g8ea07a8fe4+db21c37724,g92c671f44c+9f17e571f4,g98df359435+b2e6376b13,g99af87f6a8+b0f4ad7b8d,gac66b60396+966efe6077,gb88ae4c679+7dec8f19df,gbaa8f7a6c5+38b34f4976,gbf99507273+edbf708997,gc24b5d6ed1+9f17e571f4,gca7fc764a6+6dc8069a4c,gcc769fe2a4+97d0256649,gd7ef33dd92+6dc8069a4c,gdab6d2f7ff+ae494d68d9,gdbb4c4dda9+9f17e571f4,ge410e46f29+6dc8069a4c,geaed405ab2+e194be0d2b,w.2025.47
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.pipe.tasks.matchBackgrounds Namespace Reference

Classes

class  ChooseReferenceVisitConfig
 
class  ChooseReferenceVisitTask
 
class  MatchBackgroundsConnections
 

Variables

 config : `MatchBackgroundsConfig`
 
 statsCtrl : `~lsst.afw.math.StatisticsControl`
 
 warps : `list`[`~lsst.afw.image.Exposure`]
 
 skyMap : `lsst.skyMap.SkyMap`
 
 result : `~lsst.afw.math.BackgroundList`, `~lsst.afw.image.Exposure`
 
 refVisitId : `int`
 
 visitTractDifferenceBackrounds : `dict` [`int`, `TractBackground`]
 
 backgroundInfoList : `list`[`TractBackground`]
 
 matchedImageList : `list`[`~lsst.afw.image.ExposureF`]
 
 warp : `~lsst.afw.image.MaskedImageF`
 
 statsFlag : `~lsst.afw.math.Property`
 
 undersampleStyle : `str`
 
 bkgd : `~lsst.afw.math.BackgroundMI`
 
 bgCtrl : `~lsst.afw.math.BackgroundControl`
 

Variable Documentation

◆ backgroundInfoList

lsst.pipe.tasks.matchBackgrounds.backgroundInfoList : `list`[`TractBackground`]

Definition at line 612 of file matchBackgrounds.py.

◆ bgCtrl

lsst.pipe.tasks.matchBackgrounds.bgCtrl : `~lsst.afw.math.BackgroundControl`

Definition at line 677 of file matchBackgrounds.py.

◆ bkgd

lsst.pipe.tasks.matchBackgrounds.bkgd : `~lsst.afw.math.BackgroundMI`

Definition at line 675 of file matchBackgrounds.py.

◆ config

lsst.pipe.tasks.matchBackgrounds.config : `MatchBackgroundsConfig`

Definition at line 398 of file matchBackgrounds.py.

◆ matchedImageList

lsst.pipe.tasks.matchBackgrounds.matchedImageList : `list`[`~lsst.afw.image.ExposureF`]

Definition at line 615 of file matchBackgrounds.py.

◆ refVisitId

lsst.pipe.tasks.matchBackgrounds.refVisitId : `int`

Definition at line 479 of file matchBackgrounds.py.

◆ result

lsst.pipe.tasks.matchBackgrounds.result : `~lsst.afw.math.BackgroundList`, `~lsst.afw.image.Exposure`

Definition at line 443 of file matchBackgrounds.py.

◆ skyMap

lsst.pipe.tasks.matchBackgrounds.skyMap : `lsst.skyMap.SkyMap`

Definition at line 438 of file matchBackgrounds.py.

◆ statsCtrl

lsst.pipe.tasks.matchBackgrounds.statsCtrl : `~lsst.afw.math.StatisticsControl`

Definition at line 400 of file matchBackgrounds.py.

◆ statsFlag

lsst.pipe.tasks.matchBackgrounds.statsFlag : `~lsst.afw.math.Property`

Definition at line 667 of file matchBackgrounds.py.

◆ undersampleStyle

lsst.pipe.tasks.matchBackgrounds.undersampleStyle : `str`

Definition at line 669 of file matchBackgrounds.py.

◆ visitTractDifferenceBackrounds

lsst.pipe.tasks.matchBackgrounds.visitTractDifferenceBackrounds : `dict` [`int`, `TractBackground`]

Definition at line 484 of file matchBackgrounds.py.

◆ warp

lsst.pipe.tasks.matchBackgrounds.warp : `~lsst.afw.image.MaskedImageF`
visits = np.unique([i.dataId["visit"] for i in warps])
self.log.info("Processing %d visits", len(visits))

backgroundInfoList = []
matchedImageList = []
diffTractBackgrounds = self._makeTractDifferenceBackgrounds(warps, skyMap, refVisitId)

# Reference visit doesn't need an offset image, so use all 0's
im = warps[0].get()  # Use arbitrary image as base
bkgd = diffTractBackgrounds[refVisitId].toWarpBackground(im)
blank = bkgd.getImage()
blank *= 0

for warp in warps:
    visId = warp.dataId["visit"]
    if visId == refVisitId:
        backgroundInfoList.append(bkgd)  # Just append a 0 image
        matchedImageList.append(warp.get())
        continue
    self.log.info(
        "Matching background of %s to same patch in visit %s",
        warp.dataId,
        refVisitId,
    )
    im = warp.get()
    maskIm = im.getMaskedImage()
    tractBg = diffTractBackgrounds[visId]
    diffModel = tractBg.toWarpBackground(im)
    bkgdIm = diffModel.getImage()
    maskIm.image += bkgdIm

    backgroundInfoList.append(diffModel)
    matchedImageList.append(im)

return backgroundInfoList, matchedImageList


def fitBackground(
warp: MaskedImageF, statsCtrl, statsFlag, undersampleStyle
) -> tuple[BackgroundMI, BackgroundControl]:

Definition at line 663 of file matchBackgrounds.py.

◆ warps

lsst.pipe.tasks.matchBackgrounds.warps : `list`[`~lsst.afw.image.Exposure`]
ConfigClass = MatchBackgroundsConfig
config: MatchBackgroundsConfig
_DefaultName = "matchBackgrounds"

def __init__(self, *args, **kwargs):
    super().__init__(**kwargs)
    # Fits on binned images only; masking controlled in tractBackground.py
    self.statsFlag = stringToStatisticsProperty(self.config.gridStatistic)
    self.statsCtrl = StatisticsControl()
    self.statsCtrl.setNanSafe(True)
    self.statsCtrl.setNumSigmaClip(self.config.numSigmaClip)
    self.statsCtrl.setNumIter(self.config.numIter)
    self.stringToInterpStyle = stringToInterpStyle(self.config.interpStyle)
    self.undersampleStyle = stringToUndersampleStyle(self.config.undersampleStyle)

    self.makeSubtask("reference")

@timeMethod
def run(self, warps, skyMap):
# TODO: include warped backgroundToPhotometricRatio correction
if (numExp := len(warps)) < 1:
    self.log.warning("No exposures found!  Returning empty lists.")
    return Struct(backgroundInfoList=[], matchedImageList=[])

if self.config.refWarpVisit is None:
    # Build FFP BG models of each visit
    visitTractBgs = self.reference._makeTractBackgrounds(warps, skyMap)
    # Choose a reference visit using those
    refVisId = self.reference._defineWarps(visitTractBgs)
else:
    self.log.info("Using user-supplied reference visit %d", self.config.refWarpVisit)
    refVisId = self.config.refWarpVisit

self.log.info("Matching %d Exposures", numExp)

backgroundInfoList, matchedImageList = self.matchBackgrounds(warps, skyMap, refVisId)

return Struct(backgroundInfoList=backgroundInfoList, matchedImageList=matchedImageList)

@timeMethod
def _makeTractDifferenceBackgrounds(self, warps, skyMap, refVisitId):
# First, separate warps by visit
visits = np.unique([i.dataId["visit"] for i in warps])

# Then build difference image background models for each visit & store
visitTractDifferenceBackgrounds = {}
for i in range(len(visits)):
    visitWarpDDFs = [j for j in warps if j.dataId["visit"] == visits[i]]
    refWarpDDFs = [j for j in warps if j.dataId["visit"] == refVisitId]
    refPatches = [j.dataId["patch"] for j in refWarpDDFs]
    # Set up empty full tract background model object
    bgModelBase = TractBackground(
        config=self.config.tractBgModel, skymap=skyMap, tract=warps[0].dataId["tract"]
    )

    bgModels = []
    for warp in visitWarpDDFs:
        msg = "Constructing FFP background model for reference visit %d - visit %d using %d patches"
        self.log.debug(
            msg,
            refVisitId,
            visits[i],
            len(visitWarpDDFs),
        )
        workingWarp = warp.get()

        patchId = warp.dataId["patch"]
        # On no overlap between working warp and reference visit, set
        # the image to all NaN
        try:
            idx = refPatches.index(patchId)
            refWarp = refWarpDDFs[idx].get()
        except ValueError:
            refWarp = workingWarp.clone()
            refWarp.image += np.nan
        workingWarp.image.array = refWarp.image.array - workingWarp.image.array

        bgModel = bgModelBase.clone()
        bgModel.addWarp(workingWarp)
        bgModels.append(bgModel)

    # Merge warp difference models to make a single full tract
    # background difference model
    for bgModel, warp in zip(bgModels, visitWarpDDFs):
        msg = (
            "Patch %d: Merging %d unmasked pixels (%.1f%s of detector area) into full tract "
            "difference background model"
        )
        self.log.debug(
            msg,
            warp.dataId["patch"],
            bgModel._numbers.getArray().sum(),
            100 * bgModel._numbers.getArray().sum() / workingWarp.getBBox().getArea(),
            "%",
        )
        bgModelBase += bgModel

    # Fit full tract background to generate offset image
    if visits[i] != refVisitId:
        bgModelImage = bgModelBase.getStatsImage()
        # Note: this just extrapolates into regions of no overlap
        # between reference and visit
        bkgd, _ = fitBackground(
            bgModelImage, self.statsCtrl, self.statsFlag, self.config.undersampleStyle
        )
        try:
            bkgdImage = bkgd.getImageF(self.config.interpStyle, self.config.undersampleStyle)
        except Exception as e:
            e.add_note(f"on image {warp.dataId}")
            raise
        # Calculate RMS and MSE of fit and print as log
        resids = ImageF(bgModelImage.array - bkgdImage.array)
        rms = np.sqrt(np.nanmean(resids.array**2))
        mse = makeStatistics(resids, MEANSQUARE, self.statsCtrl).getValue()

        self.log.info(
            "Visit %d; difference BG fit RMS=%.2f nJy, matched MSE=%.2f nJy",
            visits[i],
            rms,
            mse,
        )
        # Replace binned difference image w/best-fit model.
        # Resetting numbers to override interpolation
        bgModelBase._numbers.array[:] = 1e6  # Arbitrarily large value
        bgModelBase._values.array = bkgdImage.array * bgModelBase._numbers.array

    visitTractDifferenceBackgrounds[visits[i]] = bgModelBase

return visitTractDifferenceBackgrounds

@timeMethod
def matchBackgrounds(self, warps, skyMap, refVisitId):

Definition at line 436 of file matchBackgrounds.py.