2 __all__ = [
"matchOptimisticB",
"MatchOptimisticBTask",
"MatchOptimisticBConfig",
8 import lsst.pipe.base
as pipeBase
9 from lsst.meas.algorithms.sourceSelector
import sourceSelectorRegistry
11 from ..setMatchDistance
import setMatchDistance
12 from .
import matchOptimisticB, MatchOptimisticBControl
16 """ Stores match tolerances for use in AstrometryTask and later 17 iterations of the matcher. 21 maxMatchDist : lsst.afw.geom.Angle 25 """ MatchOptimsiticBTask relies on a maximum distance for matching 26 set by either the default in MatchOptimisticBConfig or the 2 sigma 27 scatter found after AstrometryTask has fit for a wcs. 33 """Configuration for MatchOptimisticBTask 35 maxMatchDistArcSec = pexConfig.RangeField(
36 doc=
"Maximum separation between reference objects and sources " 37 "beyond which they will not be considered a match (arcsec)",
42 numBrightStars = pexConfig.RangeField(
43 doc=
"Number of bright stars to use",
48 minMatchedPairs = pexConfig.RangeField(
49 doc=
"Minimum number of matched pairs; see also minFracMatchedPairs",
54 minFracMatchedPairs = pexConfig.RangeField(
55 doc=
"Minimum number of matched pairs as a fraction of the smaller of " 56 "the number of reference stars or the number of good sources; " 57 "the actual minimum is the smaller of this value or minMatchedPairs",
63 maxOffsetPix = pexConfig.RangeField(
64 doc=
"Maximum allowed shift of WCS, due to matching (pixel). " 65 "When changing this value, the LoadReferenceObjectsConfig.pixelMargin should also be updated.",
70 maxRotationDeg = pexConfig.RangeField(
71 doc=
"Rotation angle allowed between sources and position reference objects (degrees)",
76 allowedNonperpDeg = pexConfig.RangeField(
77 doc=
"Allowed non-perpendicularity of x and y (degree)",
82 numPointsForShape = pexConfig.Field(
83 doc=
"number of points to define a shape for matching",
87 maxDeterminant = pexConfig.Field(
88 doc=
"maximum determinant of linear transformation matrix for a usable solution",
92 sourceSelector = sourceSelectorRegistry.makeField(
93 doc=
"How to select sources for cross-matching",
99 sourceSelector.setDefaults()
112 """!Match sources to reference objects 114 @anchor MatchOptimisticBTask_ 116 @section meas_astrom_matchOptimisticB_Contents Contents 118 - @ref meas_astrom_matchOptimisticB_Purpose 119 - @ref meas_astrom_matchOptimisticB_Initialize 120 - @ref meas_astrom_matchOptimisticB_IO 121 - @ref meas_astrom_matchOptimisticB_Config 122 - @ref meas_astrom_matchOptimisticB_Example 123 - @ref meas_astrom_matchOptimisticB_Debug 125 @section meas_astrom_matchOptimisticB_Purpose Description 127 Match sources to reference objects. This is often done as a preliminary step to fitting an astrometric 128 or photometric solution. For details about the matching algorithm see matchOptimisticB.h 130 @section meas_astrom_matchOptimisticB_Initialize Task initialisation 132 @copydoc \_\_init\_\_ 134 @section meas_astrom_matchOptimisticB_IO Invoking the Task 136 @copydoc matchObjectsToSources 138 @section meas_astrom_matchOptimisticB_Config Configuration parameters 140 See @ref MatchOptimisticBConfig 142 To modify how usable sources are selected, specify a different source 143 selector in `config.sourceSelector`. 145 @section meas_astrom_matchOptimisticB_Example A complete example of using MatchOptimisticBTask 147 MatchOptimisticBTask is a subtask of AstrometryTask, which is called by PhotoCalTask. 148 See \ref pipe_tasks_photocal_Example. 150 @section meas_astrom_matchOptimisticB_Debug Debug variables 152 The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink interface supports a 153 flag @c -d to import @b debug.py from your @c PYTHONPATH; see @ref baseDebug for more about 156 The available variables in MatchOptimisticBTask are: 158 <DT> @c verbose (bool) 159 <DD> If True then the matcher prints debug messages to stdout 162 To investigate the @ref meas_astrom_matchOptimisticB_Debug, put something like 166 debug = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively 167 if name == "lsst.pipe.tasks.astrometry": 172 lsstDebug.Info = DebugInfo 174 into your debug.py file and run this task with the @c --debug flag. 176 ConfigClass = MatchOptimisticBConfig
177 _DefaultName =
"matchObjectsToSources" 180 pipeBase.Task.__init__(self, **kwargs)
181 self.makeSubtask(
"sourceSelector")
184 """Extra filtering pass; subclass if desired 190 match_tolerance=None):
191 """!Match sources to position reference stars 193 @param[in] refCat catalog of reference objects that overlap the exposure; reads fields for: 195 - the specified flux field 196 @param[in] sourceCat catalog of sources found on an exposure; reads fields for: 201 - aperture flux, if found, else PSF flux 202 @param[in] wcs estimated WCS 203 @param[in] refFluxField field of refCat to use for flux 204 @param[in] match_tolerance a MatchTolerance object for specifying 205 tolerances. Must at minimum contain a lsst.afw.geom.Angle 206 called maxMatchDist that communicates state between AstrometryTask 207 and the matcher Task. 208 @return an lsst.pipe.base.Struct with fields: 209 - matches a list of matches, each instance of lsst.afw.table.ReferenceMatch 210 - usableSourcCat a catalog of sources potentially usable for matching. 211 For this fitter usable sources include unresolved sources not too near the edge. 212 It includes saturated sources, even those these are removed from the final match list, 213 because saturated sources may be used to determine the match list. 218 preNumObj = len(refCat)
220 numRefObj = len(refCat)
223 self.log.info(
"filterStars purged %d reference stars, leaving %d stars" %
224 (preNumObj - numRefObj, numRefObj))
226 if match_tolerance
is None:
230 numSources = len(sourceCat)
231 selectedSources = self.sourceSelector.selectSources(sourceCat)
232 usableSourceCat = selectedSources.sourceCat
233 numUsableSources = len(usableSourceCat)
234 self.log.info(
"Purged %d unusable sources, leaving %d usable sources" %
235 (numSources - numUsableSources, numUsableSources))
237 if len(usableSourceCat) == 0:
238 raise pipeBase.TaskError(
"No sources are usable")
242 minMatchedPairs = min(self.config.minMatchedPairs,
243 int(self.config.minFracMatchedPairs * min([len(refCat), len(usableSourceCat)])))
248 sourceCat=usableSourceCat,
250 refFluxField=refFluxField,
251 numUsableSources=numUsableSources,
252 minMatchedPairs=minMatchedPairs,
253 maxMatchDist=match_tolerance.maxMatchDist,
254 sourceFluxField=self.sourceSelector.fluxField,
255 verbose=debug.verbose,
261 for match
in usableMatches:
264 matches.append(match)
266 self.log.debug(
"Found %d usable matches, of which %d had good sources",
267 len(usableMatches), len(matches))
269 if len(matches) == 0:
270 raise RuntimeError(
"Unable to match sources")
272 self.log.info(
"Matched %d sources" % len(matches))
273 if len(matches) < minMatchedPairs:
274 self.log.warn(
"Number of matches is smaller than request")
276 return pipeBase.Struct(
278 usableSourceCat=usableSourceCat,
279 match_tolerance=match_tolerance,
282 def _getIsGoodKeys(self, schema):
283 self.
edgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
287 def _isGoodTest(self, source):
289 This is a hard coded version of the isGood flag from the old SourceInfo class that used to be 290 part of this class. This is done current as the API for sourceSelector does not currently 293 return (
not source.get(self.
edgeKey)
and 298 def _doMatch(self, refCat, sourceCat, wcs, refFluxField, numUsableSources, minMatchedPairs,
299 maxMatchDist, sourceFluxField, verbose):
300 """!Implementation of matching sources to position reference stars 302 Unlike matchObjectsToSources, this method does not check if the sources are suitable. 304 @param[in] refCat catalog of position reference stars that overlap an exposure 305 @param[in] sourceCat catalog of sources found on the exposure 306 @param[in] wcs estimated WCS of exposure 307 @param[in] refFluxField field of refCat to use for flux 308 @param[in] numUsableSources number of usable sources (sources with known centroid 309 that are not near the edge, but may be saturated) 310 @param[in] minMatchedPairs minimum number of matches 311 @param[in] maxMatchDist maximum on-sky distance between reference objects and sources 312 (an lsst.afw.geom.Angle); if specified then the smaller of config.maxMatchDistArcSec or 313 maxMatchDist is used; if None then config.maxMatchDistArcSec is used 314 @param[in] sourceFluxField Name of flux field in source catalog 315 @param[in] verbose true to print diagnostic information to std::cout 317 @return a list of matches, an instance of lsst.afw.table.ReferenceMatch 319 numSources = len(sourceCat)
320 posRefBegInd = numUsableSources - numSources
321 if maxMatchDist
is None:
322 maxMatchDistArcSec = self.config.maxMatchDistArcSec
324 maxMatchDistArcSec = min(maxMatchDist.asArcseconds(), self.config.maxMatchDistArcSec)
325 configMatchDistPix = maxMatchDistArcSec/wcs.getPixelScale().asArcseconds()
327 matchControl = MatchOptimisticBControl()
328 matchControl.refFluxField = refFluxField
329 matchControl.sourceFluxField = sourceFluxField
330 matchControl.numBrightStars = self.config.numBrightStars
331 matchControl.minMatchedPairs = self.config.minMatchedPairs
332 matchControl.maxOffsetPix = self.config.maxOffsetPix
333 matchControl.numPointsForShape = self.config.numPointsForShape
334 matchControl.maxDeterminant = self.config.maxDeterminant
336 for maxRotInd
in range(4):
337 matchControl.maxRotationDeg = self.config.maxRotationDeg * math.pow(2.0, 0.5*maxRotInd)
338 for matchRadInd
in range(3):
339 matchControl.matchingAllowancePix = configMatchDistPix * math.pow(1.25, matchRadInd)
341 for angleDiffInd
in range(3):
342 matchControl.allowedNonperpDeg = self.config.allowedNonperpDeg*(angleDiffInd+1)
351 if matches
is not None and len(matches) > 0:
def _isGoodTest(self, source)
def _doMatch(self, refCat, sourceCat, wcs, refFluxField, numUsableSources, minMatchedPairs, maxMatchDist, sourceFluxField, verbose)
Implementation of matching sources to position reference stars.
def filterStars(self, refCat)
def __init__(self, kwargs)
def setMatchDistance(matches)
lsst::afw::table::ReferenceMatchVector matchOptimisticB(lsst::afw::table::SimpleCatalog const &posRefCat, lsst::afw::table::SourceCatalog const &sourceCat, MatchOptimisticBControl const &control, afw::geom::SkyWcs const &wcs, int posRefBegInd=0, bool verbose=false)
Match sources to stars in a position reference catalog using optimistic pattern matching B...
def __init__(self, maxMatchDist=None)
def matchObjectsToSources(self, refCat, sourceCat, wcs, refFluxField, match_tolerance=None)
Match sources to position reference stars.
Match sources to reference objects.
def _getIsGoodKeys(self, schema)