1 from __future__
import absolute_import, division, print_function
3 __all__ = [
"matchOptimisticB",
"MatchOptimisticBTask",
"MatchOptimisticBConfig",
6 from builtins
import range
7 from builtins
import object
12 from lsst.afw.table
import Point2DKey
13 import lsst.pex.config
as pexConfig
14 import lsst.pipe.base
as pipeBase
15 from lsst.meas.algorithms.sourceSelector
import sourceSelectorRegistry
17 from ..setMatchDistance
import setMatchDistance
18 from .
import matchOptimisticB, MatchOptimisticBControl
22 """ Stores match tolerances for use in AstrometryTask and later
23 iterations of the matcher.
27 maxMatchDist : lsst.afw.geom.Angle
31 """ MatchOptimsiticBTask relies on a maximum distance for matching
32 set by either the default in MatchOptimisticBConfig or the 2 sigma
33 scatter found after AstrometryTask has fit for a wcs.
39 """Configuration for MatchOptimisticBTask
41 maxMatchDistArcSec = pexConfig.RangeField(
42 doc=
"Maximum separation between reference objects and sources "
43 "beyond which they will not be considered a match (arcsec)",
48 numBrightStars = pexConfig.RangeField(
49 doc=
"Number of bright stars to use",
54 minMatchedPairs = pexConfig.RangeField(
55 doc=
"Minimum number of matched pairs; see also minFracMatchedPairs",
60 minFracMatchedPairs = pexConfig.RangeField(
61 doc=
"Minimum number of matched pairs as a fraction of the smaller of "
62 "the number of reference stars or the number of good sources; "
63 "the actual minimum is the smaller of this value or minMatchedPairs",
69 maxOffsetPix = pexConfig.RangeField(
70 doc=
"Maximum allowed shift of WCS, due to matching (pixel)",
75 maxRotationDeg = pexConfig.RangeField(
76 doc=
"Rotation angle allowed between sources and position reference objects (degrees)",
81 allowedNonperpDeg = pexConfig.RangeField(
82 doc=
"Allowed non-perpendicularity of x and y (degree)",
87 numPointsForShape = pexConfig.Field(
88 doc=
"number of points to define a shape for matching",
92 maxDeterminant = pexConfig.Field(
93 doc=
"maximum determinant of linear transformation matrix for a usable solution",
97 sourceSelector = sourceSelectorRegistry.makeField(
98 doc=
"How to select sources for cross-matching",
104 sourceSelector.setDefaults()
117 """!Match sources to reference objects
119 @anchor MatchOptimisticBTask_
121 @section meas_astrom_matchOptimisticB_Contents Contents
123 - @ref meas_astrom_matchOptimisticB_Purpose
124 - @ref meas_astrom_matchOptimisticB_Initialize
125 - @ref meas_astrom_matchOptimisticB_IO
126 - @ref meas_astrom_matchOptimisticB_Config
127 - @ref meas_astrom_matchOptimisticB_Example
128 - @ref meas_astrom_matchOptimisticB_Debug
130 @section meas_astrom_matchOptimisticB_Purpose Description
132 Match sources to reference objects. This is often done as a preliminary step to fitting an astrometric
133 or photometric solution. For details about the matching algorithm see matchOptimisticB.h
135 @section meas_astrom_matchOptimisticB_Initialize Task initialisation
137 @copydoc \_\_init\_\_
139 @section meas_astrom_matchOptimisticB_IO Invoking the Task
141 @copydoc matchObjectsToSources
143 @section meas_astrom_matchOptimisticB_Config Configuration parameters
145 See @ref MatchOptimisticBConfig
147 To modify how usable sources are selected, specify a different source
148 selector in `config.sourceSelector`.
150 @section meas_astrom_matchOptimisticB_Example A complete example of using MatchOptimisticBTask
152 MatchOptimisticBTask is a subtask of AstrometryTask, which is called by PhotoCalTask.
153 See \ref pipe_tasks_photocal_Example.
155 @section meas_astrom_matchOptimisticB_Debug Debug variables
157 The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink interface supports a
158 flag @c -d to import @b debug.py from your @c PYTHONPATH; see @ref baseDebug for more about
161 The available variables in MatchOptimisticBTask are:
163 <DT> @c verbose (bool)
164 <DD> If True then the matcher prints debug messages to stdout
167 To investigate the @ref meas_astrom_matchOptimisticB_Debug, put something like
171 debug = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
172 if name == "lsst.pipe.tasks.astrometry":
177 lsstDebug.Info = DebugInfo
179 into your debug.py file and run this task with the @c --debug flag.
181 ConfigClass = MatchOptimisticBConfig
182 _DefaultName =
"matchObjectsToSources"
185 pipeBase.Task.__init__(self, **kwargs)
186 self.makeSubtask(
"sourceSelector")
189 """Extra filtering pass; subclass if desired
195 match_tolerance=
None):
196 """!Match sources to position reference stars
198 @param[in] refCat catalog of reference objects that overlap the exposure; reads fields for:
200 - the specified flux field
201 @param[in] sourceCat catalog of sources found on an exposure; reads fields for:
206 - aperture flux, if found, else PSF flux
207 @param[in] wcs estimated WCS
208 @param[in] refFluxField field of refCat to use for flux
209 @param[in] match_tolerance a MatchTolerance object for specifying
210 tolerances. Must at minimum contain a lsst.afw.geom.Angle
211 called maxMatchDist that communicates state between AstrometryTask
212 and the matcher Task.
213 @return an lsst.pipe.base.Struct with fields:
214 - matches a list of matches, each instance of lsst.afw.table.ReferenceMatch
215 - usableSourcCat a catalog of sources potentially usable for matching.
216 For this fitter usable sources include unresolved sources not too near the edge.
217 It includes saturated sources, even those these are removed from the final match list,
218 because saturated sources may be used to determine the match list.
221 debug = lsstDebug.Info(__name__)
223 preNumObj = len(refCat)
225 numRefObj = len(refCat)
228 self.log.info(
"filterStars purged %d reference stars, leaving %d stars" %
229 (preNumObj - numRefObj, numRefObj))
231 if match_tolerance
is None:
235 numSources = len(sourceCat)
236 selectedSources = self.sourceSelector.selectSources(sourceCat)
237 usableSourceCat = selectedSources.sourceCat
238 numUsableSources = len(usableSourceCat)
239 self.log.info(
"Purged %d unusable sources, leaving %d usable sources" %
240 (numSources - numUsableSources, numUsableSources))
242 if len(usableSourceCat) == 0:
243 raise pipeBase.TaskError(
"No sources are usable")
247 minMatchedPairs = min(self.config.minMatchedPairs,
248 int(self.config.minFracMatchedPairs * min([len(refCat), len(usableSourceCat)])))
253 sourceCat=usableSourceCat,
255 refFluxField=refFluxField,
256 numUsableSources=numUsableSources,
257 minMatchedPairs=minMatchedPairs,
258 maxMatchDist=match_tolerance.maxMatchDist,
259 sourceFluxField=self.sourceSelector.fluxField,
260 verbose=debug.verbose,
266 for match
in usableMatches:
269 matches.append(match)
271 self.log.debug(
"Found %d usable matches, of which %d had good sources",
272 len(usableMatches), len(matches))
274 if len(matches) == 0:
275 raise RuntimeError(
"Unable to match sources")
277 self.log.info(
"Matched %d sources" % len(matches))
278 if len(matches) < minMatchedPairs:
279 self.log.warn(
"Number of matches is smaller than request")
281 return pipeBase.Struct(
283 usableSourceCat=usableSourceCat,
284 match_tolerance=match_tolerance,
287 def _getIsGoodKeys(self, schema):
288 self.
edgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
292 def _isGoodTest(self, source):
294 This is a hard coded version of the isGood flag from the old SourceInfo class that used to be
295 part of this class. This is done current as the API for sourceSelector does not currently
298 return (
not source.get(self.
edgeKey)
and
303 def _doMatch(self, refCat, sourceCat, wcs, refFluxField, numUsableSources, minMatchedPairs,
304 maxMatchDist, sourceFluxField, verbose):
305 """!Implementation of matching sources to position reference stars
307 Unlike matchObjectsToSources, this method does not check if the sources are suitable.
309 @param[in] refCat catalog of position reference stars that overlap an exposure
310 @param[in] sourceCat catalog of sources found on the exposure
311 @param[in] wcs estimated WCS of exposure
312 @param[in] refFluxField field of refCat to use for flux
313 @param[in] numUsableSources number of usable sources (sources with known centroid
314 that are not near the edge, but may be saturated)
315 @param[in] minMatchedPairs minimum number of matches
316 @param[in] maxMatchDist maximum on-sky distance between reference objects and sources
317 (an lsst.afw.geom.Angle); if specified then the smaller of config.maxMatchDistArcSec or
318 maxMatchDist is used; if None then config.maxMatchDistArcSec is used
319 @param[in] sourceFluxField Name of flux field in source catalog
320 @param[in] verbose true to print diagnostic information to std::cout
322 @return a list of matches, an instance of lsst.afw.table.ReferenceMatch
324 numSources = len(sourceCat)
325 posRefBegInd = numUsableSources - numSources
326 if maxMatchDist
is None:
327 maxMatchDistArcSec = self.config.maxMatchDistArcSec
329 maxMatchDistArcSec = min(maxMatchDist.asArcseconds(), self.config.maxMatchDistArcSec)
330 configMatchDistPix = maxMatchDistArcSec/wcs.pixelScale().asArcseconds()
333 matchControl.refFluxField = refFluxField
334 matchControl.sourceFluxField = sourceFluxField
335 matchControl.numBrightStars = self.config.numBrightStars
336 matchControl.minMatchedPairs = self.config.minMatchedPairs
337 matchControl.maxOffsetPix = self.config.maxOffsetPix
338 matchControl.numPointsForShape = self.config.numPointsForShape
339 matchControl.maxDeterminant = self.config.maxDeterminant
341 for maxRotInd
in range(4):
342 matchControl.maxRotationDeg = self.config.maxRotationDeg * math.pow(2.0, 0.5*maxRotInd)
343 for matchRadInd
in range(3):
344 matchControl.matchingAllowancePix = configMatchDistPix * math.pow(1.25, matchRadInd)
346 for angleDiffInd
in range(3):
347 matchControl.allowedNonperpDeg = self.config.allowedNonperpDeg*(angleDiffInd+1)
356 if matches
is not None and len(matches) > 0:
def _doMatch
Implementation of matching sources to position reference stars.
lsst::afw::table::ReferenceMatchVector matchOptimisticB(lsst::afw::table::SimpleCatalog const &posRefCat, lsst::afw::table::SourceCatalog const &sourceCat, MatchOptimisticBControl const &control, afw::image::Wcs const &wcs, int posRefBegInd=0, bool verbose=false)
Match sources to stars in a position reference catalog using optimistic pattern matching B...
def matchObjectsToSources
Match sources to position reference stars.
Match sources to reference objects.