lsst.pipe.tasks g0e56ae04e6+8102d5cb36
Loading...
Searching...
No Matches
lsst.pipe.tasks.multiBand Namespace Reference

Classes

class  DetectCoaddSourcesConnections
class  MeasureMergedCoaddSourcesConnections

Functions

 run (self, exposure, idFactory, expId, patchInfo=None)
 _cropToExactBinning (self, exposure, patchInfo)
 _makeEmptyBackground (self, exposure, patchInfo=None)

Variables

tuple DEEP_COADD_BACKGROUND_DOCSTRING
 useCellCoadd
 detectedMask = exposure.mask.getMaskPlane(maskName)
 error
 schema : ``lsst.afw.table.Schema`, optional
 peakSchema : ``lsst.afw.table.Schema`, optional
 initInputs : `dict`, optional
 exposure : `lsst.afw.image.Exposure`
 sources : `lsst.afw.table.SourceCatalog`
 parentCatalog : `lsst.afw.table.SourceCatalog`
 skyInfo : `lsst.pipe.base.Struct`
 exposureId : `int` or `bytes`
 ccdInputs : `lsst.afw.table.ExposureCatalog`, optional
 sourceTableHandleDict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`], optional
 finalizedSourceTableHandleDict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`], optional
 finalVisitSummaryHandleDict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`], optional
 apCorrMap : `lsst.afw.image.ApCorrMap`, optional
 results : `lsst.pipe.base.Struct`

Function Documentation

◆ _cropToExactBinning()

_cropToExactBinning ( self,
exposure,
patchInfo )
protected
Crop a coadd `~lsst.afw.image.Exposure` instance to ensure exact
background binning.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure to crop, assumed to cover the patch outer bounding box.
patchInfo : `lsst.skymap.PatchInfo`
    Description of the patch geometry.

Returns
-------
cropped : `lsst.afw.image.Exposure`
    View of ``exposure`` with background bins that evenly divide both
    the full cropped image and the patch inner region.  The bounding
    box is guaranteed to contain the patch inner bounding box and be
    contained by the patch outer bounding box.

Raises
------
ValueError
    Raised if the patch inner region width or height is not a multiple
    of the background bin size.

Definition at line 446 of file multiBand.py.

◆ _makeEmptyBackground()

_makeEmptyBackground ( self,
exposure,
patchInfo = None )
protected
Construct an empty `lsst.afw.math.BackgroundList` with NaN values.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    Exposure that the background should correspond to.
patchInfo : `lsst.skymap.PatchInfo`, optional
    Description of the patch geometry.  Only needed if
    `~DetectCoaddSourceConfig.forceExactBinning` is `True`.

Returns
-------
background : `lsst.afw.math.BackgroundList`
    A background object with a single layer and the same bin geometry
    that a background for that exposure would have had if it had enough
    usable pixels.  This object cannot actually be used for background
    subtraction.

Definition at line 497 of file multiBand.py.

◆ run()

run ( self,
exposure,
idFactory,
expId,
patchInfo = None )
Run detection on an exposure.

First scale the variance plane to match the observed variance
using ``ScaleVarianceTask``. Then invoke the ``SourceDetectionTask_`` "detection" subtask to
detect sources.

Parameters
----------
exposure : `lsst.afw.image.Exposure` or `lsst.images.cells.CellCoadd`.
    Exposure on which to detect (may be background-subtracted and scaled,
    depending on configuration).
idFactory : `lsst.afw.table.IdFactory`
    IdFactory to set source identifiers.
expId : `int`
    Exposure identifier (integer) for RNG seed.
patchInfo : `lsst.skymap.PatchInfo`, optional
    Description of the patch geometry.  Only needed if
    `~DetectCoaddSourceConfig.forceExactBinning` is `True`.

Returns
-------
result : `lsst.pipe.base.Struct`
    Results as a struct with attributes:

    ``outputSources``
        Catalog of detections (`lsst.afw.table.SourceCatalog`).
    ``outputBackgrounds``
        List of backgrounds (`list`).
    ``outputExposure``
        The background-subtracted coadd image, with its mask plane
        updated to include detections.  This will have the same type
        as ``exposure``.

Definition at line 372 of file multiBand.py.

Variable Documentation

◆ apCorrMap

lsst.pipe.tasks.multiBand.apCorrMap : `lsst.afw.image.ApCorrMap`, optional

Definition at line 943 of file multiBand.py.

◆ ccdInputs

lsst.pipe.tasks.multiBand.ccdInputs : `lsst.afw.table.ExposureCatalog`, optional

Definition at line 931 of file multiBand.py.

◆ DEEP_COADD_BACKGROUND_DOCSTRING

tuple lsst.pipe.tasks.multiBand.DEEP_COADD_BACKGROUND_DOCSTRING
Initial value:
= (
"Background subtracted from the image when generating the Object catalog. "
"This intentionally oversubtracts the background to reduce blending and ensure "
"scattered light is subtracted. "
"Restoring this background does not restore all original backgrounds, "
"as the coadd was built from background-subtracted visit images; in most "
"cases this background term is actually quite small "
)

Definition at line 95 of file multiBand.py.

◆ detectedMask

lsst.pipe.tasks.multiBand.detectedMask = exposure.mask.getMaskPlane(maskName)

Definition at line 359 of file multiBand.py.

◆ error

lsst.pipe.tasks.multiBand.error
Initial value:
= AnnotatedPartialOutputsError.annotate(
e,
self,
exposure,
log=self.log,
)

Definition at line 361 of file multiBand.py.

◆ exposure

lsst.pipe.tasks.multiBand.exposure : `lsst.afw.image.Exposure`
_DefaultName = "measureCoaddSources"
ConfigClass = MeasureMergedCoaddSourcesConfig

def __init__(self, schema=None, peakSchema=None, initInputs=None, **kwargs):
    super().__init__(**kwargs)
    if initInputs is not None:
        schema = initInputs['inputSchema'].schema
    if schema is None:
        raise ValueError("Schema must be defined.")
    self.schemaMapper = afwTable.SchemaMapper(schema)
    self.schemaMapper.addMinimalSchema(schema)
    self.schema = self.schemaMapper.getOutputSchema()
    self.algMetadata = PropertyList()
    self.makeSubtask("measurement", schema=self.schema, algMetadata=self.algMetadata)
    self.makeSubtask("setPrimaryFlags", schema=self.schema)
    if self.config.doPropagateFlags:
        self.makeSubtask("propagateFlags", schema=self.schema)
    self.schema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
    if self.config.doApCorr:
        self.makeSubtask("applyApCorr", schema=self.schema)
    if self.config.doRunCatalogCalculation:
        self.makeSubtask("catalogCalculation", schema=self.schema)

    self.outputSchema = afwTable.SourceCatalog(self.schema)

def runQuantum(self, butlerQC, inputRefs, outputRefs):
    inputs = butlerQC.get(inputRefs)

    if self.config.imageType == "future":
        coadd = inputs.pop("exposure")
        band = inputRefs.exposure.dataId["band"]
        # Instead of going directly from lsst.images.cells.CellCoadd to
        # Exposure, it's cleaner for now to go through MultipleCellCoadd
        # because the apCorrMap and ccdInputs need special handling - the
        # cell-based versions can't be attached to Exposure.  Eventually
        # we'll rewrite the lower-level code to use the lsst.images
        # equivalents natively.
        coadd = coadd.to_legacy_cell_coadd()
    elif self.config.useCellCoadds:
        coadd = inputs.pop("exposure_cells")
        band = inputRefs.exposure_cells.dataId["band"]
    else:
        coadd = inputs.pop("exposure")
        band = inputRefs.exposure.dataId["band"]
    if isinstance(coadd, MultipleCellCoadd):
        stitched_coadd = coadd.stitch()
        exposure = stitched_coadd.asExposure()
        if self.config.imageType == "legacy":
            background = inputs.pop("background")
            exposure.image -= background.getImage()
        ccdInputs = stitched_coadd.ccds
        apCorrMap = stitched_coadd.ap_corr_map
    else:
        exposure = coadd
        # Set psfcache only when we don't have a cell-based coadd.
        exposure.getPsf().setCacheCapacity(self.config.psfCache)

        ccdInputs = exposure.getInfo().getCoaddInputs().ccds
        apCorrMap = exposure.getInfo().getApCorrMap()

    # Get unique integer ID for IdFactory and RNG seeds; only the latter
    # should really be used as the IDs all come from the input catalog.
    idGenerator = self.config.idGenerator.apply(butlerQC.quantum.dataId)

    # Transform inputCatalog
    table = afwTable.SourceTable.make(self.schema, idGenerator.make_table_id_factory())
    sources = afwTable.SourceCatalog(table)
    # Load the correct input catalog
    inputCatalog = inputs.pop("scarletCatalog")
    catalogRef = inputRefs.scarletCatalog
    sources.extend(inputCatalog, self.schemaMapper)
    del inputCatalog
    # Add the HeavyFootprints to the deblended sources
    if self.config.doAddFootprints:
        modelData = inputs.pop('scarletModels')
        if self.config.doConserveFlux:
            imageForRedistribution = exposure
        else:
            imageForRedistribution = None
        updateCatalogFootprints(
            modelData=modelData,
            catalog=sources,
            band=band,
            imageForRedistribution=imageForRedistribution,
            removeScarletData=True,
            updateFluxColumns=True,
        )
    table = sources.getTable()
    table.setMetadata(self.algMetadata)  # Capture algorithm metadata to write out to the source catalog.

    skyMap = inputs.pop('skyMap')
    tractNumber = catalogRef.dataId['tract']
    tractInfo = skyMap[tractNumber]
    patchInfo = tractInfo.getPatchInfo(catalogRef.dataId['patch'])
    skyInfo = Struct(
        skyMap=skyMap,
        tractInfo=tractInfo,
        patchInfo=patchInfo,
        wcs=tractInfo.getWcs(),
        bbox=patchInfo.getOuterBBox()
    )

    sourceTableHandleDict = None
    finalizedSourceTableHandleDict = None
    finalVisitSummaryHandleDict = None
    if self.config.doPropagateFlags:
        if "sourceTableHandles" in inputs:
            sourceTableHandles = inputs.pop("sourceTableHandles")
            sourceTableHandleDict = {handle.dataId["visit"]: handle for handle in sourceTableHandles}
        if "finalizedSourceTableHandles" in inputs:
            finalizedSourceTableHandles = inputs.pop("finalizedSourceTableHandles")
            finalizedSourceTableHandleDict = {handle.dataId["visit"]: handle
                                              for handle in finalizedSourceTableHandles}
        if "finalVisitSummaryHandles" in inputs:
            finalVisitSummaryHandles = inputs.pop("finalVisitSummaryHandles")
            finalVisitSummaryHandleDict = {handle.dataId["visit"]: handle
                                           for handle in finalVisitSummaryHandles}

    assert not inputs, "runQuantum got more inputs than expected."
    outputs = self.run(
        exposure=exposure,
        sources=sources,
        skyInfo=skyInfo,
        exposureId=idGenerator.catalog_id,
        ccdInputs=ccdInputs,
        sourceTableHandleDict=sourceTableHandleDict,
        finalizedSourceTableHandleDict=finalizedSourceTableHandleDict,
        finalVisitSummaryHandleDict=finalVisitSummaryHandleDict,
        apCorrMap=apCorrMap,
    )
    # Strip HeavyFootprints to save space on disk
    if self.config.doStripFootprints:
        sources = outputs.outputSources
        for source in sources[sources["parent"] != 0]:
            source.setFootprint(None)
    butlerQC.put(outputs, outputRefs)

def run(self, exposure, sources, skyInfo, exposureId, ccdInputs=None,
        sourceTableHandleDict=None, finalizedSourceTableHandleDict=None, finalVisitSummaryHandleDict=None,
        apCorrMap=None):

Definition at line 919 of file multiBand.py.

◆ exposureId

lsst.pipe.tasks.multiBand.exposureId : `int` or `bytes`

Definition at line 929 of file multiBand.py.

◆ finalizedSourceTableHandleDict

lsst.pipe.tasks.multiBand.finalizedSourceTableHandleDict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`], optional

Definition at line 937 of file multiBand.py.

◆ finalVisitSummaryHandleDict

lsst.pipe.tasks.multiBand.finalVisitSummaryHandleDict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`], optional

Definition at line 940 of file multiBand.py.

◆ initInputs

lsst.pipe.tasks.multiBand.initInputs : `dict`, optional

Definition at line 767 of file multiBand.py.

◆ parentCatalog

lsst.pipe.tasks.multiBand.parentCatalog : `lsst.afw.table.SourceCatalog`

Definition at line 924 of file multiBand.py.

◆ peakSchema

lsst.pipe.tasks.multiBand.peakSchema : ``lsst.afw.table.Schema`, optional

Definition at line 765 of file multiBand.py.

◆ results

lsst.pipe.tasks.multiBand.results : `lsst.pipe.base.Struct`

Definition at line 949 of file multiBand.py.

◆ schema

lsst.pipe.tasks.multiBand.schema : ``lsst.afw.table.Schema`, optional
doAddFootprints = Field(dtype=bool,
                        default=True,
                        doc="Whether or not to add footprints to the input catalog from scarlet models. "
                            "This should be true whenever using the multi-band deblender, "
                            "otherwise this should be False.")
doConserveFlux = Field(dtype=bool, default=True,
                       doc="Whether to use the deblender models as templates to re-distribute the flux "
                           "from the 'exposure' (True), or to perform measurements on the deblender "
                           "model footprints.")
doStripFootprints = Field(dtype=bool, default=True,
                          doc="Whether to strip footprints from the output catalog before "
                              "saving to disk. "
                              "This is usually done when using scarlet models to save disk space.")
useCellCoadds = Field(dtype=bool, default=False, doc="Whether to use cell coadds?")
measurement = ConfigurableField(target=SingleFrameMeasurementTask, doc="Source measurement")
setPrimaryFlags = ConfigurableField(target=SetPrimaryFlagsTask, doc="Set flags for primary tract/patch")
doPropagateFlags = Field(
    dtype=bool, default=True,
    doc="Whether to match sources to CCD catalogs to propagate flags (to e.g. identify PSF stars)"
)
propagateFlags = ConfigurableField(target=PropagateSourceFlagsTask, doc="Propagate source flags to coadd")
coaddName = Field(dtype=str, default="deep", doc="Name of coadd")
psfCache = Field(dtype=int, default=100, doc="Size of psfCache")
checkUnitsParseStrict = Field(
    doc="Strictness of Astropy unit compatibility check, can be 'raise', 'warn' or 'silent'",
    dtype=str,
    default="raise",
)
doApCorr = Field(
    dtype=bool,
    default=True,
    doc="Apply aperture corrections"
)
applyApCorr = ConfigurableField(
    target=ApplyApCorrTask,
    doc="Subtask to apply aperture corrections"
)
doRunCatalogCalculation = Field(
    dtype=bool,
    default=True,
    doc='Run catalogCalculation task'
)
catalogCalculation = ConfigurableField(
    target=CatalogCalculationTask,
    doc="Subtask to run catalogCalculation plugins on catalog"
)

hasFakes = Field(
    dtype=bool,
    default=False,
    doc="Should be set to True if fake sources have been inserted into the input data."
)
idGenerator = SkyMapIdGeneratorConfig.make_field()
imageType = ChoiceField(
    "Which image type to expect for the input coadd. "
    "This option only directly affects connection storage classes and hence 'runQuantum'; the 'run' "
    "method behavior is determined by which type is actually passed in.",
    allowed={
        "legacy": (
            "Read a lsst.cell_coadds.MultipleCellCoadd via 'exposure_cells` and restore 'background' "
            "(if useCellCoadd) or lsst.afw.image.Exposure via `exposure` (if not useCellCoadd)."
        ),
        "future": (
            "Read lsst.images.cells.CellCoadd via the 'exposure' connection.  useCellCoadd is ignored."
        ),
    },
    dtype=str,
    optional=False,
    default="legacy",
)

def setDefaults(self):
    super().setDefaults()
    self.measurement.plugins.names |= ['base_InputCount',
                                       'base_Variance',
                                       'base_LocalPhotoCalib',
                                       'base_LocalWcs']

    # TODO: Remove STREAK in DM-44658, streak masking to happen only in
    # ip_diffim; if we can propagate the streak mask from diffim, we can
    # still set flags with it here.
    self.measurement.plugins['base_PixelFlags'].masksFpAnywhere = ['CLIPPED', 'SENSOR_EDGE',
                                                                   'INEXACT_PSF']
    self.measurement.plugins['base_PixelFlags'].masksFpCenter = ['CLIPPED', 'SENSOR_EDGE',
                                                                 'INEXACT_PSF']


class MeasureMergedCoaddSourcesTask(PipelineTask):

Definition at line 763 of file multiBand.py.

◆ skyInfo

lsst.pipe.tasks.multiBand.skyInfo : `lsst.pipe.base.Struct`

Definition at line 926 of file multiBand.py.

◆ sources

lsst.pipe.tasks.multiBand.sources : `lsst.afw.table.SourceCatalog`

Definition at line 921 of file multiBand.py.

◆ sourceTableHandleDict

lsst.pipe.tasks.multiBand.sourceTableHandleDict : `dict` [`int`, `lsst.daf.butler.DeferredDatasetHandle`], optional

Definition at line 934 of file multiBand.py.

◆ useCellCoadd

lsst.pipe.tasks.multiBand.useCellCoadd

Definition at line 114 of file multiBand.py.