LSST Applications g044012fb7c+6976b5ec80,g04a91732dc+88a5fc122b,g07dc498a13+7e3c5f68a2,g114c6a66ad+09472d7a76,g1409bbee79+7e3c5f68a2,g1a7e361dbc+7e3c5f68a2,g1fd858c14a+3a43eabc0e,g35bb328faa+fcb1d3bbc8,g3bd4b5ce2c+2647bb081c,g4e0f332c67+5d362be553,g53246c7159+fcb1d3bbc8,g5477a8d5ce+b19c77c7ae,g58d0cdf3ff+4a2e102ff8,g60b5630c4e+09472d7a76,g623d845a50+09472d7a76,g6f0c2978f1+fcf1c0bcd6,g71fabbc107+09472d7a76,g75b6c65c88+d0b1dc44cc,g78460c75b0+2f9a1b4bcd,g786e29fd12+cf7ec2a62a,g7b71ed6315+fcb1d3bbc8,g8852436030+349c7e81d4,g89139ef638+7e3c5f68a2,g9125e01d80+fcb1d3bbc8,g95236ca021+f7a31438ed,g989de1cb63+7e3c5f68a2,g9f33ca652e+f17d666fbc,gaaedd4e678+7e3c5f68a2,gabe3b4be73+1e0a283bba,gb1101e3267+f870f33517,gb58c049af0+f03b321e39,gc99c83e5f0+76d20ab76d,gcf25f946ba+349c7e81d4,gd0fa69b896+f3a65fa83c,gd6cbbdb0b4+c8606af20c,gde0f65d7ad+5bd27d919f,ge278dab8ac+932305ba37,gfba249425e+fcb1d3bbc8,w.2025.07
LSST Data Management Base Package
Loading...
Searching...
No Matches
lsst.meas.base.forcedMeasurement.ForcedMeasurementTask Class Reference
Inheritance diagram for lsst.meas.base.forcedMeasurement.ForcedMeasurementTask:
lsst.meas.base.baseMeasurement.BaseMeasurementTask

Public Member Functions

 __init__ (self, refSchema, algMetadata=None, **kwds)
 
 run (self, measCat, exposure, refCat, refWcs, exposureId=None, beginOrder=None, endOrder=None)
 
 generateMeasCat (self, exposure, refCat, refWcs, idFactory=None)
 
 attachTransformedFootprints (self, sources, refCat, exposure, refWcs)
 
 attachPsfShapeFootprints (self, sources, exposure, scaling=3)
 
 initializePlugins (self, **kwds)
 
 callMeasure (self, measRecord, *args, **kwds)
 
 doMeasurement (self, plugin, measRecord, *args, **kwds)
 
 callMeasureN (self, measCat, *args, **kwds)
 
 doMeasurementN (self, plugin, measCat, *args, **kwds)
 

Static Public Member Functions

 getFootprintsFromCatalog (catalog)
 

Public Attributes

 mapper = lsst.afw.table.SchemaMapper(refSchema)
 
 schema = self.mapper.getOutputSchema()
 
 undeblendedPlugins = PluginMap()
 
 keyInvalidPsf = schema.find(invalidPsfName).key
 

Static Public Attributes

 ConfigClass = BaseMeasurementConfig
 
 plugins = None
 
 algMetadata = None
 

Static Protected Attributes

str _DefaultName = "measurement"
 

Detailed Description

Measure sources on an image, constrained by a reference catalog.

A subtask for measuring the properties of sources on a single image,
using an existing "reference" catalog to constrain some aspects of the
measurement.

Parameters
----------
refSchema : `lsst.afw.table.Schema`
    Schema of the reference catalog.  Must match the catalog later passed
    to 'ForcedMeasurementTask.generateMeasCat` and/or
    `ForcedMeasurementTask.run`.
algMetadata : `lsst.daf.base.PropertyList` or `None`
    Will be updated in place to to record information about each
    algorithm. An empty `~lsst.daf.base.PropertyList` will be created if
    `None`.
**kwds
    Keyword arguments are passed to the supertask constructor.

Notes
-----
Note that while `SingleFrameMeasurementTask` is passed an initial
`~lsst.afw.table.Schema` that is appended to in order to create the output
`~lsst.afw.table.Schema`, `ForcedMeasurementTask` is initialized with the
`~lsst.afw.table.Schema` of the reference catalog, from which a new
`~lsst.afw.table.Schema` for the output catalog is created.  Fields to be
copied directly from the reference `~lsst.afw.table.Schema` are added
before ``Plugin`` fields are added.

Definition at line 215 of file forcedMeasurement.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.__init__ ( self,
refSchema,
algMetadata = None,
** kwds )

Definition at line 248 of file forcedMeasurement.py.

248 def __init__(self, refSchema, algMetadata=None, **kwds):
249 super(ForcedMeasurementTask, self).__init__(algMetadata=algMetadata, **kwds)
250 self.mapper = lsst.afw.table.SchemaMapper(refSchema)
251 self.mapper.addMinimalSchema(lsst.afw.table.SourceTable.makeMinimalSchema(), False)
252 self.config.slots.setupSchema(self.mapper.editOutputSchema())
253 for refName, targetName in self.config.copyColumns.items():
254 refItem = refSchema.find(refName)
255 self.mapper.addMapping(refItem.key, targetName)
256 self.config.slots.setupSchema(self.mapper.editOutputSchema())
257 self.initializePlugins(schemaMapper=self.mapper)
258 self.schema = self.mapper.getOutputSchema()
259 self.schema.checkUnits(parse_strict=self.config.checkUnitsParseStrict)
260
A mapping between the keys of two Schemas, used to copy data between them.
static Schema makeMinimalSchema()
Return a minimal schema for Source tables and records.
Definition Source.h:258

Member Function Documentation

◆ attachPsfShapeFootprints()

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.attachPsfShapeFootprints ( self,
sources,
exposure,
scaling = 3 )
Attach Footprints to blank sources prior to measurement, by
creating elliptical Footprints from the PSF moments.

Parameters
----------
sources : `lsst.afw.table.SourceCatalog`
    Blank catalog (with all rows and columns, but values other than
    ``coord_ra``, ``coord_dec`` unpopulated).
    to which footprints should be attached.
exposure : `lsst.afw.image.Exposure`
    Image object from which peak values and the PSF are obtained.
scaling : `int`, optional
    Scaling factor to apply to the PSF second-moments ellipse in order
    to determine the footprint boundary.

Notes
-----
This is a utility function for use by parent tasks; see
`attachTransformedFootprints` for more information.

Definition at line 457 of file forcedMeasurement.py.

457 def attachPsfShapeFootprints(self, sources, exposure, scaling=3):
458 """Attach Footprints to blank sources prior to measurement, by
459 creating elliptical Footprints from the PSF moments.
460
461 Parameters
462 ----------
463 sources : `lsst.afw.table.SourceCatalog`
464 Blank catalog (with all rows and columns, but values other than
465 ``coord_ra``, ``coord_dec`` unpopulated).
466 to which footprints should be attached.
467 exposure : `lsst.afw.image.Exposure`
468 Image object from which peak values and the PSF are obtained.
469 scaling : `int`, optional
470 Scaling factor to apply to the PSF second-moments ellipse in order
471 to determine the footprint boundary.
472
473 Notes
474 -----
475 This is a utility function for use by parent tasks; see
476 `attachTransformedFootprints` for more information.
477 """
478 psf = exposure.getPsf()
479 if psf is None:
480 raise RuntimeError("Cannot construct Footprints from PSF shape without a PSF.")
481 bbox = exposure.getBBox()
482 wcs = exposure.getWcs()
483 for record in sources:
484 localPoint = wcs.skyToPixel(record.getCoord())
485 localIntPoint = lsst.geom.Point2I(localPoint)
486 assert bbox.contains(localIntPoint), (
487 f"Center for record {record.getId()} is not in exposure; this should be guaranteed by "
488 "generateMeasCat."
489 )
490 ellipse = lsst.afw.geom.ellipses.Ellipse(psf.computeShape(localPoint), localPoint)
491 ellipse.getCore().scale(scaling)
492 spans = lsst.afw.geom.SpanSet.fromShape(ellipse)
493 footprint = lsst.afw.detection.Footprint(spans.clippedTo(bbox), bbox)
494 footprint.addPeak(localIntPoint.getX(), localIntPoint.getY(),
495 exposure.image._get(localIntPoint, lsst.afw.image.PARENT))
496 record.setFootprint(footprint)
Class to describe the properties of a detected object from an image.
Definition Footprint.h:63
static std::shared_ptr< geom::SpanSet > fromShape(int r, Stencil s=Stencil::CIRCLE, lsst::geom::Point2I offset=lsst::geom::Point2I())
Factory function for creating SpanSets from a Stencil.
Definition SpanSet.cc:688
An ellipse defined by an arbitrary BaseCore and a center point.
Definition Ellipse.h:51

◆ attachTransformedFootprints()

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.attachTransformedFootprints ( self,
sources,
refCat,
exposure,
refWcs )
Attach Footprints to blank sources prior to measurement, by
transforming Footprints attached to the reference catalog.

Notes
-----
`~lsst.afw.detection.Footprint`\s for forced photometry must be in the
pixel coordinate system of the image being measured, while the actual
detections may start out in a different coordinate system. This
default implementation transforms the Footprints from the reference
catalog from the WCS to the exposure's WCS, which downgrades
``HeavyFootprint``\s into regular `~lsst.afw.detection.Footprint`\s,
destroying deblend information.

See the documentation for `run` for information about the
relationships between `run`, `generateMeasCat`, and
`attachTransformedFootprints`.

Definition at line 434 of file forcedMeasurement.py.

434 def attachTransformedFootprints(self, sources, refCat, exposure, refWcs):
435 r"""Attach Footprints to blank sources prior to measurement, by
436 transforming Footprints attached to the reference catalog.
437
438 Notes
439 -----
440 `~lsst.afw.detection.Footprint`\s for forced photometry must be in the
441 pixel coordinate system of the image being measured, while the actual
442 detections may start out in a different coordinate system. This
443 default implementation transforms the Footprints from the reference
444 catalog from the WCS to the exposure's WCS, which downgrades
445 ``HeavyFootprint``\s into regular `~lsst.afw.detection.Footprint`\s,
446 destroying deblend information.
447
448 See the documentation for `run` for information about the
449 relationships between `run`, `generateMeasCat`, and
450 `attachTransformedFootprints`.
451 """
452 exposureWcs = exposure.getWcs()
453 region = exposure.getBBox(lsst.afw.image.PARENT)
454 for srcRecord, refRecord in zip(sources, refCat):
455 srcRecord.setFootprint(refRecord.getFootprint().transform(refWcs, exposureWcs, region))
456

◆ callMeasure()

lsst.meas.base.baseMeasurement.BaseMeasurementTask.callMeasure ( self,
measRecord,
* args,
** kwds )
inherited
Call ``measure`` on all plugins and consistently handle exceptions.

Parameters
----------
measRecord : `lsst.afw.table.SourceRecord`
    The record corresponding to the object being measured. Will be
    updated in-place with the results of measurement.
*args
    Positional arguments forwarded to ``plugin.measure``
**kwds
    Keyword arguments. Two are handled locally:

    beginOrder : `int`
        Beginning execution order (inclusive). Measurements with
        ``executionOrder`` < ``beginOrder`` are not executed. `None`
        for no limit.

    endOrder : `int`
        Ending execution order (exclusive). Measurements with
        ``executionOrder`` >= ``endOrder`` are not executed. `None`
        for no limit.

    Others are forwarded to ``plugin.measure()``.

Notes
-----
This method can be used with plugins that have different signatures;
the only requirement is that ``measRecord`` be the first argument.
Subsequent positional arguments and keyword arguments are forwarded
directly to the plugin.

This method should be considered "protected": it is intended for use by
derived classes, not users.

Definition at line 344 of file baseMeasurement.py.

344 def callMeasure(self, measRecord, *args, **kwds):
345 """Call ``measure`` on all plugins and consistently handle exceptions.
346
347 Parameters
348 ----------
349 measRecord : `lsst.afw.table.SourceRecord`
350 The record corresponding to the object being measured. Will be
351 updated in-place with the results of measurement.
352 *args
353 Positional arguments forwarded to ``plugin.measure``
354 **kwds
355 Keyword arguments. Two are handled locally:
356
357 beginOrder : `int`
358 Beginning execution order (inclusive). Measurements with
359 ``executionOrder`` < ``beginOrder`` are not executed. `None`
360 for no limit.
361
362 endOrder : `int`
363 Ending execution order (exclusive). Measurements with
364 ``executionOrder`` >= ``endOrder`` are not executed. `None`
365 for no limit.
366
367 Others are forwarded to ``plugin.measure()``.
368
369 Notes
370 -----
371 This method can be used with plugins that have different signatures;
372 the only requirement is that ``measRecord`` be the first argument.
373 Subsequent positional arguments and keyword arguments are forwarded
374 directly to the plugin.
375
376 This method should be considered "protected": it is intended for use by
377 derived classes, not users.
378 """
379 beginOrder = kwds.pop("beginOrder", None)
380 endOrder = kwds.pop("endOrder", None)
381 for plugin in self.plugins.iter():
382 if beginOrder is not None and plugin.getExecutionOrder() < beginOrder:
383 continue
384 if endOrder is not None and plugin.getExecutionOrder() >= endOrder:
385 break
386 self.doMeasurement(plugin, measRecord, *args, **kwds)
387

◆ callMeasureN()

lsst.meas.base.baseMeasurement.BaseMeasurementTask.callMeasureN ( self,
measCat,
* args,
** kwds )
inherited
Call ``measureN`` on all plugins and consistently handle exceptions.

Parameters
----------
measCat : `lsst.afw.table.SourceCatalog`
    Catalog containing only the records for the source family to be
    measured, and where outputs should be written.
*args
    Positional arguments forwarded to ``plugin.measure()``
**kwds
    Keyword arguments. Two are handled locally:

    beginOrder:
        Beginning execution order (inclusive): Measurements with
        ``executionOrder`` < ``beginOrder`` are not executed. `None`
        for no limit.
    endOrder:
        Ending execution order (exclusive): measurements with
        ``executionOrder`` >= ``endOrder`` are not executed. `None` for
        no ``limit``.

    Others are are forwarded to ``plugin.measure()``.

Notes
-----
This method can be used with plugins that have different signatures;
the only requirement is that ``measRecord`` be the first argument.
Subsequent positional arguments and keyword arguments are forwarded
directly to the plugin.

This method should be considered "protected": it is intended for use by
derived classes, not users.

Definition at line 436 of file baseMeasurement.py.

436 def callMeasureN(self, measCat, *args, **kwds):
437 """Call ``measureN`` on all plugins and consistently handle exceptions.
438
439 Parameters
440 ----------
441 measCat : `lsst.afw.table.SourceCatalog`
442 Catalog containing only the records for the source family to be
443 measured, and where outputs should be written.
444 *args
445 Positional arguments forwarded to ``plugin.measure()``
446 **kwds
447 Keyword arguments. Two are handled locally:
448
449 beginOrder:
450 Beginning execution order (inclusive): Measurements with
451 ``executionOrder`` < ``beginOrder`` are not executed. `None`
452 for no limit.
453 endOrder:
454 Ending execution order (exclusive): measurements with
455 ``executionOrder`` >= ``endOrder`` are not executed. `None` for
456 no ``limit``.
457
458 Others are are forwarded to ``plugin.measure()``.
459
460 Notes
461 -----
462 This method can be used with plugins that have different signatures;
463 the only requirement is that ``measRecord`` be the first argument.
464 Subsequent positional arguments and keyword arguments are forwarded
465 directly to the plugin.
466
467 This method should be considered "protected": it is intended for use by
468 derived classes, not users.
469 """
470 beginOrder = kwds.pop("beginOrder", None)
471 endOrder = kwds.pop("endOrder", None)
472 for plugin in self.plugins.iterN():
473 if beginOrder is not None and plugin.getExecutionOrder() < beginOrder:
474 continue
475 if endOrder is not None and plugin.getExecutionOrder() >= endOrder:
476 break
477 self.doMeasurementN(plugin, measCat, *args, **kwds)
478

◆ doMeasurement()

lsst.meas.base.baseMeasurement.BaseMeasurementTask.doMeasurement ( self,
plugin,
measRecord,
* args,
** kwds )
inherited
Call ``measure`` on the specified plugin.

Exceptions are handled in a consistent way.

Parameters
----------
plugin : subclass of `BasePlugin`
    Plugin that will be executed.
measRecord : `lsst.afw.table.SourceRecord`
    The record corresponding to the object being measured. Will be
    updated in-place with the results of measurement.
*args
    Positional arguments forwarded to ``plugin.measure()``.
**kwds
    Keyword arguments forwarded to ``plugin.measure()``.

Notes
-----
This method can be used with plugins that have different signatures;
the only requirement is that ``plugin`` and ``measRecord`` be the first
two arguments.  Subsequent positional arguments and keyword arguments
are forwarded directly to the plugin.

This method should be considered "protected": it is intended for use by
derived classes, not users.

Definition at line 388 of file baseMeasurement.py.

388 def doMeasurement(self, plugin, measRecord, *args, **kwds):
389 """Call ``measure`` on the specified plugin.
390
391 Exceptions are handled in a consistent way.
392
393 Parameters
394 ----------
395 plugin : subclass of `BasePlugin`
396 Plugin that will be executed.
397 measRecord : `lsst.afw.table.SourceRecord`
398 The record corresponding to the object being measured. Will be
399 updated in-place with the results of measurement.
400 *args
401 Positional arguments forwarded to ``plugin.measure()``.
402 **kwds
403 Keyword arguments forwarded to ``plugin.measure()``.
404
405 Notes
406 -----
407 This method can be used with plugins that have different signatures;
408 the only requirement is that ``plugin`` and ``measRecord`` be the first
409 two arguments. Subsequent positional arguments and keyword arguments
410 are forwarded directly to the plugin.
411
412 This method should be considered "protected": it is intended for use by
413 derived classes, not users.
414 """
415 try:
416 plugin.measure(measRecord, *args, **kwds)
417 except FATAL_EXCEPTIONS:
418 raise
419 except MeasurementError as error:
420 self.log.getChild(plugin.name).debug(
421 "MeasurementError in %s.measure on record %s: %s",
422 plugin.name, measRecord.getId(), error)
423 plugin.fail(measRecord, error)
424 except InvalidPsfError as error:
425 self.log.getChild(plugin.name).debug(
426 "InvalidPsfError in %s.measure on record %s: %s",
427 plugin.name, measRecord.getId(), error)
428 measRecord.set(self.keyInvalidPsf, True)
429 plugin.fail(measRecord)
430 except Exception as error:
431 self.log.getChild(plugin.name).warning(
432 "Exception in %s.measure on record %s: %s",
433 plugin.name, measRecord.getId(), error)
434 plugin.fail(measRecord)
435

◆ doMeasurementN()

lsst.meas.base.baseMeasurement.BaseMeasurementTask.doMeasurementN ( self,
plugin,
measCat,
* args,
** kwds )
inherited
Call ``measureN`` on the specified plugin.

Exceptions are handled in a consistent way.

Parameters
----------
plugin : subclass of `BasePlugin`
    Plugin that will be executed.
measCat : `lsst.afw.table.SourceCatalog`
    Catalog containing only the records for the source family to be
    measured, and where outputs should be written.
*args
    Positional arguments forwarded to ``plugin.measureN()``.
**kwds
    Keyword arguments forwarded to ``plugin.measureN()``.

Notes
-----
This method can be used with plugins that have different signatures;
the only requirement is that the ``plugin`` and ``measCat`` be the
first two arguments. Subsequent positional arguments and keyword
arguments are forwarded directly to the plugin.

This method should be considered "protected": it is intended for use by
derived classes, not users.

Definition at line 479 of file baseMeasurement.py.

479 def doMeasurementN(self, plugin, measCat, *args, **kwds):
480 """Call ``measureN`` on the specified plugin.
481
482 Exceptions are handled in a consistent way.
483
484 Parameters
485 ----------
486 plugin : subclass of `BasePlugin`
487 Plugin that will be executed.
488 measCat : `lsst.afw.table.SourceCatalog`
489 Catalog containing only the records for the source family to be
490 measured, and where outputs should be written.
491 *args
492 Positional arguments forwarded to ``plugin.measureN()``.
493 **kwds
494 Keyword arguments forwarded to ``plugin.measureN()``.
495
496 Notes
497 -----
498 This method can be used with plugins that have different signatures;
499 the only requirement is that the ``plugin`` and ``measCat`` be the
500 first two arguments. Subsequent positional arguments and keyword
501 arguments are forwarded directly to the plugin.
502
503 This method should be considered "protected": it is intended for use by
504 derived classes, not users.
505 """
506 try:
507 plugin.measureN(measCat, *args, **kwds)
508 except FATAL_EXCEPTIONS:
509 raise
510
511 except MeasurementError as error:
512 self.log.getChild(plugin.name).debug(
513 "MeasurementError in %s.measureN on records %s-%s: %s",
514 plugin.name, measCat[0].getId(), measCat[-1].getId(), error)
515 for measRecord in measCat:
516 plugin.fail(measRecord, error)
517 except InvalidPsfError as error:
518 self.log.getChild(plugin.name).debug(
519 "InvalidPsfError in %s.measureN on records %s-%s: %s",
520 plugin.name, measCat[0].getId(), measCat[-1].getId(), error)
521 for measRecord in measCat:
522 measRecord.set(self.keyInvalidPsf, True)
523 plugin.fail(measRecord, error)
524 except Exception as error:
525 self.log.getChild(plugin.name).warning(
526 "Exception in %s.measureN on records %s-%s: %s",
527 plugin.name, measCat[0].getId(), measCat[-1].getId(), error)
528 for measRecord in measCat:
529 plugin.fail(measRecord)
530

◆ generateMeasCat()

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.generateMeasCat ( self,
exposure,
refCat,
refWcs,
idFactory = None )
Initialize an output catalog from the reference catalog.

Parameters
----------
exposure : `lsst.afw.image.exposureF`
    Image to be measured.
refCat : iterable of `lsst.afw.table.SourceRecord`
    Catalog of reference sources.
refWcs : `lsst.afw.geom.SkyWcs`
    Defines the X,Y coordinate system of ``refCat``.
    This parameter is not currently used.
idFactory : `lsst.afw.table.IdFactory`, optional
    Factory for creating IDs for sources.

Returns
-------
meascat : `lsst.afw.table.SourceCatalog`
    Source catalog ready for measurement.

Notes
-----
This generates a new blank `~lsst.afw.table.SourceRecord` for each
record in ``refCat``. Note that this method does not attach any
`~lsst.afw.detection.Footprint`\ s.  Doing so is up to the caller (who
may call `attachedTransformedFootprints` or define their own method -
see `run` for more information).

Definition at line 394 of file forcedMeasurement.py.

394 def generateMeasCat(self, exposure, refCat, refWcs, idFactory=None):
395 r"""Initialize an output catalog from the reference catalog.
396
397 Parameters
398 ----------
399 exposure : `lsst.afw.image.exposureF`
400 Image to be measured.
401 refCat : iterable of `lsst.afw.table.SourceRecord`
402 Catalog of reference sources.
403 refWcs : `lsst.afw.geom.SkyWcs`
404 Defines the X,Y coordinate system of ``refCat``.
405 This parameter is not currently used.
406 idFactory : `lsst.afw.table.IdFactory`, optional
407 Factory for creating IDs for sources.
408
409 Returns
410 -------
411 meascat : `lsst.afw.table.SourceCatalog`
412 Source catalog ready for measurement.
413
414 Notes
415 -----
416 This generates a new blank `~lsst.afw.table.SourceRecord` for each
417 record in ``refCat``. Note that this method does not attach any
418 `~lsst.afw.detection.Footprint`\ s. Doing so is up to the caller (who
419 may call `attachedTransformedFootprints` or define their own method -
420 see `run` for more information).
421 """
422 if idFactory is None:
424 table = lsst.afw.table.SourceTable.make(self.schema, idFactory)
425 measCat = lsst.afw.table.SourceCatalog(table)
426 table = measCat.table
427 table.setMetadata(self.algMetadata)
428 table.preallocate(len(refCat))
429 for ref in refCat:
430 newSource = measCat.addNew()
431 newSource.assign(ref, self.mapper)
432 return measCat
433
static std::shared_ptr< IdFactory > makeSimple()
Return a simple IdFactory that simply counts from 1.
Definition IdFactory.cc:70
static std::shared_ptr< SourceTable > make(Schema const &schema, std::shared_ptr< IdFactory > const &idFactory)
Construct a new table.
Definition Source.cc:400

◆ getFootprintsFromCatalog()

lsst.meas.base.baseMeasurement.BaseMeasurementTask.getFootprintsFromCatalog ( catalog)
staticinherited
Get a set of footprints from a catalog, keyed by id.

Parameters
----------
catalog : `lsst.afw.table.SourceCatalog`
    Catalog with `lsst.afw.detection.Footprint`s attached.

Returns
-------
footprints : `dict` [`int`: (`int`, `lsst.afw.detection.Footprint`)]
    Dictionary of footprint, keyed by id number, with a tuple of
    the parent id and footprint.

Definition at line 532 of file baseMeasurement.py.

532 def getFootprintsFromCatalog(catalog):
533 """Get a set of footprints from a catalog, keyed by id.
534
535 Parameters
536 ----------
537 catalog : `lsst.afw.table.SourceCatalog`
538 Catalog with `lsst.afw.detection.Footprint`s attached.
539
540 Returns
541 -------
542 footprints : `dict` [`int`: (`int`, `lsst.afw.detection.Footprint`)]
543 Dictionary of footprint, keyed by id number, with a tuple of
544 the parent id and footprint.
545 """
546 return {measRecord.getId(): (measRecord.getParent(), measRecord.getFootprint())
547 for measRecord in catalog}

◆ initializePlugins()

lsst.meas.base.baseMeasurement.BaseMeasurementTask.initializePlugins ( self,
** kwds )
inherited
Initialize plugins (and slots) according to configuration.

Parameters
----------
**kwds
    Keyword arguments forwarded directly to plugin constructors.

Notes
-----
Derived class constructors should call this method to fill the
`plugins` attribute and add corresponding output fields and slot
aliases to the output schema.

In addition to the attributes added by `BaseMeasurementTask.__init__`,
a ``schema``` attribute holding the output schema must be present
before this method is called.

Keyword arguments are forwarded directly to plugin constructors,
allowing derived classes to use plugins with different signatures.

Definition at line 274 of file baseMeasurement.py.

274 def initializePlugins(self, **kwds):
275 """Initialize plugins (and slots) according to configuration.
276
277 Parameters
278 ----------
279 **kwds
280 Keyword arguments forwarded directly to plugin constructors.
281
282 Notes
283 -----
284 Derived class constructors should call this method to fill the
285 `plugins` attribute and add corresponding output fields and slot
286 aliases to the output schema.
287
288 In addition to the attributes added by `BaseMeasurementTask.__init__`,
289 a ``schema``` attribute holding the output schema must be present
290 before this method is called.
291
292 Keyword arguments are forwarded directly to plugin constructors,
293 allowing derived classes to use plugins with different signatures.
294 """
295 # Make a place at the beginning for the centroid plugin to run first
296 # (because it's an OrderedDict, adding an empty element in advance
297 # means it will get run first when it's reassigned to the actual
298 # Plugin).
299 if self.config.slots.centroid is not None:
300 self.plugins[self.config.slots.centroid] = None
301 # Init the plugins, sorted by execution order. At the same time add to
302 # the schema
303 for executionOrder, name, config, PluginClass in sorted(self.config.plugins.apply()):
304 # Pass logName to the plugin if the plugin is marked as using it
305 # The task will use this name to log plugin errors, regardless.
306 if getattr(PluginClass, "hasLogName", False):
307 self.plugins[name] = PluginClass(config, name, metadata=self.algMetadata,
308 logName=self.log.getChild(name).name, **kwds)
309 else:
310 self.plugins[name] = PluginClass(config, name, metadata=self.algMetadata, **kwds)
311
312 # In rare circumstances (usually tests), the centroid slot not be
313 # coming from an algorithm, which means we'll have added something we
314 # don't want to the plugins map, and we should remove it.
315 if self.config.slots.centroid is not None and self.plugins[self.config.slots.centroid] is None:
316 del self.plugins[self.config.slots.centroid]
317 # Initialize the plugins to run on the undeblended image
318 for executionOrder, name, config, PluginClass in sorted(self.config.undeblended.apply()):
319 undeblendedName = self.config.undeblendedPrefix + name
320 if getattr(PluginClass, "hasLogName", False):
321 self.undeblendedPlugins[name] = PluginClass(config, undeblendedName,
322 metadata=self.algMetadata,
323 logName=self.log.getChild(undeblendedName).name,
324 **kwds)
325 else:
326 self.undeblendedPlugins[name] = PluginClass(config, undeblendedName,
327 metadata=self.algMetadata, **kwds)
328
329 if "schemaMapper" in kwds:
330 schema = kwds["schemaMapper"].editOutputSchema()
331 else:
332 schema = kwds["schema"]
333
334 invalidPsfName = "base_InvalidPsf_flag"
335 if invalidPsfName in schema:
336 self.keyInvalidPsf = schema.find(invalidPsfName).key
337 else:
338 self.keyInvalidPsf = schema.addField(
339 invalidPsfName,
340 type="Flag",
341 doc="Invalid PSF at this location.",
342 )
343

◆ run()

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.run ( self,
measCat,
exposure,
refCat,
refWcs,
exposureId = None,
beginOrder = None,
endOrder = None )
Perform forced measurement.

    Parameters
    ----------
    exposure : `lsst.afw.image.exposureF`
        Image to be measured. Must have at least a `lsst.afw.geom.SkyWcs`
        attached.
    measCat : `lsst.afw.table.SourceCatalog`
        Source catalog for measurement results; must be initialized with
        empty records already corresponding to those in ``refCat`` (via
        e.g. `generateMeasCat`).
    refCat : `lsst.afw.table.SourceCatalog`
        A sequence of `lsst.afw.table.SourceRecord` objects that provide
        reference information for the measurement.  These will be passed
        to each plugin in addition to the output
        `~lsst.afw.table.SourceRecord`.
    refWcs : `lsst.afw.geom.SkyWcs`
        Defines the X,Y coordinate system of ``refCat``.
    exposureId : `int`, optional
        Optional unique exposureId used to calculate random number
        generator seed in the NoiseReplacer.
    beginOrder : `int`, optional
        Beginning execution order (inclusive). Algorithms with
        ``executionOrder`` < ``beginOrder`` are not executed. `None` for no limit.
    endOrder : `int`, optional
        Ending execution order (exclusive). Algorithms with
        ``executionOrder`` >= ``endOrder`` are not executed. `None` for no limit.

    Notes
    -----
    Fills the initial empty `~lsst.afw.table.SourceCatalog` with forced
    measurement results.  Two steps must occur before `run` can be called:

    - `generateMeasCat` must be called to create the output ``measCat``
      argument.
    - `~lsst.afw.detection.Footprint`\ s appropriate for the forced sources
      must be attached to the ``measCat`` records. The
      `attachTransformedFootprints` method can be used to do this, but
      this degrades "heavy" (i.e., including pixel values)
      `~lsst.afw.detection.Footprint`\s to regular
      `~lsst.afw.detection.Footprint`\s, leading to non-deblended
      measurement, so most callers should provide
      `~lsst.afw.detection.Footprint`\s some other way. Typically, calling
      code will have access to information that will allow them to provide
      heavy footprints - for instance, `ForcedPhotCoaddTask` uses the
      heavy footprints from deblending run in the same band just before
      non-forced is run measurement in that band.

Definition at line 261 of file forcedMeasurement.py.

261 def run(self, measCat, exposure, refCat, refWcs, exposureId=None, beginOrder=None, endOrder=None):
262 r"""Perform forced measurement.
263
264 Parameters
265 ----------
266 exposure : `lsst.afw.image.exposureF`
267 Image to be measured. Must have at least a `lsst.afw.geom.SkyWcs`
268 attached.
269 measCat : `lsst.afw.table.SourceCatalog`
270 Source catalog for measurement results; must be initialized with
271 empty records already corresponding to those in ``refCat`` (via
272 e.g. `generateMeasCat`).
273 refCat : `lsst.afw.table.SourceCatalog`
274 A sequence of `lsst.afw.table.SourceRecord` objects that provide
275 reference information for the measurement. These will be passed
276 to each plugin in addition to the output
277 `~lsst.afw.table.SourceRecord`.
278 refWcs : `lsst.afw.geom.SkyWcs`
279 Defines the X,Y coordinate system of ``refCat``.
280 exposureId : `int`, optional
281 Optional unique exposureId used to calculate random number
282 generator seed in the NoiseReplacer.
283 beginOrder : `int`, optional
284 Beginning execution order (inclusive). Algorithms with
285 ``executionOrder`` < ``beginOrder`` are not executed. `None` for no limit.
286 endOrder : `int`, optional
287 Ending execution order (exclusive). Algorithms with
288 ``executionOrder`` >= ``endOrder`` are not executed. `None` for no limit.
289
290 Notes
291 -----
292 Fills the initial empty `~lsst.afw.table.SourceCatalog` with forced
293 measurement results. Two steps must occur before `run` can be called:
294
295 - `generateMeasCat` must be called to create the output ``measCat``
296 argument.
297 - `~lsst.afw.detection.Footprint`\ s appropriate for the forced sources
298 must be attached to the ``measCat`` records. The
299 `attachTransformedFootprints` method can be used to do this, but
300 this degrades "heavy" (i.e., including pixel values)
301 `~lsst.afw.detection.Footprint`\s to regular
302 `~lsst.afw.detection.Footprint`\s, leading to non-deblended
303 measurement, so most callers should provide
304 `~lsst.afw.detection.Footprint`\s some other way. Typically, calling
305 code will have access to information that will allow them to provide
306 heavy footprints - for instance, `ForcedPhotCoaddTask` uses the
307 heavy footprints from deblending run in the same band just before
308 non-forced is run measurement in that band.
309 """
310 # First check that the reference catalog does not contain any children
311 # for which any member of their parent chain is not within the list.
312 # This can occur at boundaries when the parent is outside and one of
313 # the children is within. Currently, the parent chain is always only
314 # one deep, but just in case, this code checks for any case where when
315 # the parent chain to a child's topmost parent is broken and raises an
316 # exception if it occurs.
317 #
318 # I.e. this code checks that this precondition is satisfied by
319 # whatever reference catalog provider is being paired with it.
320 refCatIdDict = {ref.getId(): ref.getParent() for ref in refCat}
321 for ref in refCat:
322 refId = ref.getId()
323 topId = refId
324 while topId > 0:
325 if topId not in refCatIdDict:
326 raise RuntimeError("Reference catalog contains a child for which at least "
327 "one parent in its parent chain is not in the catalog.")
328 topId = refCatIdDict[topId]
329
330 # Construct a footprints dict which looks like
331 # {ref.getId(): (ref.getParent(), source.getFootprint())}
332 # (i.e. getting the footprint from the transformed source footprint)
333 footprints = {ref.getId(): (ref.getParent(), measRecord.getFootprint())
334 for (ref, measRecord) in zip(refCat, measCat)}
335
336 self.log.info("Performing forced measurement on %d source%s", len(refCat),
337 "" if len(refCat) == 1 else "s")
338
339 # Wrap the task logger into a periodic logger.
340 periodicLog = PeriodicLogger(self.log)
341
342 if self.config.doReplaceWithNoise:
343 noiseReplacer = NoiseReplacer(self.config.noiseReplacer, exposure,
344 footprints, log=self.log, exposureId=exposureId)
345 algMetadata = measCat.getTable().getMetadata()
346 if algMetadata is not None:
347 algMetadata.addInt("NOISE_SEED_MULTIPLIER", self.config.noiseReplacer.noiseSeedMultiplier)
348 algMetadata.addString("NOISE_SOURCE", self.config.noiseReplacer.noiseSource)
349 algMetadata.addDouble("NOISE_OFFSET", self.config.noiseReplacer.noiseOffset)
350 if exposureId is not None:
351 algMetadata.addLong("NOISE_EXPOSURE_ID", exposureId)
352 else:
353 noiseReplacer = DummyNoiseReplacer()
354
355 # Create parent cat which slices both the refCat and measCat (sources)
356 # first, get the reference and source records which have no parent
357 refParentCat, measParentCat = refCat.getChildren(0, measCat)
358 childrenIter = refCat.getChildren((refParentRecord.getId() for refParentRecord in refCat), measCat)
359 for parentIdx, records in enumerate(zip(refParentCat, measParentCat, childrenIter)):
360 # Unpack records
361 refParentRecord, measParentRecord, (refChildCat, measChildCat) = records
362 # First process the records which have the current parent as children
363 # TODO: skip this loop if there are no plugins configured for single-object mode
364 for refChildRecord, measChildRecord in zip(refChildCat, measChildCat):
365 noiseReplacer.insertSource(refChildRecord.getId())
366 self.callMeasure(measChildRecord, exposure, refChildRecord, refWcs,
367 beginOrder=beginOrder, endOrder=endOrder)
368 noiseReplacer.removeSource(refChildRecord.getId())
369
370 # Then process the parent record
371 noiseReplacer.insertSource(refParentRecord.getId())
372 self.callMeasure(measParentRecord, exposure, refParentRecord, refWcs,
373 beginOrder=beginOrder, endOrder=endOrder)
374 self.callMeasureN(measParentCat[parentIdx:parentIdx+1], exposure,
375 refParentCat[parentIdx:parentIdx+1],
376 beginOrder=beginOrder, endOrder=endOrder)
377 # Measure all the children simultaneously
378 self.callMeasureN(measChildCat, exposure, refChildCat,
379 beginOrder=beginOrder, endOrder=endOrder)
380 noiseReplacer.removeSource(refParentRecord.getId())
381 # Log a message if it has been a while since the last log.
382 periodicLog.log("Forced measurement complete for %d parents (and their children) out of %d",
383 parentIdx + 1, len(refParentCat))
384 noiseReplacer.end()
385
386 # Undeblended plugins only fire if we're running everything
387 if endOrder is None:
388 for recordIndex, (measRecord, refRecord) in enumerate(zip(measCat, refCat)):
389 for plugin in self.undeblendedPlugins.iter():
390 self.doMeasurement(plugin, measRecord, exposure, refRecord, refWcs)
391 periodicLog.log("Undeblended forced measurement complete for %d sources out of %d",
392 recordIndex + 1, len(refCat))
393

Member Data Documentation

◆ _DefaultName

str lsst.meas.base.baseMeasurement.BaseMeasurementTask._DefaultName = "measurement"
staticprotectedinherited

Definition at line 250 of file baseMeasurement.py.

◆ algMetadata

lsst.meas.base.baseMeasurement.BaseMeasurementTask.algMetadata = None
staticinherited

Definition at line 259 of file baseMeasurement.py.

◆ ConfigClass

lsst.meas.base.baseMeasurement.BaseMeasurementTask.ConfigClass = BaseMeasurementConfig
staticinherited

Definition at line 249 of file baseMeasurement.py.

◆ keyInvalidPsf

lsst.meas.base.baseMeasurement.BaseMeasurementTask.keyInvalidPsf = schema.find(invalidPsfName).key
inherited

Definition at line 336 of file baseMeasurement.py.

◆ mapper

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.mapper = lsst.afw.table.SchemaMapper(refSchema)

Definition at line 250 of file forcedMeasurement.py.

◆ plugins

lsst.meas.base.baseMeasurement.BaseMeasurementTask.plugins = None
staticinherited

Definition at line 252 of file baseMeasurement.py.

◆ schema

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.schema = self.mapper.getOutputSchema()

Definition at line 258 of file forcedMeasurement.py.

◆ undeblendedPlugins

lsst.meas.base.baseMeasurement.BaseMeasurementTask.undeblendedPlugins = PluginMap()
inherited

Definition at line 269 of file baseMeasurement.py.


The documentation for this class was generated from the following file: