diff --git a/python/lsst/meas/extensions/scarlet/io.py b/python/lsst/meas/extensions/scarlet/io.py index 83ebb84..36e1707 100644 --- a/python/lsst/meas/extensions/scarlet/io.py +++ b/python/lsst/meas/extensions/scarlet/io.py @@ -41,7 +41,7 @@ # The name of the band in an monochome blend. # This is used as a placeholder since the band is not used in the # monochromatic model. -monochromeBand = "dummmy" +monochromeBand = "dummy" monochromeBands = (monochromeBand,) def monochromaticDataToScarlet( @@ -128,6 +128,7 @@ def updateCatalogFootprints( imageForRedistribution: MaskedImage | Exposure | None = None, removeScarletData: bool = True, updateFluxColumns: bool = True, + bbox: scl.Box | None = None, ) -> dict[int, scl.Blend]: """Use the scarlet models to set HeavyFootprints for modeled sources @@ -163,6 +164,7 @@ def updateCatalogFootprints( imageForRedistribution=imageForRedistribution, bandIndex=bandIndex, removeScarletData=removeScarletData, + bbox=bbox, ) for blendId, blend in blends.items(): @@ -244,6 +246,35 @@ def extraxctMonochrmaticBlends( removeScarletData: bool = True, bbox: scl.Box | None = None, ) -> dict[int, scl.Blend]: + """Extract the monochromatic blends from the scarlet model data + + Parameters + ---------- + modelData: + The scarlet model data. + catalog: + The catalog that is being updated. + modelPsf: + The 2D model of the PSF. + observedPsf: + The observed PSF model for the catalog. + imageForRedistribution: + The image that is the source for flux re-distribution. + If `imageForRedistribution` is `None` then flux re-distribution is + not performed. + bandIndex: + The number of the band to extract. + removeScarletData: + Whether or not to remove `ScarletBlendData` for each blend + in order to save memory. + bbox: + The bounding box of the image to create the weight image for. + + Returns + ------- + blends : + A dictionary of blends extracted from the model data. + """ blends = {} # Create an observation for the entire image observation = buildMonochromeObservation( @@ -395,7 +426,6 @@ def updateBlendRecords( ) if updateFluxColumns: - assert imageForRedistribution is not None if heavy.getArea() == 0: # The source has no flux after being weighted with the PSF # in this particular band (it might have flux in others). @@ -412,9 +442,6 @@ def updateBlendRecords( else: sourceRecord.set("deblend_zeroFlux", False) sourceRecord.setFootprint(heavy) - calculateFootprintCoverage( - sourceRecord.getFootprint(), imageForRedistribution.mask - ) if useFlux: # Set the fraction of pixels with valid data. diff --git a/tests/test_deblend.py b/tests/test_deblend.py index ecdf682..a30cdac 100644 --- a/tests/test_deblend.py +++ b/tests/test_deblend.py @@ -22,6 +22,7 @@ import unittest import lsst.afw.image as afwImage +import lsst.meas.extensions.scarlet as mes import lsst.scarlet.lite as scl import lsst.utils.tests import numpy as np @@ -30,12 +31,8 @@ from lsst.afw.table import SourceCatalog from lsst.geom import Point2D, Point2I from lsst.meas.algorithms import SourceDetectionTask -from lsst.meas.extensions.scarlet.io import ( - monochromaticDataToScarlet, - updateCatalogFootprints, -) from lsst.meas.extensions.scarlet.scarletDeblendTask import ScarletDeblendTask -from lsst.meas.extensions.scarlet.utils import bboxToScarletBox, scarletBoxToBBox +from lsst.meas.extensions.scarlet.deconvolveExposureTask import DeconvolveExposureTask from numpy.testing import assert_almost_equal from utils import initData @@ -151,6 +148,14 @@ def _deblend(self, version): detectionResult = detectionTask.run(table, self.coadds["r"]) catalog = detectionResult.sources + # Deconvolve the coadds + deconvolvedCoadds = [] + deconvolveTask = DeconvolveExposureTask() + for coadd in self.coadds: + deconvolvedCoadd = deconvolveTask.run(coadd, catalog).deconvolved + deconvolvedCoadds.append(deconvolvedCoadd) + mDeconvolved = afwImage.MultibandExposure.fromExposures(self.bands, deconvolvedCoadds) + # Add a footprint that is too large src = catalog.addNew() halfLength = int(np.ceil(np.sqrt(config.maxFootprintArea) + 1)) @@ -168,7 +173,7 @@ def _deblend(self, version): src.setFootprint(denseFoot) # Run the deblender - catalog, modelData = deblendTask.run(self.coadds, catalog) + catalog, modelData = deblendTask.run(self.coadds, mDeconvolved, catalog) return catalog, modelData, config def test_deblend_task(self): @@ -187,15 +192,19 @@ def test_deblend_task(self): if useFlux: imageForRedistribution = coadd + bbox = None else: imageForRedistribution = None + bbox = mes.utils.bboxToScarletBox(coadd.getBBox()) - updateCatalogFootprints( + mes.io.updateCatalogFootprints( modelData, catalog, band=band, imageForRedistribution=imageForRedistribution, removeScarletData=False, + updateFluxColumns=True, + bbox = bbox, ) # Check that the number of deblended children is consistent @@ -262,7 +271,7 @@ def test_deblend_task(self): bbox=modelBox, dtype=np.float32, ) - blend = monochromaticDataToScarlet( + blend = mes.io.monochromaticDataToScarlet( blendData=blendData, bandIndex=bandIndex, observation=observation, @@ -278,6 +287,7 @@ def test_deblend_task(self): self.assertEqual(source.center[0], py) if useFlux: + assert imageForRedistribution is not None # Get the flux re-weighted model and test against # the HeavyFootprint. # The HeavyFootprint needs to be projected onto @@ -301,7 +311,7 @@ def test_deblend_task(self): ) blend.conserve_flux() model = source.flux_weighted_image.data[0] - bbox = scarletBoxToBBox(source.flux_weighted_image.bbox) + bbox = mes.utils.scarletBoxToBBox(source.flux_weighted_image.bbox) image = afwImage.ImageF(model, xy0=bbox.getMin()) fp.insert(image) np.testing.assert_almost_equal(image.array, model) @@ -309,7 +319,7 @@ def test_deblend_task(self): # Get the model for the source and test # against the HeavyFootprint bbox = fp.getBBox() - bbox = bboxToScarletBox(bbox) + bbox = mes.utils.bboxToScarletBox(bbox) model = blend.observation.convolve( source.get_model().project(bbox=bbox), mode="real" ).data[0]