LSSTApplications  16.0-10-g1758552+4,16.0-10-g4f78f78+4,16.0-10-gc1446dd+30,16.0-11-g39ac3c7+2,16.0-13-g066a532+3,16.0-14-g6c7ed55+4,16.0-14-gd373004+3,16.0-15-g072d20e+4,16.0-15-gb461e1a+2,16.0-16-g48c959a+3,16.0-16-g89065d4+2,16.0-16-gd8e3590+4,16.0-19-gb830ed4e+4,16.0-2-g0febb12+20,16.0-2-g9d5294e+53,16.0-2-ga8830df+3,16.0-20-g17d57d5+2,16.0-22-gf7a7fdf+3,16.0-27-g78173a71+3,16.0-3-g324faa9+3,16.0-3-gcfd6c53+51,16.0-3-ge00e371+9,16.0-4-g03cf288+42,16.0-4-g5f3a788+19,16.0-4-ga3eb747+9,16.0-4-gabf74b7+4,16.0-4-gb13d127+3,16.0-5-g6a53317+9,16.0-5-gb3f8a4b+62,16.0-5-gef99c9f+4,16.0-57-g90e7ba260+2,16.0-6-g0838257+3,16.0-6-g9321be7+3,16.0-6-gcbc7b31+3,16.0-6-gf49912c+4,16.0-7-gd2eeba5+12,16.0-8-g21fd5fe+4,16.0-8-g3a9f023+4,16.0-9-g85d1a16+4,master-g7b902255af+4,w.2018.43
LSSTDataManagementBasePackage
Public Member Functions | Public Attributes | Static Public Attributes | List of all members
lsst.pipe.tasks.multiBand.MergeMeasurementsTask Class Reference

Merge measurements from multiple bands. More...

Inheritance diagram for lsst.pipe.tasks.multiBand.MergeMeasurementsTask:
lsst.pipe.tasks.multiBand.MergeSourcesTask lsst.pipe.tasks.dcrMultiBand.MergeDcrMeasurementsTask

Public Member Functions

def __init__ (self, butler=None, schema=None, kwargs)
 Initialize the task. More...
 
def run (self, catalogs, patchRef)
 Merge measurement catalogs to create a single reference catalog for forced photometry. More...
 
def getInputSchema (self, butler=None, schema=None)
 Obtain the input schema either directly or froma butler reference. More...
 
def runDataRef (self, patchRefList)
 Merge coadd sources from multiple bands. More...
 
def readCatalog (self, patchRef)
 Read input catalog. More...
 
def write (self, patchRef, catalog)
 Write the output. More...
 
def writeMetadata (self, dataRefList)
 No metadata to write, and not sure how to write it for a list of dataRefs. More...
 

Public Attributes

 schemaMapper
 
 instFluxKey
 
 instFluxErrKey
 
 fluxFlagKey
 
 flagKeys
 
 schema
 
 pseudoFilterKeys
 
 badFlags
 

Static Public Attributes

 ConfigClass = MergeMeasurementsConfig
 
string inputDataset = "meas"
 
string outputDataset = "ref"
 
 getSchemaCatalogs = _makeGetSchemaCatalogs("ref")
 
 RunnerClass = MergeSourcesRunner
 

Detailed Description

Merge measurements from multiple bands.

Contents

Description

Command-line task that merges measurements from multiple bands.

Combines consistent (i.e. with the same peaks and footprints) catalogs of sources from multiple filter bands to construct a unified catalog that is suitable for driving forced photometry. Every source is required to have centroid, shape and flux measurements in each band.

Inputs:
deepCoadd_meas{tract,patch,filter}: SourceCatalog
Outputs:
deepCoadd_ref{tract,patch}: SourceCatalog
Data Unit:
tract, patch

MergeMeasurementsTask subclasses MergeSourcesTask.

Task initialization

Initialize the task. Additional keyword arguments (forwarded to MergeSourcesTask.__init__):

Parameters
[in]schemathe schema of the detection catalogs used as input to this one
[in]butlera butler used to read the input schema from disk, if schema is None

The task will set its own self.schema attribute to the schema of the output merged catalog.

Invoking the Task

Merge measurement catalogs to create a single reference catalog for forced photometry.

Parameters
[in]catalogsthe catalogs to be merged
[in]patchRefpatch reference for data

For parent sources, we choose the first band in config.priorityList for which the merge_footprint flag for that band is is True.

For child sources, the logic is the same, except that we use the merge_peak flags.

Configuration parameters

See MergeMeasurementsConfig_

Debug variables

The command line task interface supports a flag -d to import debug.py from your PYTHONPATH; see Using lsstDebug to control debugging output for more about debug.py files.

MergeMeasurementsTask has no debug variables.

A complete example

of using MergeMeasurementsTask

MergeMeasurementsTask is meant to be run after deblending & measuring sources in every band. The purpose of the task is to generate a catalog of sources suitable for driving forced photometry in coadds and individual exposures. Command-line usage of MergeMeasurementsTask expects a data reference to the coadds to be processed. A list of the available optional arguments can be obtained by calling mergeCoaddMeasurements.py with the --help command line argument:

mergeCoaddMeasurements.py --help

To demonstrate usage of the DetectCoaddSourcesTask in the larger context of multi-band processing, we will process HSC data in the ci_hsc package. Assuming one has finished step 7 at pipeTasks_multiBand, one may merge the catalogs generated after deblending and measuring as follows:

mergeCoaddMeasurements.py $CI_HSC_DIR/DATA --id patch=5,4 tract=0 filter=HSC-I^HSC-R

This will merge the HSC-I & HSC-R band catalogs. The results are written in $CI_HSC_DIR/DATA/deepCoadd-results/.

Definition at line 1517 of file multiBand.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.pipe.tasks.multiBand.MergeMeasurementsTask.__init__ (   self,
  butler = None,
  schema = None,
  kwargs 
)

Initialize the task.

Additional keyword arguments (forwarded to MergeSourcesTask.__init__):

Parameters
[in]schemathe schema of the detection catalogs used as input to this one
[in]butlera butler used to read the input schema from disk, if schema is None

The task will set its own self.schema attribute to the schema of the output merged catalog.

Definition at line 1598 of file multiBand.py.

1598  def __init__(self, butler=None, schema=None, **kwargs):
1599  """!
1600  Initialize the task.
1601 
1602  Additional keyword arguments (forwarded to MergeSourcesTask.__init__):
1603  @param[in] schema: the schema of the detection catalogs used as input to this one
1604  @param[in] butler: a butler used to read the input schema from disk, if schema is None
1605 
1606  The task will set its own self.schema attribute to the schema of the output merged catalog.
1607  """
1608  MergeSourcesTask.__init__(self, butler=butler, schema=schema, **kwargs)
1609  inputSchema = self.getInputSchema(butler=butler, schema=schema)
1610  self.schemaMapper = afwTable.SchemaMapper(inputSchema, True)
1611  self.schemaMapper.addMinimalSchema(inputSchema, True)
1612  self.instFluxKey = inputSchema.find(self.config.snName + "_instFlux").getKey()
1613  self.instFluxErrKey = inputSchema.find(self.config.snName + "_instFluxErr").getKey()
1614  self.fluxFlagKey = inputSchema.find(self.config.snName + "_flag").getKey()
1615 
1616  self.flagKeys = {}
1617  for band in self.config.priorityList:
1618  short = getShortFilterName(band)
1619  outputKey = self.schemaMapper.editOutputSchema().addField(
1620  "merge_measurement_%s" % short,
1621  type="Flag",
1622  doc="Flag field set if the measurements here are from the %s filter" % band
1623  )
1624  peakKey = inputSchema.find("merge_peak_%s" % short).key
1625  footprintKey = inputSchema.find("merge_footprint_%s" % short).key
1626  self.flagKeys[band] = Struct(peak=peakKey, footprint=footprintKey, output=outputKey)
1627  self.schema = self.schemaMapper.getOutputSchema()
1628 
1629  self.pseudoFilterKeys = []
1630  for filt in self.config.pseudoFilterList:
1631  try:
1632  self.pseudoFilterKeys.append(self.schema.find("merge_peak_%s" % filt).getKey())
1633  except Exception as e:
1634  self.log.warn("merge_peak is not set for pseudo-filter %s: %s" % (filt, e))
1635 
1636  self.badFlags = {}
1637  for flag in self.config.flags:
1638  try:
1639  self.badFlags[flag] = self.schema.find(flag).getKey()
1640  except KeyError as exc:
1641  self.log.warn("Can't find flag %s in schema: %s" % (flag, exc,))
1642 
A mapping between the keys of two Schemas, used to copy data between them.
Definition: SchemaMapper.h:21
def getShortFilterName(name)
Definition: multiBand.py:98
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
Definition: functional.cc:33
def __init__(self, minimum, dataRange, Q)

Member Function Documentation

◆ getInputSchema()

def lsst.pipe.tasks.multiBand.MergeSourcesTask.getInputSchema (   self,
  butler = None,
  schema = None 
)
inherited

Obtain the input schema either directly or froma butler reference.

Parameters
[in]butlerbutler reference to obtain the input schema from
[in]schemathe input schema

Definition at line 537 of file multiBand.py.

537  def getInputSchema(self, butler=None, schema=None):
538  """!
539  @brief Obtain the input schema either directly or froma butler reference.
540 
541  @param[in] butler butler reference to obtain the input schema from
542  @param[in] schema the input schema
543  """
544  if schema is None:
545  assert butler is not None, "Neither butler nor schema specified"
546  schema = butler.get(self.config.coaddName + "Coadd_" + self.inputDataset + "_schema",
547  immediate=True).schema
548  return schema
549 

◆ readCatalog()

def lsst.pipe.tasks.multiBand.MergeSourcesTask.readCatalog (   self,
  patchRef 
)
inherited

Read input catalog.

We read the input dataset provided by the 'inputDataset' class variable.

Parameters
[in]patchRefdata reference for patch
Returns
tuple consisting of the filter name and the catalog

Definition at line 574 of file multiBand.py.

574  def readCatalog(self, patchRef):
575  """!
576  @brief Read input catalog.
577 
578  We read the input dataset provided by the 'inputDataset'
579  class variable.
580 
581  @param[in] patchRef data reference for patch
582  @return tuple consisting of the filter name and the catalog
583  """
584  filterName = patchRef.dataId["filter"]
585  catalog = patchRef.get(self.config.coaddName + "Coadd_" + self.inputDataset, immediate=True)
586  self.log.info("Read %d sources for filter %s: %s" % (len(catalog), filterName, patchRef.dataId))
587  return filterName, catalog
588 

◆ run()

def lsst.pipe.tasks.multiBand.MergeMeasurementsTask.run (   self,
  catalogs,
  patchRef 
)

Merge measurement catalogs to create a single reference catalog for forced photometry.

Parameters
[in]catalogsthe catalogs to be merged
[in]patchRefpatch reference for data

For parent sources, we choose the first band in config.priorityList for which the merge_footprint flag for that band is is True.

For child sources, the logic is the same, except that we use the merge_peak flags.

Definition at line 1643 of file multiBand.py.

1643  def run(self, catalogs, patchRef):
1644  """!
1645  Merge measurement catalogs to create a single reference catalog for forced photometry
1646 
1647  @param[in] catalogs: the catalogs to be merged
1648  @param[in] patchRef: patch reference for data
1649 
1650  For parent sources, we choose the first band in config.priorityList for which the
1651  merge_footprint flag for that band is is True.
1652 
1653  For child sources, the logic is the same, except that we use the merge_peak flags.
1654  """
1655  # Put catalogs, filters in priority order
1656  orderedCatalogs = [catalogs[band] for band in self.config.priorityList if band in catalogs.keys()]
1657  orderedKeys = [self.flagKeys[band] for band in self.config.priorityList if band in catalogs.keys()]
1658 
1659  mergedCatalog = afwTable.SourceCatalog(self.schema)
1660  mergedCatalog.reserve(len(orderedCatalogs[0]))
1661 
1662  idKey = orderedCatalogs[0].table.getIdKey()
1663  for catalog in orderedCatalogs[1:]:
1664  if numpy.any(orderedCatalogs[0].get(idKey) != catalog.get(idKey)):
1665  raise ValueError("Error in inputs to MergeCoaddMeasurements: source IDs do not match")
1666 
1667  # This first zip iterates over all the catalogs simultaneously, yielding a sequence of one
1668  # record for each band, in priority order.
1669  for orderedRecords in zip(*orderedCatalogs):
1670 
1671  maxSNRecord = None
1672  maxSNFlagKeys = None
1673  maxSN = 0.
1674  priorityRecord = None
1675  priorityFlagKeys = None
1676  prioritySN = 0.
1677  hasPseudoFilter = False
1678 
1679  # Now we iterate over those record-band pairs, keeping track of the priority and the
1680  # largest S/N band.
1681  for inputRecord, flagKeys in zip(orderedRecords, orderedKeys):
1682  parent = (inputRecord.getParent() == 0 and inputRecord.get(flagKeys.footprint))
1683  child = (inputRecord.getParent() != 0 and inputRecord.get(flagKeys.peak))
1684 
1685  if not (parent or child):
1686  for pseudoFilterKey in self.pseudoFilterKeys:
1687  if inputRecord.get(pseudoFilterKey):
1688  hasPseudoFilter = True
1689  priorityRecord = inputRecord
1690  priorityFlagKeys = flagKeys
1691  break
1692  if hasPseudoFilter:
1693  break
1694 
1695  isBad = any(inputRecord.get(flag) for flag in self.badFlags)
1696  if isBad or inputRecord.get(self.fluxFlagKey) or inputRecord.get(self.instFluxErrKey) == 0:
1697  sn = 0.
1698  else:
1699  sn = inputRecord.get(self.instFluxKey)/inputRecord.get(self.instFluxErrKey)
1700  if numpy.isnan(sn) or sn < 0.:
1701  sn = 0.
1702  if (parent or child) and priorityRecord is None:
1703  priorityRecord = inputRecord
1704  priorityFlagKeys = flagKeys
1705  prioritySN = sn
1706  if sn > maxSN:
1707  maxSNRecord = inputRecord
1708  maxSNFlagKeys = flagKeys
1709  maxSN = sn
1710 
1711  # If the priority band has a low S/N we would like to choose the band with the highest S/N as
1712  # the reference band instead. However, we only want to choose the highest S/N band if it is
1713  # significantly better than the priority band. Therefore, to choose a band other than the
1714  # priority, we require that the priority S/N is below the minimum threshold and that the
1715  # difference between the priority and highest S/N is larger than the difference threshold.
1716  #
1717  # For pseudo code objects we always choose the first band in the priority list.
1718  bestRecord = None
1719  bestFlagKeys = None
1720  if hasPseudoFilter:
1721  bestRecord = priorityRecord
1722  bestFlagKeys = priorityFlagKeys
1723  elif (prioritySN < self.config.minSN and (maxSN - prioritySN) > self.config.minSNDiff and
1724  maxSNRecord is not None):
1725  bestRecord = maxSNRecord
1726  bestFlagKeys = maxSNFlagKeys
1727  elif priorityRecord is not None:
1728  bestRecord = priorityRecord
1729  bestFlagKeys = priorityFlagKeys
1730 
1731  if bestRecord is not None and bestFlagKeys is not None:
1732  outputRecord = mergedCatalog.addNew()
1733  outputRecord.assign(bestRecord, self.schemaMapper)
1734  outputRecord.set(bestFlagKeys.output, True)
1735  else: # if we didn't find any records
1736  raise ValueError("Error in inputs to MergeCoaddMeasurements: no valid reference for %s" %
1737  inputRecord.getId())
1738 
1739  # more checking for sane inputs, since zip silently iterates over the smallest sequence
1740  for inputCatalog in orderedCatalogs:
1741  if len(mergedCatalog) != len(inputCatalog):
1742  raise ValueError("Mismatch between catalog sizes: %s != %s" %
1743  (len(mergedCatalog), len(orderedCatalogs)))
1744 
1745  return mergedCatalog
1746 
bool any(CoordinateExpr< N > const &expr) noexcept
Return true if any elements are true.

◆ runDataRef()

def lsst.pipe.tasks.multiBand.MergeSourcesTask.runDataRef (   self,
  patchRefList 
)
inherited

Merge coadd sources from multiple bands.

Calls run which must be defined in subclasses that inherit from MergeSourcesTask.

Parameters
[in]patchRefListlist of data references for each filter

Definition at line 563 of file multiBand.py.

563  def runDataRef(self, patchRefList):
564  """!
565  @brief Merge coadd sources from multiple bands. Calls @ref `run` which must be defined in
566  subclasses that inherit from MergeSourcesTask.
567 
568  @param[in] patchRefList list of data references for each filter
569  """
570  catalogs = dict(self.readCatalog(patchRef) for patchRef in patchRefList)
571  mergedCatalog = self.run(catalogs, patchRefList[0])
572  self.write(patchRefList[0], mergedCatalog)
573 

◆ write()

def lsst.pipe.tasks.multiBand.MergeSourcesTask.write (   self,
  patchRef,
  catalog 
)
inherited

Write the output.

Parameters
[in]patchRefdata reference for patch
[in]catalogcatalog

We write as the dataset provided by the 'outputDataset' class variable.

Definition at line 600 of file multiBand.py.

600  def write(self, patchRef, catalog):
601  """!
602  @brief Write the output.
603 
604  @param[in] patchRef data reference for patch
605  @param[in] catalog catalog
606 
607  We write as the dataset provided by the 'outputDataset'
608  class variable.
609  """
610  patchRef.put(catalog, self.config.coaddName + "Coadd_" + self.outputDataset)
611  # since the filter isn't actually part of the data ID for the dataset we're saving,
612  # it's confusing to see it in the log message, even if the butler simply ignores it.
613  mergeDataId = patchRef.dataId.copy()
614  del mergeDataId["filter"]
615  self.log.info("Wrote merged catalog: %s" % (mergeDataId,))
616 

◆ writeMetadata()

def lsst.pipe.tasks.multiBand.MergeSourcesTask.writeMetadata (   self,
  dataRefList 
)
inherited

No metadata to write, and not sure how to write it for a list of dataRefs.

Definition at line 617 of file multiBand.py.

617  def writeMetadata(self, dataRefList):
618  """!
619  @brief No metadata to write, and not sure how to write it for a list of dataRefs.
620  """
621  pass
622 
623 

Member Data Documentation

◆ badFlags

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.badFlags

Definition at line 1636 of file multiBand.py.

◆ ConfigClass

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.ConfigClass = MergeMeasurementsConfig
static

Definition at line 1593 of file multiBand.py.

◆ flagKeys

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.flagKeys

Definition at line 1616 of file multiBand.py.

◆ fluxFlagKey

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.fluxFlagKey

Definition at line 1614 of file multiBand.py.

◆ getSchemaCatalogs

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.getSchemaCatalogs = _makeGetSchemaCatalogs("ref")
static

Definition at line 1596 of file multiBand.py.

◆ inputDataset

string lsst.pipe.tasks.multiBand.MergeMeasurementsTask.inputDataset = "meas"
static

Definition at line 1594 of file multiBand.py.

◆ instFluxErrKey

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.instFluxErrKey

Definition at line 1613 of file multiBand.py.

◆ instFluxKey

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.instFluxKey

Definition at line 1612 of file multiBand.py.

◆ outputDataset

string lsst.pipe.tasks.multiBand.MergeMeasurementsTask.outputDataset = "ref"
static

Definition at line 1595 of file multiBand.py.

◆ pseudoFilterKeys

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.pseudoFilterKeys

Definition at line 1629 of file multiBand.py.

◆ RunnerClass

lsst.pipe.tasks.multiBand.MergeSourcesTask.RunnerClass = MergeSourcesRunner
staticinherited

Definition at line 517 of file multiBand.py.

◆ schema

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.schema

Definition at line 1627 of file multiBand.py.

◆ schemaMapper

lsst.pipe.tasks.multiBand.MergeMeasurementsTask.schemaMapper

Definition at line 1610 of file multiBand.py.


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