|
lsst.ip.diffim ga500d100eb+833bc1611b
|
Classes | |
| class | DetectAndMeasureConnections |
Variables | |
| expId : `int` | |
| expBits : `int` | |
| idFactory : `lsst.afw.table.IdFactory` | |
| science : `lsst.afw.image.ExposureF` | |
| matchedTemplate : `lsst.afw.image.ExposureF` | |
| difference : `lsst.afw.image.ExposureF` | |
| measurementResults : `lsst.pipe.base.Struct` | |
| sources : `lsst.afw.table.SourceCatalog` | |
| positiveFootprints : `lsst.afw.detection.FootprintSet`, optional | |
| negativeFootprints : `lsst.afw.detection.FootprintSet`, optional | |
| table : `lsst.afw.table.SourceTable` | |
| diaSources : `lsst.afw.table.SourceCatalog` | |
| mask : `lsst.afw.image.Mask` | |
| seed : `int` | |
| wcs : `lsst.afw.geom.SkyWcs` | |
| scoreExposure : `lsst.afw.image.ExposureF` | |
| lsst.ip.diffim.detectAndMeasure.diaSources : `lsst.afw.table.SourceCatalog` |
if self.config.doMerge:
fpSet = positiveFootprints
fpSet.merge(negativeFootprints, self.config.growFootprint,
self.config.growFootprint, False)
diaSources = afwTable.SourceCatalog(table)
fpSet.makeSources(diaSources)
self.log.info("Merging detections into %d sources", len(diaSources))
else:
diaSources = sources
if self.config.doSkySources:
self.addSkySources(diaSources, difference.mask, difference.info.id)
self.measureDiaSources(diaSources, science, difference, matchedTemplate)
if self.config.doForcedMeasurement:
self.measureForcedSources(diaSources, science, difference.getWcs())
measurementResults = pipeBase.Struct(
subtractedMeasuredExposure=difference,
diaSources=diaSources,
)
return measurementResults
def addSkySources(self, diaSources, mask, seed):
skySourceFootprints = self.skySources.run(mask=mask, seed=seed)
if skySourceFootprints:
for foot in skySourceFootprints:
s = diaSources.addNew()
s.setFootprint(foot)
s.set(self.skySourceKey, True)
def measureDiaSources(self, diaSources, science, difference, matchedTemplate):
# Note that this may not be correct if we convolved the science image.
# In the future we may wish to persist the matchedScience image.
self.measurement.run(diaSources, difference, science, matchedTemplate)
if self.config.doApCorr:
self.applyApCorr.run(
catalog=diaSources,
apCorrMap=difference.getInfo().getApCorrMap()
)
def measureForcedSources(self, diaSources, science, wcs):
Definition at line 374 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.difference : `lsst.afw.image.ExposureF` |
Definition at line 283 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.expBits : `int` |
Definition at line 239 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.expId : `int` |
doMerge = pexConfig.Field(
dtype=bool,
default=True,
doc="Merge positive and negative diaSources with grow radius "
"set by growFootprint"
)
doForcedMeasurement = pexConfig.Field(
dtype=bool,
default=True,
doc="Force photometer diaSource locations on PVI?")
doAddMetrics = pexConfig.Field(
dtype=bool,
default=False,
doc="Add columns to the source table to hold analysis metrics?"
)
detection = pexConfig.ConfigurableField(
target=SourceDetectionTask,
doc="Final source detection for diaSource measurement",
)
measurement = pexConfig.ConfigurableField(
target=DipoleFitTask,
doc="Task to measure sources on the difference image.",
)
doApCorr = lsst.pex.config.Field(
dtype=bool,
default=True,
doc="Run subtask to apply aperture corrections"
)
applyApCorr = lsst.pex.config.ConfigurableField(
target=ApplyApCorrTask,
doc="Task to apply aperture corrections"
)
forcedMeasurement = pexConfig.ConfigurableField(
target=ForcedMeasurementTask,
doc="Task to force photometer science image at diaSource locations.",
)
growFootprint = pexConfig.Field(
dtype=int,
default=2,
doc="Grow positive and negative footprints by this many pixels before merging"
)
diaSourceMatchRadius = pexConfig.Field(
dtype=float,
default=0.5,
doc="Match radius (in arcseconds) for DiaSource to Source association"
)
doSkySources = pexConfig.Field(
dtype=bool,
default=False,
doc="Generate sky sources?",
)
skySources = pexConfig.ConfigurableField(
target=SkyObjectsTask,
doc="Generate sky sources",
)
idGenerator = DetectorVisitIdGeneratorConfig.make_field()
def setDefaults(self):
# DiaSource Detection
self.detection.thresholdPolarity = "both"
self.detection.thresholdValue = 5.0
self.detection.reEstimateBackground = False
self.detection.thresholdType = "pixel_stdev"
self.detection.excludeMaskPlanes = ["EDGE"]
# Add filtered flux measurement, the correct measurement for pre-convolved images.
self.measurement.algorithms.names.add('base_PeakLikelihoodFlux')
self.measurement.plugins.names |= ['ext_trailedSources_Naive',
'base_LocalPhotoCalib',
'base_LocalWcs',
'ext_shapeHSM_HsmSourceMoments',
'ext_shapeHSM_HsmPsfMoments',
]
self.measurement.slots.psfShape = "ext_shapeHSM_HsmPsfMoments"
self.measurement.slots.shape = "ext_shapeHSM_HsmSourceMoments"
self.measurement.plugins["base_NaiveCentroid"].maxDistToPeak = 5.0
self.measurement.plugins["base_SdssCentroid"].maxDistToPeak = 5.0
self.forcedMeasurement.plugins = ["base_TransformedCentroid", "base_PsfFlux"]
self.forcedMeasurement.copyColumns = {
"id": "objectId", "parent": "parentObjectId", "coord_ra": "coord_ra", "coord_dec": "coord_dec"}
self.forcedMeasurement.slots.centroid = "base_TransformedCentroid"
self.forcedMeasurement.slots.shape = None
class DetectAndMeasureTask(lsst.pipe.base.PipelineTask):
ConfigClass = DetectAndMeasureConfig
_DefaultName = "detectAndMeasure"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.schema = afwTable.SourceTable.makeMinimalSchema()
self.algMetadata = dafBase.PropertyList()
self.makeSubtask("detection", schema=self.schema)
self.makeSubtask("measurement", schema=self.schema,
algMetadata=self.algMetadata)
if self.config.doApCorr:
self.makeSubtask("applyApCorr", schema=self.measurement.schema)
if self.config.doForcedMeasurement:
self.schema.addField(
"ip_diffim_forced_PsfFlux_instFlux", "D",
"Forced PSF flux measured on the direct image.",
units="count")
self.schema.addField(
"ip_diffim_forced_PsfFlux_instFluxErr", "D",
"Forced PSF flux error measured on the direct image.",
units="count")
self.schema.addField(
"ip_diffim_forced_PsfFlux_area", "F",
"Forced PSF flux effective area of PSF.",
units="pixel")
self.schema.addField(
"ip_diffim_forced_PsfFlux_flag", "Flag",
"Forced PSF flux general failure flag.")
self.schema.addField(
"ip_diffim_forced_PsfFlux_flag_noGoodPixels", "Flag",
"Forced PSF flux not enough non-rejected pixels in data to attempt the fit.")
self.schema.addField(
"ip_diffim_forced_PsfFlux_flag_edge", "Flag",
"Forced PSF flux object was too close to the edge of the image to use the full PSF model.")
self.makeSubtask("forcedMeasurement", refSchema=self.schema)
self.schema.addField("refMatchId", "L", "unique id of reference catalog match")
self.schema.addField("srcMatchId", "L", "unique id of source match")
if self.config.doSkySources:
self.makeSubtask("skySources")
self.skySourceKey = self.schema.addField("sky_source", type="Flag", doc="Sky objects.")
# initialize InitOutputs
self.outputSchema = afwTable.SourceCatalog(self.schema)
self.outputSchema.getTable().setMetadata(self.algMetadata)
@staticmethod
@deprecated(
reason=(
"ID factory construction now depends on configuration; use the "
"idGenerator config field. Will be removed after v27."
),
version="v26.0",
category=FutureWarning,
)
def makeIdFactory(expId, expBits):
Definition at line 236 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.idFactory : `lsst.afw.table.IdFactory` |
Definition at line 250 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.mask : `lsst.afw.image.Mask` |
Definition at line 376 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.matchedTemplate : `lsst.afw.image.ExposureF` |
Definition at line 280 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.measurementResults : `lsst.pipe.base.Struct` |
Definition at line 290 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.negativeFootprints : `lsst.afw.detection.FootprintSet`, optional |
Definition at line 322 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.positiveFootprints : `lsst.afw.detection.FootprintSet`, optional |
Definition at line 320 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.science : `lsst.afw.image.ExposureF` |
return ExposureIdInfo(expId, expBits).makeSourceIdFactory()
def runQuantum(self, butlerQC: pipeBase.ButlerQuantumContext,
inputRefs: pipeBase.InputQuantizedConnection,
outputRefs: pipeBase.OutputQuantizedConnection):
inputs = butlerQC.get(inputRefs)
idGenerator = self.config.idGenerator.apply(butlerQC.quantum.dataId)
idFactory = idGenerator.make_table_id_factory()
outputs = self.run(**inputs, idFactory=idFactory)
butlerQC.put(outputs, outputRefs)
@timeMethod
def run(self, science, matchedTemplate, difference,
idFactory=None):
# Run forced psf photometry on the PVI at the diaSource locations.
# Copy the measured flux and error into the diaSource.
forcedSources = self.forcedMeasurement.generateMeasCat(
science, diaSources, wcs)
self.forcedMeasurement.run(forcedSources, science, diaSources, wcs)
mapper = afwTable.SchemaMapper(forcedSources.schema, diaSources.schema)
mapper.addMapping(forcedSources.schema.find("base_PsfFlux_instFlux")[0],
"ip_diffim_forced_PsfFlux_instFlux", True)
mapper.addMapping(forcedSources.schema.find("base_PsfFlux_instFluxErr")[0],
"ip_diffim_forced_PsfFlux_instFluxErr", True)
mapper.addMapping(forcedSources.schema.find("base_PsfFlux_area")[0],
"ip_diffim_forced_PsfFlux_area", True)
mapper.addMapping(forcedSources.schema.find("base_PsfFlux_flag")[0],
"ip_diffim_forced_PsfFlux_flag", True)
mapper.addMapping(forcedSources.schema.find("base_PsfFlux_flag_noGoodPixels")[0],
"ip_diffim_forced_PsfFlux_flag_noGoodPixels", True)
mapper.addMapping(forcedSources.schema.find("base_PsfFlux_flag_edge")[0],
"ip_diffim_forced_PsfFlux_flag_edge", True)
for diaSource, forcedSource in zip(diaSources, forcedSources):
diaSource.assign(forcedSource, mapper)
class DetectAndMeasureScoreConnections(DetectAndMeasureConnections):
scoreExposure = pipeBase.connectionTypes.Input(
doc="Maximum likelihood image for detection.",
dimensions=("instrument", "visit", "detector"),
storageClass="ExposureF",
name="{fakesType}{coaddName}Diff_scoreExp",
)
class DetectAndMeasureScoreConfig(DetectAndMeasureConfig,
pipelineConnections=DetectAndMeasureScoreConnections):
pass
class DetectAndMeasureScoreTask(DetectAndMeasureTask):
ConfigClass = DetectAndMeasureScoreConfig
_DefaultName = "detectAndMeasureScore"
@timeMethod
def run(self, science, matchedTemplate, difference, scoreExposure,
idFactory=None):
Definition at line 278 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.scoreExposure : `lsst.afw.image.ExposureF` |
Definition at line 489 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.seed : `int` |
Definition at line 378 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.sources : `lsst.afw.table.SourceCatalog` |
# Ensure that we start with an empty detection mask.
mask = difference.mask
mask &= ~(mask.getPlaneBitMask("DETECTED") | mask.getPlaneBitMask("DETECTED_NEGATIVE"))
table = afwTable.SourceTable.make(self.schema, idFactory)
table.setMetadata(self.algMetadata)
results = self.detection.run(
table=table,
exposure=difference,
doSmooth=True,
)
return self.processResults(science, matchedTemplate, difference, results.sources, table,
positiveFootprints=results.positive, negativeFootprints=results.negative)
def processResults(self, science, matchedTemplate, difference, sources, table,
positiveFootprints=None, negativeFootprints=None,):
Definition at line 318 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.table : `lsst.afw.table.SourceTable` |
Definition at line 324 of file detectAndMeasure.py.
| lsst.ip.diffim.detectAndMeasure.wcs : `lsst.afw.geom.SkyWcs` |
Definition at line 421 of file detectAndMeasure.py.