23 __all__ = [
'RefMatchConfig',
'RefMatchTask']
28 import lsst.pipe.base
as pipeBase
29 from lsst.meas.algorithms
import ScienceSourceSelectorTask, ReferenceSourceSelectorTask
30 from .matchOptimisticB
import MatchOptimisticBTask
31 from .display
import displayAstrometry
32 from .
import makeMatchStatistics
36 matcher = pexConfig.ConfigurableField(
37 target=MatchOptimisticBTask,
38 doc=
"reference object/source matcher",
40 matchDistanceSigma = pexConfig.RangeField(
41 doc=
"the maximum match distance is set to " 42 " mean_match_distance + matchDistanceSigma*std_dev_match_distance; " +
43 "ignored if not fitting a WCS",
48 sourceSelection = pexConfig.ConfigurableField(target=ScienceSourceSelectorTask,
49 doc=
"Selection of science sources")
50 referenceSelection = pexConfig.ConfigurableField(target=ReferenceSourceSelectorTask,
51 doc=
"Selection of reference sources")
63 """!Match an input source catalog with objects from a reference catalog 67 ConfigClass = RefMatchConfig
68 _DefaultName =
"calibrationBaseClass" 70 def __init__(self, refObjLoader, schema=None, **kwargs):
71 """!Construct a RefMatchTask 73 @param[in] refObjLoader A reference object loader object 74 @param[in] schema ignored; available for compatibility with an older astrometry task 75 @param[in] kwargs additional keyword arguments for pipe_base Task.\_\_init\_\_ 77 pipeBase.Task.__init__(self, **kwargs)
79 self.makeSubtask(
"matcher")
80 self.makeSubtask(
"sourceSelection")
81 self.makeSubtask(
"referenceSelection")
85 """!Load reference objects overlapping an exposure and match to sources detected on that exposure 87 @param[in] exposure exposure that the sources overlap 88 @param[in] sourceCat catalog of sources detected on the exposure (an lsst.afw.table.SourceCatalog) 90 @return an lsst.pipe.base.Struct with these fields: 91 - refCat reference object catalog of objects that overlap the exposure (with some margin) 92 (an lsst::afw::table::SimpleCatalog) 93 - matches a list of lsst.afw.table.ReferenceMatch 94 - matchMeta metadata needed to unpersist matches (an lsst.daf.base.PropertyList) 96 @note ignores config.matchDistanceSigma 103 sourceSelection = self.sourceSelection.run(sourceCat)
108 filterName=expMd.filterName,
112 refSelection = self.referenceSelection.run(loadRes.refCat)
117 filterName=expMd.filterName,
121 matchRes = self.matcher.matchObjectsToSources(
122 refCat=refSelection.sourceCat,
123 sourceCat=sourceSelection.sourceCat,
125 refFluxField=loadRes.fluxField,
126 match_tolerance=
None,
131 "Found %d matches with scatter = %0.3f +- %0.3f arcsec; " %
132 (len(matchRes.matches), distStats.distMean.asArcseconds(), distStats.distStdDev.asArcseconds())
136 frame = int(debug.frame)
138 refCat=refSelection.sourceCat,
139 sourceCat=sourceSelection.sourceCat,
140 matches=matchRes.matches,
147 return pipeBase.Struct(
148 refCat=loadRes.refCat,
149 refSelection=refSelection,
150 sourceSelection=sourceSelection,
151 matches=matchRes.matches,
155 def _computeMatchStatsOnSky(self, matchList):
156 """Compute on-sky radial distance statistics for a match list 158 @param[in] matchList list of matches between reference object and sources; 159 the distance field is the only field read and it must be set to distance in radians 161 @return a pipe_base Struct containing these fields: 162 - distMean clipped mean of on-sky radial separation 163 - distStdDev clipped standard deviation of on-sky radial separation 164 - maxMatchDist distMean + self.config.matchDistanceSigma*distStdDev 167 distMean = distStatsInRadians.getValue(afwMath.MEANCLIP)*afwGeom.radians
168 distStdDev = distStatsInRadians.getValue(afwMath.STDEVCLIP)*afwGeom.radians
169 return pipeBase.Struct(
171 distStdDev=distStdDev,
172 maxMatchDist=distMean + self.config.matchDistanceSigma*distStdDev,
175 def _getExposureMetadata(self, exposure):
176 """!Extract metadata from an exposure 178 @return an lsst.pipe.base.Struct containing the following exposure metadata: 179 - bbox: parent bounding box 180 - wcs: WCS (an lsst.afw.geom.Wcs) 181 - calib calibration (an lsst.afw.image.Calib), or None if unknown 182 - filterName: name of filter, or None if unknown 184 exposureInfo = exposure.getInfo()
185 filterName = exposureInfo.getFilter().getName()
or None 186 if filterName ==
"_unknown_":
188 return pipeBase.Struct(
189 bbox=exposure.getBBox(),
190 wcs=exposureInfo.getWcs(),
191 calib=exposureInfo.getCalib()
if exposureInfo.hasCalib()
else None,
192 filterName=filterName,
def _computeMatchStatsOnSky(self, matchList)
def __init__(self, refObjLoader, schema=None, kwargs)
Construct a RefMatchTask.
def _getExposureMetadata(self, exposure)
Extract metadata from an exposure.
Match an input source catalog with objects from a reference catalog.
def displayAstrometry(refCat=None, sourceCat=None, distortedCentroidKey=None, bbox=None, exposure=None, matches=None, frame=1, title="", pause=True)
def loadAndMatch(self, exposure, sourceCat)
Load reference objects overlapping an exposure and match to sources detected on that exposure...