lsst.meas.astrom  14.0-7-g0d69b06+3
directMatch.py
Go to the documentation of this file.
1 from __future__ import absolute_import, division, print_function
2 
3 __all__ = ["DirectMatchConfig", "DirectMatchTask", "DirectMatchConfigWithoutLoader"]
4 
5 from lsst.pex.config import Config, Field, ConfigurableField
6 from lsst.pipe.base import Task, Struct
7 from lsst.meas.algorithms import (LoadIndexedReferenceObjectsTask, ScienceSourceSelectorTask,
8  ReferenceSourceSelectorTask)
9 import lsst.afw.table as afwTable
10 import lsst.afw.coord as afwCoord
11 from lsst.afw.geom import arcseconds
12 
13 
15  """Configuration for DirectMatchTask when an already-initialized
16  refObjLoader will be passed to this task."""
17  matchRadius = Field(dtype=float, default=0.25, doc="Matching radius, arcsec")
18  sourceSelection = ConfigurableField(target=ScienceSourceSelectorTask,
19  doc="Selection of science sources")
20  referenceSelection = ConfigurableField(target=ReferenceSourceSelectorTask,
21  doc="Selection of reference sources")
22 
23 
25  """Configuration for DirectMatchTask"""
26  refObjLoader = ConfigurableField(target=LoadIndexedReferenceObjectsTask, doc="Load reference objects")
27 
28 
29 class DirectMatchTask(Task):
30  """!Simple matching of a source catalog to a reference catalog
31 
32  @anchor DirectMatchTask_
33 
34  @section meas_astrom_match_Contents Contents
35 
36  - @ref meas_astrom_match_Purpose
37  - @ref meas_astrom_match_Initialize
38  - @ref meas_astrom_match_IO
39  - @ref meas_astrom_match_Config
40  - @ref meas_astrom_match_Example
41 
42  @section meas_astrom_match_Purpose Description
43 
44  Match sources to reference objects. The matching permits no rotation or scaling,
45  but uses the existing sky positions in the source catalog. This is often useful
46  for QA, as it allows validating the pipeline astrometry and photometry against
47  the reference catalog.
48 
49  Note that this DirectMatchTask is not currently suitable for use within the
50  AstrometryTask, as it has a different interface and serves a different purpose.
51 
52  @section meas_astrom_match_Initialize Task initialisation
53 
54  @copydoc \_\_init\_\_
55 
56  @section meas_astrom_match_IO Invoking the Task
57 
58  @copydoc run
59 
60  @section meas_astrom_match_Config Configuration parameters
61 
62  See @ref DirectMatchConfig
63 
64  @section meas_astrom_match_Example A complete example of using DirectMatchTask
65 
66  config = DirectMatchConfig()
67  task = DirectMatchTask(butler=butler, config=config)
68  matchResults = task.run(catalog)
69 
70  """
71 
72  ConfigClass = DirectMatchConfig
73  _DefaultName = "directMatch"
74 
75  def __init__(self, butler=None, refObjLoader=None, **kwargs):
76  """!Ctor
77 
78  Either a 'butler' or 'refObjLoader' is required.
79 
80  @param butler Data butler, or None
81  @param refObjLoader For loading reference objects (lsst.meas.algorithms.LoadReferenceObjectsTask), or
82  None
83  @param kwargs Other keyword arguments required for instantiating a Task (e.g., 'config')
84  """
85  Task.__init__(self, **kwargs)
86  if not refObjLoader:
87  if not isinstance(self.config, DirectMatchConfig):
88  raise RuntimeError("DirectMatchTask must be initialized with DirectMatchConfig "
89  "if a refObjLoader is not supplied at initialization")
90  self.makeSubtask("refObjLoader", butler=butler)
91  else:
92  self.refObjLoader = refObjLoader
93  self.makeSubtask("sourceSelection")
94  self.makeSubtask("referenceSelection")
95 
96  def run(self, catalog, filterName=None):
97  """!Load reference objects and match to them
98 
99  @param[in] catalog Catalog to match to (lsst.afw.table.SourceCatalog)
100  @param[in] filterName Name of filter, for loading fluxes (str)
101  @return Struct with matches (lsst.afw.table.SourceMatchVector) and
102  matchMeta (lsst.meas.astrom.MatchMetadata)
103  """
104  circle = self.calculateCircle(catalog)
105  matchMeta = self.refObjLoader.getMetadataCircle(circle.center, circle.radius, filterName)
106  emptyResult = Struct(matches=[], matchMeta=matchMeta)
107  sourceSelection = self.sourceSelection.selectSources(catalog)
108  if len(sourceSelection.sourceCat) == 0:
109  self.log.warn("No objects selected from %d objects in source catalog", len(catalog))
110  return emptyResult
111  refData = self.refObjLoader.loadSkyCircle(circle.center, circle.radius, filterName)
112  refCat = refData.refCat
113  refSelection = self.referenceSelection.selectSources(refCat)
114  if len(refSelection.sourceCat) == 0:
115  self.log.warn("No objects selected from %d objects in reference catalog", len(refCat))
116  return emptyResult
117  matches = afwTable.matchRaDec(refSelection.sourceCat, sourceSelection.sourceCat,
118  self.config.matchRadius*arcseconds)
119  self.log.info("Matched %d from %d/%d input and %d/%d reference sources" %
120  (len(matches), len(sourceSelection.sourceCat), len(catalog),
121  len(refSelection.sourceCat), len(refCat)))
122  return Struct(matches=matches, matchMeta=matchMeta, refCat=refCat, sourceSelection=sourceSelection,
123  refSelection=refSelection)
124 
125  def calculateCircle(self, catalog):
126  """!Calculate a circle enclosing the catalog
127 
128  @param[in] catalog Catalog we will encircle (lsst.afw.table.SourceCatalog)
129  @return Struct with center (lsst.afw.coord.Coord) and radius (lsst.afw.geom.Angle)
130  """
131  coordList = [src.getCoord() for src in catalog]
132  center = afwCoord.averageCoord(coordList)
133  radius = max(center.angularSeparation(coord) for coord in coordList)
134  return Struct(center=center, radius=radius + self.config.matchRadius*arcseconds)
Simple matching of a source catalog to a reference catalog.
Definition: directMatch.py:29
std::vector< Match< typename Cat::Record, typename Cat::Record > > matchRaDec(Cat const &cat, Angle radius, bool symmetric)
def run(self, catalog, filterName=None)
Load reference objects and match to them.
Definition: directMatch.py:96
def calculateCircle(self, catalog)
Calculate a circle enclosing the catalog.
Definition: directMatch.py:125
std::shared_ptr< Coord > averageCoord(std::vector< std::shared_ptr< Coord const >> const coords, CoordSystem system=UNKNOWN)
def __init__(self, butler=None, refObjLoader=None, kwargs)
Ctor.
Definition: directMatch.py:75