doScaleVariance = Field(dtype=bool, default=True, doc="Scale variance plane using empirical noise?")
scaleVariance = ConfigurableField(target=ScaleVarianceTask, doc="Variance rescaling")
detection = ConfigurableField(target=DynamicDetectionTask, doc="Source detection")
coaddName = Field(dtype=str, default="deep", doc="Name of coadd")
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()
def setDefaults(self):
super().setDefaults()
self.detection.thresholdType = "pixel_stdev"
self.detection.isotropicGrow = True
# Coadds are made from background-subtracted CCDs, so any background subtraction should be very basic
self.detection.reEstimateBackground = False
self.detection.background.useApprox = False
self.detection.background.binSize = 4096
self.detection.background.undersampleStyle = 'REDUCE_INTERP_ORDER'
self.detection.doTempWideBackground = True # Suppress large footprints that overwhelm the deblender
# Include band in packed data IDs that go into object IDs (None -> "as
# many bands as are defined", rather than the default of zero).
self.idGenerator.packer.n_bands = None
class DetectCoaddSourcesTask(PipelineTask):
if self.config.doScaleVariance:
varScale = self.scaleVariance.run(exposure.maskedImage)
exposure.getMetadata().add("VARIANCE_SCALE", varScale)
backgrounds = afwMath.BackgroundList()
table = afwTable.SourceTable.make(self.schema, idFactory)
detections = self.detection.run(table, exposure, expId=expId)
sources = detections.sources
if hasattr(detections, "background") and detections.background:
for bg in detections.background:
backgrounds.append(bg)
return Struct(outputSources=sources, outputBackgrounds=backgrounds, outputExposure=exposure)
class MeasureMergedCoaddSourcesConnections(
PipelineTaskConnections,
dimensions=("tract", "patch", "band", "skymap"),
defaultTemplates={
"inputCoaddName": "deep",
"outputCoaddName": "deep",
"deblendedCatalog": "deblendedFlux",
},
deprecatedTemplates={
# TODO[DM-47797]: remove this deprecated connection template.
"deblendedCatalog": "Support for old deblender outputs will be removed after v29."
},
):
inputSchema = cT.InitInput(
doc="Input schema for measure merged task produced by a deblender or detection task",
name="{inputCoaddName}Coadd_deblendedFlux_schema",
storageClass="SourceCatalog"
)
outputSchema = cT.InitOutput(
doc="Output schema after all new fields are added by task",
name="{inputCoaddName}Coadd_meas_schema",
storageClass="SourceCatalog"
)
# TODO[DM-47797]: remove this deprecated connection.
refCat = cT.PrerequisiteInput(
doc="Reference catalog used to match measured sources against known sources",
name="ref_cat",
storageClass="SimpleCatalog",
dimensions=("skypix",),
deferLoad=True,
multiple=True,
deprecated="Reference matching in measureCoaddSources will be removed after v29.",
)
exposure = cT.Input(
doc="Input coadd image",
name="{inputCoaddName}Coadd_calexp",
storageClass="ExposureF",
dimensions=("tract", "patch", "band", "skymap")
)
skyMap = cT.Input(
doc="SkyMap to use in processing",
name=BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
storageClass="SkyMap",
dimensions=("skymap",),
)
# TODO[DM-47424]: remove this deprecated connection.
visitCatalogs = cT.Input(
doc="Deprecated and unused.",
name="src",
dimensions=("instrument", "visit", "detector"),
storageClass="SourceCatalog",
multiple=True,
deprecated="Deprecated and unused. Will be removed after v29.",
)
sourceTableHandles = cT.Input(
doc=("Source tables that are derived from the ``CalibrateTask`` sources. "
"These tables contain astrometry and photometry flags, and optionally "
"PSF flags."),
name="sourceTable_visit",
storageClass="DataFrame",
dimensions=("instrument", "visit"),
multiple=True,
deferLoad=True,
)
finalizedSourceTableHandles = cT.Input(
doc=("Finalized source tables from ``FinalizeCalibrationTask``. These "
"tables contain PSF flags from the finalized PSF estimation."),
name="finalized_src_table",
storageClass="DataFrame",
dimensions=("instrument", "visit"),
multiple=True,
deferLoad=True,
)
# TODO[DM-47797]: remove this deprecated connection.
inputCatalog = cT.Input(
doc=("Name of the input catalog to use."
"If the single band deblender was used this should be 'deblendedFlux."
"If the multi-band deblender was used this should be 'deblendedModel, "
"or deblendedFlux if the multiband deblender was configured to output "
"deblended flux catalogs. If no deblending was performed this should "
"be 'mergeDet'"),
name="{inputCoaddName}Coadd_{deblendedCatalog}",
storageClass="SourceCatalog",
deprecated="Support for old deblender outputs will be removed after v29.",
dimensions=("tract", "patch", "band", "skymap"),
)
scarletCatalog = cT.Input(
doc="Catalogs produced by multiband deblending",
name="{inputCoaddName}Coadd_deblendedCatalog",
storageClass="SourceCatalog",
dimensions=("tract", "patch", "skymap"),
)
scarletModels = cT.Input(
doc="Multiband scarlet models produced by the deblender",
name="{inputCoaddName}Coadd_scarletModelData",
storageClass="ScarletModelData",
dimensions=("tract", "patch", "skymap"),
)
outputSources = cT.Output(
doc="Source catalog containing all the measurement information generated in this task",
name="{outputCoaddName}Coadd_meas",
dimensions=("tract", "patch", "band", "skymap"),
storageClass="SourceCatalog",
)
# TODO[DM-47797]: remove this deprecated connection.
matchResult = cT.Output(
doc="Match catalog produced by configured matcher, optional on doMatchSources",
name="{outputCoaddName}Coadd_measMatch",
dimensions=("tract", "patch", "band", "skymap"),
storageClass="Catalog",
deprecated="Reference matching in measureCoaddSources will be removed after v29.",
)
# TODO[DM-47797]: remove this deprecated connection.
denormMatches = cT.Output(
doc="Denormalized Match catalog produced by configured matcher, optional on "
"doWriteMatchesDenormalized",
name="{outputCoaddName}Coadd_measMatchFull",
dimensions=("tract", "patch", "band", "skymap"),
storageClass="Catalog",
deprecated="Reference matching in measureCoaddSources will be removed after v29.",
)
def __init__(self, *, config=None):
super().__init__(config=config)
del self.visitCatalogs
if not config.doPropagateFlags:
del self.sourceTableHandles
del self.finalizedSourceTableHandles
else:
# Check for types of flags required.
if not config.propagateFlags.source_flags:
del self.sourceTableHandles
if not config.propagateFlags.finalized_source_flags:
del self.finalizedSourceTableHandles
# TODO[DM-47797]: only the 'if' block contents here should survive.
if config.inputCatalog == "deblendedCatalog":
del self.inputCatalog
if not config.doAddFootprints:
del self.scarletModels
else:
del self.deblendedCatalog
del self.scarletModels
# TODO[DM-47797]: delete the conditionals below.
if not config.doMatchSources:
del self.refCat
del self.matchResult
if not config.doWriteMatchesDenormalized:
del self.denormMatches
class MeasureMergedCoaddSourcesConfig(PipelineTaskConfig,
pipelineConnections=MeasureMergedCoaddSourcesConnections):
inputCatalog = ChoiceField(
dtype=str,
default="deblendedCatalog",
allowed={
"deblendedCatalog": "Output catalog from ScarletDeblendTask",
"deblendedFlux": "Output catalog from SourceDeblendTask",
"mergeDet": "The merged detections before deblending."
},
doc="The name of the input catalog.",
# TODO[DM-47797]: remove this config option and anything using it.
deprecated="Support for old deblender outputs will be removed after v29.",
)
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.")
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")
doMatchSources = Field(
dtype=bool,
default=False,
doc="Match sources to reference catalog?",
deprecated="Reference matching in measureCoaddSources will be removed after v29.",
)
match = ConfigurableField(
target=DirectMatchTask,
doc="Matching to reference catalog",
deprecated="Reference matching in measureCoaddSources will be removed after v29.",
)
doWriteMatchesDenormalized = Field(
dtype=bool,
default=False,
doc=("Write reference matches in denormalized format? "
"This format uses more disk space, but is more convenient to read."),
deprecated="Reference matching in measureCoaddSources will be removed after v29.",
)
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()
@property
def refObjLoader(self):
return self.match.refObjLoader
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']
def validate(self):
super().validate()
if not self.doMatchSources and self.doWriteMatchesDenormalized:
raise ValueError("Cannot set doWriteMatchesDenormalized if doMatchSources is False.")
class MeasureMergedCoaddSourcesTask(PipelineTask):
Definition at line 153 of file multiBand.py.