LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
Public Member Functions | Public Attributes | Static Public Attributes | List of all members
lsst.meas.base.forcedMeasurement.ForcedMeasurementTask Class Reference
Inheritance diagram for lsst.meas.base.forcedMeasurement.ForcedMeasurementTask:
lsst.meas.base.baseMeasurement.BaseMeasurementTask

Public Member Functions

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

Public Attributes

 mapper
 
 schema
 
 undeblendedPlugins
 

Static Public Attributes

 ConfigClass = ForcedMeasurementConfig
 
 plugins = None
 
 algMetadata = None
 

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 220 of file forcedMeasurement.py.

Constructor & Destructor Documentation

◆ __init__()

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

Definition at line 253 of file forcedMeasurement.py.

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

Member Function Documentation

◆ attachPsfShapeFootprints()

def 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 463 of file forcedMeasurement.py.

463  def attachPsfShapeFootprints(self, sources, exposure, scaling=3):
464  """Attach Footprints to blank sources prior to measurement, by
465  creating elliptical Footprints from the PSF moments.
466 
467  Parameters
468  ----------
469  sources : `lsst.afw.table.SourceCatalog`
470  Blank catalog (with all rows and columns, but values other than
471  ``coord_ra``, ``coord_dec`` unpopulated).
472  to which footprints should be attached.
473  exposure : `lsst.afw.image.Exposure`
474  Image object from which peak values and the PSF are obtained.
475  scaling : `int`, optional
476  Scaling factor to apply to the PSF second-moments ellipse in order
477  to determine the footprint boundary.
478 
479  Notes
480  -----
481  This is a utility function for use by parent tasks; see
482  `attachTransformedFootprints` for more information.
483  """
484  psf = exposure.getPsf()
485  if psf is None:
486  raise RuntimeError("Cannot construct Footprints from PSF shape without a PSF.")
487  bbox = exposure.getBBox()
488  wcs = exposure.getWcs()
489  for record in sources:
490  localPoint = wcs.skyToPixel(record.getCoord())
491  localIntPoint = lsst.geom.Point2I(localPoint)
492  assert bbox.contains(localIntPoint), (
493  f"Center for record {record.getId()} is not in exposure; this should be guaranteed by "
494  "generateMeasCat."
495  )
496  ellipse = lsst.afw.geom.ellipses.Ellipse(psf.computeShape(localPoint), localPoint)
497  ellipse.getCore().scale(scaling)
498  spans = lsst.afw.geom.SpanSet.fromShape(ellipse)
499  footprint = lsst.afw.detection.Footprint(spans.clippedTo(bbox), bbox)
500  footprint.addPeak(localIntPoint.getX(), localIntPoint.getY(),
501  exposure.image._get(localIntPoint, lsst.afw.image.PARENT))
502  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
def scale(algorithm, min, max=None, frame=None)
Definition: ds9.py:108

◆ attachTransformedFootprints()

def 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 440 of file forcedMeasurement.py.

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

◆ callMeasure()

def 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 295 of file baseMeasurement.py.

295  def callMeasure(self, measRecord, *args, **kwds):
296  """Call ``measure`` on all plugins and consistently handle exceptions.
297 
298  Parameters
299  ----------
300  measRecord : `lsst.afw.table.SourceRecord`
301  The record corresponding to the object being measured. Will be
302  updated in-place with the results of measurement.
303  *args
304  Positional arguments forwarded to ``plugin.measure``
305  **kwds
306  Keyword arguments. Two are handled locally:
307 
308  beginOrder : `int`
309  Beginning execution order (inclusive). Measurements with
310  ``executionOrder`` < ``beginOrder`` are not executed. `None`
311  for no limit.
312 
313  endOrder : `int`
314  Ending execution order (exclusive). Measurements with
315  ``executionOrder`` >= ``endOrder`` are not executed. `None`
316  for no limit.
317 
318  Others are forwarded to ``plugin.measure()``.
319 
320  Notes
321  -----
322  This method can be used with plugins that have different signatures;
323  the only requirement is that ``measRecord`` be the first argument.
324  Subsequent positional arguments and keyword arguments are forwarded
325  directly to the plugin.
326 
327  This method should be considered "protected": it is intended for use by
328  derived classes, not users.
329  """
330  beginOrder = kwds.pop("beginOrder", None)
331  endOrder = kwds.pop("endOrder", None)
332  for plugin in self.plugins.iter():
333  if beginOrder is not None and plugin.getExecutionOrder() < beginOrder:
334  continue
335  if endOrder is not None and plugin.getExecutionOrder() >= endOrder:
336  break
337  self.doMeasurement(plugin, measRecord, *args, **kwds)
338 

◆ callMeasureN()

def 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 381 of file baseMeasurement.py.

381  def callMeasureN(self, measCat, *args, **kwds):
382  """Call ``measureN`` on all plugins and consistently handle exceptions.
383 
384  Parameters
385  ----------
386  measCat : `lsst.afw.table.SourceCatalog`
387  Catalog containing only the records for the source family to be
388  measured, and where outputs should be written.
389  *args
390  Positional arguments forwarded to ``plugin.measure()``
391  **kwds
392  Keyword arguments. Two are handled locally:
393 
394  beginOrder:
395  Beginning execution order (inclusive): Measurements with
396  ``executionOrder`` < ``beginOrder`` are not executed. `None`
397  for no limit.
398  endOrder:
399  Ending execution order (exclusive): measurements with
400  ``executionOrder`` >= ``endOrder`` are not executed. `None` for
401  no ``limit``.
402 
403  Others are are 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 ``measRecord`` be the first argument.
409  Subsequent positional arguments and keyword arguments are forwarded
410  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  beginOrder = kwds.pop("beginOrder", None)
416  endOrder = kwds.pop("endOrder", None)
417  for plugin in self.plugins.iterN():
418  if beginOrder is not None and plugin.getExecutionOrder() < beginOrder:
419  continue
420  if endOrder is not None and plugin.getExecutionOrder() >= endOrder:
421  break
422  self.doMeasurementN(plugin, measCat, *args, **kwds)
423 

◆ doMeasurement()

def 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 339 of file baseMeasurement.py.

339  def doMeasurement(self, plugin, measRecord, *args, **kwds):
340  """Call ``measure`` on the specified plugin.
341 
342  Exceptions are handled in a consistent way.
343 
344  Parameters
345  ----------
346  plugin : subclass of `BasePlugin`
347  Plugin that will be executed.
348  measRecord : `lsst.afw.table.SourceRecord`
349  The record corresponding to the object being measured. Will be
350  updated in-place with the results of measurement.
351  *args
352  Positional arguments forwarded to ``plugin.measure()``.
353  **kwds
354  Keyword arguments forwarded to ``plugin.measure()``.
355 
356  Notes
357  -----
358  This method can be used with plugins that have different signatures;
359  the only requirement is that ``plugin`` and ``measRecord`` be the first
360  two arguments. Subsequent positional arguments and keyword arguments
361  are forwarded directly to the plugin.
362 
363  This method should be considered "protected": it is intended for use by
364  derived classes, not users.
365  """
366  try:
367  plugin.measure(measRecord, *args, **kwds)
368  except FATAL_EXCEPTIONS:
369  raise
370  except MeasurementError as error:
371  self.log.getChild(plugin.name).debug(
372  "MeasurementError in %s.measure on record %s: %s",
373  plugin.name, measRecord.getId(), error)
374  plugin.fail(measRecord, error)
375  except Exception as error:
376  self.log.getChild(plugin.name).debug(
377  "Exception in %s.measure on record %s: %s",
378  plugin.name, measRecord.getId(), error)
379  plugin.fail(measRecord)
380 

◆ doMeasurementN()

def 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 424 of file baseMeasurement.py.

424  def doMeasurementN(self, plugin, measCat, *args, **kwds):
425  """Call ``measureN`` on the specified plugin.
426 
427  Exceptions are handled in a consistent way.
428 
429  Parameters
430  ----------
431  plugin : subclass of `BasePlugin`
432  Plugin that will be executed.
433  measCat : `lsst.afw.table.SourceCatalog`
434  Catalog containing only the records for the source family to be
435  measured, and where outputs should be written.
436  *args
437  Positional arguments forwarded to ``plugin.measureN()``.
438  **kwds
439  Keyword arguments forwarded to ``plugin.measureN()``.
440 
441  Notes
442  -----
443  This method can be used with plugins that have different signatures;
444  the only requirement is that the ``plugin`` and ``measCat`` be the
445  first two arguments. Subsequent positional arguments and keyword
446  arguments are forwarded directly to the plugin.
447 
448  This method should be considered "protected": it is intended for use by
449  derived classes, not users.
450  """
451  try:
452  plugin.measureN(measCat, *args, **kwds)
453  except FATAL_EXCEPTIONS:
454  raise
455 
456  except MeasurementError as error:
457  for measRecord in measCat:
458  self.log.getChild(plugin.name).debug(
459  "MeasurementError in %s.measureN on records %s-%s: %s",
460  plugin.name, measCat[0].getId(), measCat[-1].getId(), error)
461  plugin.fail(measRecord, error)
462  except Exception as error:
463  for measRecord in measCat:
464  plugin.fail(measRecord)
465  self.log.getChild(plugin.name).debug(
466  "Exception in %s.measureN on records %s-%s: %s",
467  plugin.name, measCat[0].getId(), measCat[-1].getId(), error)

◆ generateMeasCat()

def 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``.
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 401 of file forcedMeasurement.py.

401  def generateMeasCat(self, exposure, refCat, refWcs, idFactory=None):
402  r"""Initialize an output catalog from the reference catalog.
403 
404  Parameters
405  ----------
406  exposure : `lsst.afw.image.exposureF`
407  Image to be measured.
408  refCat : iterable of `lsst.afw.table.SourceRecord`
409  Catalog of reference sources.
410  refWcs : `lsst.afw.geom.SkyWcs`
411  Defines the X,Y coordinate system of ``refCat``.
412  idFactory : `lsst.afw.table.IdFactory`, optional
413  Factory for creating IDs for sources.
414 
415  Returns
416  -------
417  meascat : `lsst.afw.table.SourceCatalog`
418  Source catalog ready for measurement.
419 
420  Notes
421  -----
422  This generates a new blank `~lsst.afw.table.SourceRecord` for each
423  record in ``refCat``. Note that this method does not attach any
424  `~lsst.afw.detection.Footprint`\ s. Doing so is up to the caller (who
425  may call `attachedTransformedFootprints` or define their own method -
426  see `run` for more information).
427  """
428  if idFactory is None:
430  table = lsst.afw.table.SourceTable.make(self.schema, idFactory)
431  measCat = lsst.afw.table.SourceCatalog(table)
432  table = measCat.table
433  table.setMetadata(self.algMetadata)
434  table.preallocate(len(refCat))
435  for ref in refCat:
436  newSource = measCat.addNew()
437  newSource.assign(ref, self.mapper)
438  return measCat
439 
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:382

◆ initializePlugins()

def 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 240 of file baseMeasurement.py.

240  def initializePlugins(self, **kwds):
241  """Initialize plugins (and slots) according to configuration.
242 
243  Parameters
244  ----------
245  **kwds
246  Keyword arguments forwarded directly to plugin constructors.
247 
248  Notes
249  -----
250  Derived class constructors should call this method to fill the
251  `plugins` attribute and add corresponding output fields and slot
252  aliases to the output schema.
253 
254  In addition to the attributes added by `BaseMeasurementTask.__init__`,
255  a ``schema``` attribute holding the output schema must be present
256  before this method is called.
257 
258  Keyword arguments are forwarded directly to plugin constructors,
259  allowing derived classes to use plugins with different signatures.
260  """
261  # Make a place at the beginning for the centroid plugin to run first
262  # (because it's an OrderedDict, adding an empty element in advance
263  # means it will get run first when it's reassigned to the actual
264  # Plugin).
265  if self.config.slots.centroid is not None:
266  self.plugins[self.config.slots.centroid] = None
267  # Init the plugins, sorted by execution order. At the same time add to
268  # the schema
269  for executionOrder, name, config, PluginClass in sorted(self.config.plugins.apply()):
270  # Pass logName to the plugin if the plugin is marked as using it
271  # The task will use this name to log plugin errors, regardless.
272  if getattr(PluginClass, "hasLogName", False):
273  self.plugins[name] = PluginClass(config, name, metadata=self.algMetadata,
274  logName=self.log.getChild(name).name, **kwds)
275  else:
276  self.plugins[name] = PluginClass(config, name, metadata=self.algMetadata, **kwds)
277 
278  # In rare circumstances (usually tests), the centroid slot not be
279  # coming from an algorithm, which means we'll have added something we
280  # don't want to the plugins map, and we should remove it.
281  if self.config.slots.centroid is not None and self.plugins[self.config.slots.centroid] is None:
282  del self.plugins[self.config.slots.centroid]
283  # Initialize the plugins to run on the undeblended image
284  for executionOrder, name, config, PluginClass in sorted(self.config.undeblended.apply()):
285  undeblendedName = self.config.undeblendedPrefix + name
286  if getattr(PluginClass, "hasLogName", False):
287  self.undeblendedPlugins[name] = PluginClass(config, undeblendedName,
288  metadata=self.algMetadata,
289  logName=self.log.getChild(undeblendedName).name,
290  **kwds)
291  else:
292  self.undeblendedPlugins[name] = PluginClass(config, undeblendedName,
293  metadata=self.algMetadata, **kwds)
294 

◆ run()

def 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 266 of file forcedMeasurement.py.

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

Member Data Documentation

◆ algMetadata

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

Definition at line 225 of file baseMeasurement.py.

◆ ConfigClass

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.ConfigClass = ForcedMeasurementConfig
static

Definition at line 251 of file forcedMeasurement.py.

◆ mapper

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.mapper

Definition at line 255 of file forcedMeasurement.py.

◆ plugins

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

Definition at line 218 of file baseMeasurement.py.

◆ schema

lsst.meas.base.forcedMeasurement.ForcedMeasurementTask.schema

Definition at line 263 of file forcedMeasurement.py.

◆ undeblendedPlugins

lsst.meas.base.baseMeasurement.BaseMeasurementTask.undeblendedPlugins
inherited

Definition at line 235 of file baseMeasurement.py.


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