lsst.meas.astrom gdc81be3499+a88542c14c
Loading...
Searching...
No Matches
directMatch.py
Go to the documentation of this file.
2__all__ = ["DirectMatchConfig", "DirectMatchTask", "DirectMatchConfigWithoutLoader"]
3
4import warnings
5
6from lsst.pex.config import Config, Field, ConfigurableField, ConfigField
7from lsst.pipe.base import Task, Struct
8from lsst.meas.algorithms import (LoadReferenceObjectsConfig, ScienceSourceSelectorTask,
9 ReferenceSourceSelectorTask)
10import lsst.afw.table as afwTable
11from lsst.geom import arcseconds, averageSpherePoint
12
13
15 """Configuration for `DirectMatchTask` when an already-initialized
16 ``refObjLoader`` will be passed to this task.
17 """
18 matchRadius = Field(dtype=float, default=0.25, doc="Matching radius, arcsec")
19 sourceSelection = ConfigurableField(target=ScienceSourceSelectorTask,
20 doc="Selection of science sources")
21 referenceSelection = ConfigurableField(target=ReferenceSourceSelectorTask,
22 doc="Selection of reference sources")
23
24
26 """Configuration for `DirectMatchTask`.
27 """
28 refObjLoader = ConfigField(dtype=LoadReferenceObjectsConfig,
29 doc="Configuration of reference object loader")
30
31
32class DirectMatchTask(Task):
33 """Simple, brute force matching of a source catalog to a reference catalog.
34
35 Parameters
36 ----------
37 butler : `None`
38 Compatibility parameter. Should not be used.
39 refObjLoader : `lsst.meas.algorithms.ReferenceObjectLoader` or `None`
40 For loading reference objects.
41 **kwargs
42 Other keyword arguments required for instantiating a Task (such as
43 ``config``).
44 """
45 ConfigClass = DirectMatchConfig
46 _DefaultName = "directMatch"
47
48 def __init__(self, butler=None, refObjLoader=None, **kwargs):
49 Task.__init__(self, **kwargs)
50 if not refObjLoader:
51 if butler:
52 if not isinstance(self.config, DirectMatchConfig):
53 raise RuntimeError("DirectMatchTask must be initialized with DirectMatchConfig "
54 "if a refObjLoader is not supplied at initialization")
55 warnings.warn("The 'butler' parameter is no longer used and can be safely removed.",
56 category=FutureWarning, stacklevel=2)
57 self.refObjLoader = refObjLoader
58 self.makeSubtask("sourceSelection")
59 self.makeSubtask("referenceSelection")
60
61 def setRefObjLoader(self, refObjLoader):
62 """Set the reference object loader for the task.
63
64 Parameters
65 ----------
66 refObjLoader : `lsst.meas.algorithms.ReferenceObjectLoader`
67 An instance of a reference object loader.
68 """
69 self.refObjLoader = refObjLoader
70
71 def run(self, catalog, filterName=None, epoch=None):
72 """Load reference objects and match to them.
73
74 Parameters
75 ----------
77 Catalog to match.
78 filterName : `str`
79 Name of filter loading fluxes.
80 epoch : `astropy.time.Time` or `None`
81 Epoch to which to correct proper motion and parallax, or `None` to
82 not apply such corrections.
83
84 Returns
85 -------
86 result : `lsst.pipe.base.Struct`
87 Result struct with components:
88
89 ``matches``
90 Matched sources with associated reference
92 ``matchMeta``
93 Match metadata (`lsst.meas.astrom.MatchMetadata`).
94 """
95 if self.refObjLoader is None:
96 raise RuntimeError("Running matcher task with no refObjLoader set in __ini__ or setRefObjLoader")
97 circle = self.calculateCircle(catalog)
98 matchMeta = self.refObjLoader.getMetadataCircle(circle.center, circle.radius, filterName, epoch=epoch)
99 emptyResult = Struct(matches=[], matchMeta=matchMeta)
100 sourceSelection = self.sourceSelection.run(catalog)
101 if len(sourceSelection.sourceCat) == 0:
102 self.log.warning("No objects selected from %d objects in source catalog", len(catalog))
103 return emptyResult
104 refData = self.refObjLoader.loadSkyCircle(circle.center, circle.radius, filterName, epoch=epoch)
105 refCat = refData.refCat
106 refSelection = self.referenceSelection.run(refCat)
107 if len(refSelection.sourceCat) == 0:
108 self.log.warning("No objects selected from %d objects in reference catalog", len(refCat))
109 return emptyResult
110 matches = afwTable.matchRaDec(refSelection.sourceCat, sourceSelection.sourceCat,
111 self.config.matchRadius*arcseconds)
112 self.log.info("Matched %d from %d/%d input and %d/%d reference sources",
113 len(matches), len(sourceSelection.sourceCat), len(catalog),
114 len(refSelection.sourceCat), len(refCat))
115 return Struct(matches=matches, matchMeta=matchMeta, refCat=refCat, sourceSelection=sourceSelection,
116 refSelection=refSelection)
117
118 def calculateCircle(self, catalog):
119 """Calculate a circle enclosing the catalog.
120
121 Parameters
122 ----------
124 Catalog to encircle.
125
126 Returns
127 -------
128 result : `lsst.pipe.base.Struct`
129 Result struct with components:
130
131 ``center``
132 ICRS center coordinate (`lsst.afw.geom.SpherePoint`).
133 ``radius``
134 Radius of the circle (`lsst.geom.Angle`).
135 """
136 coordList = [src.getCoord() for src in catalog]
137 center = averageSpherePoint(coordList)
138 radius = max(center.separation(coord) for coord in coordList)
139 return Struct(center=center, radius=radius + self.config.matchRadius*arcseconds)
def run(self, catalog, filterName=None, epoch=None)
Definition: directMatch.py:71
def __init__(self, butler=None, refObjLoader=None, **kwargs)
Definition: directMatch.py:48
std::vector< Match< typename Cat1::Record, typename Cat2::Record > > matchRaDec(Cat1 const &cat1, Cat2 const &cat2, lsst::geom::Angle radius, MatchControl const &mc=MatchControl())