1 from __future__
import absolute_import, division, print_function
2 from builtins
import range
3 from builtins
import object
10 from .setMatchDistance
import setMatchDistance
11 from .astromLib
import matchOptimisticB, MatchOptimisticBControl
13 __all__ = [
"MatchOptimisticBTask",
"MatchOptimisticBConfig"]
17 """Configuration for MatchOptimisticBTask
19 maxMatchDistArcSec = pexConfig.RangeField(
20 doc=
"Maximum separation between reference objects and sources "
21 "beyond which they will not be considered a match (arcsec)",
26 numBrightStars = pexConfig.RangeField(
27 doc=
"Number of bright stars to use",
32 minMatchedPairs = pexConfig.RangeField(
33 doc=
"Minimum number of matched pairs; see also minFracMatchedPairs",
38 minFracMatchedPairs = pexConfig.RangeField(
39 doc=
"Minimum number of matched pairs as a fraction of the smaller of "
40 "the number of reference stars or the number of good sources; "
41 "the actual minimum is the smaller of this value or minMatchedPairs",
47 maxOffsetPix = pexConfig.RangeField(
48 doc=
"Maximum allowed shift of WCS, due to matching (pixel)",
53 maxRotationDeg = pexConfig.RangeField(
54 doc=
"Rotation angle allowed between sources and position reference objects (degrees)",
59 allowedNonperpDeg = pexConfig.RangeField(
60 doc=
"Allowed non-perpendicularity of x and y (degree)",
65 numPointsForShape = pexConfig.Field(
66 doc=
"number of points to define a shape for matching",
70 maxDeterminant = pexConfig.Field(
71 doc=
"maximum determinant of linear transformation matrix for a usable solution",
75 sourceSelector = sourceSelectorRegistry.makeField(
76 doc=
"How to select sources for cross-matching",
82 sourceSelector.setDefaults()
94 """!Match sources to reference objects
96 @anchor MatchOptimisticBTask_
98 @section meas_astrom_matchOptimisticB_Contents Contents
100 - @ref meas_astrom_matchOptimisticB_Purpose
101 - @ref meas_astrom_matchOptimisticB_Initialize
102 - @ref meas_astrom_matchOptimisticB_IO
103 - @ref meas_astrom_matchOptimisticB_Config
104 - @ref meas_astrom_matchOptimisticB_Example
105 - @ref meas_astrom_matchOptimisticB_Debug
107 @section meas_astrom_matchOptimisticB_Purpose Description
109 Match sources to reference objects. This is often done as a preliminary step to fitting an astrometric
110 or photometric solution. For details about the matching algorithm see matchOptimisticB.h
112 @section meas_astrom_matchOptimisticB_Initialize Task initialisation
114 @copydoc \_\_init\_\_
116 @section meas_astrom_matchOptimisticB_IO Invoking the Task
118 @copydoc matchObjectsToSources
120 @section meas_astrom_matchOptimisticB_Config Configuration parameters
122 See @ref MatchOptimisticBConfig
124 To modify the tests for usable sources and good sources, subclass SourceInfo and
125 set MatchOptimisticBTask.SourceInfoClass to your subclass.
127 @section meas_astrom_matchOptimisticB_Example A complete example of using MatchOptimisticBTask
129 MatchOptimisticBTask is a subtask of AstrometryTask, which is called by PhotoCalTask.
130 See \ref meas_photocal_photocal_Example.
132 @section meas_astrom_matchOptimisticB_Debug Debug variables
134 The @link lsst.pipe.base.cmdLineTask.CmdLineTask command line task@endlink interface supports a
135 flag @c -d to import @b debug.py from your @c PYTHONPATH; see @ref baseDebug for more about
138 The available variables in MatchOptimisticBTask are:
140 <DT> @c verbose (bool)
141 <DD> If True then the matcher prints debug messages to stdout
144 To investigate the @ref meas_astrom_matchOptimisticB_Debug, put something like
148 debug = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
149 if name == "lsst.pipe.tasks.astrometry":
154 lsstDebug.Info = DebugInfo
156 into your debug.py file and run this task with the @c --debug flag.
158 ConfigClass = MatchOptimisticBConfig
159 _DefaultName =
"matchObjectsToSources"
162 pipeBase.Task.__init__(self, **kwargs)
163 self.makeSubtask(
"sourceSelector")
166 """Extra filtering pass; subclass if desired
172 """!Match sources to position reference stars
174 @param[in] refCat catalog of reference objects that overlap the exposure; reads fields for:
176 - the specified flux field
177 @param[in] sourceCat catalog of sources found on an exposure; reads fields for:
182 - aperture flux, if found, else PSF flux
183 @param[in] wcs estimated WCS
184 @param[in] refFluxField field of refCat to use for flux
185 @param[in] maxMatchDist maximum on-sky distance between reference objects and sources
186 (an lsst.afw.geom.Angle); if specified then the smaller of config.maxMatchDistArcSec or
187 maxMatchDist is used; if None then config.maxMatchDistArcSec is used
188 @return an lsst.pipe.base.Struct with fields:
189 - matches a list of matches, each instance of lsst.afw.table.ReferenceMatch
190 - usableSourcCat a catalog of sources potentially usable for matching.
191 For this fitter usable sources include unresolved sources not too near the edge.
192 It includes saturated sources, even those these are removed from the final match list,
193 because saturated sources may be used to determine the match list.
198 preNumObj = len(refCat)
200 numRefObj = len(refCat)
203 self.log.info(
"filterStars purged %d reference stars, leaving %d stars" %
204 (preNumObj - numRefObj, numRefObj))
207 numSources = len(sourceCat)
208 selectedSources = self.sourceSelector.selectSources(sourceCat)
209 usableSourceCat = selectedSources.sourceCat
210 numUsableSources = len(usableSourceCat)
211 self.log.info(
"Purged %d unusable sources, leaving %d usable sources" %
212 (numSources - numUsableSources, numUsableSources))
214 if len(usableSourceCat) == 0:
215 raise pipeBase.TaskError(
"No sources are usable")
219 minMatchedPairs = min(self.config.minMatchedPairs,
220 int(self.config.minFracMatchedPairs * min([len(refCat), len(usableSourceCat)])))
225 sourceCat=usableSourceCat,
227 refFluxField=refFluxField,
228 numUsableSources=numUsableSources,
229 minMatchedPairs=minMatchedPairs,
230 maxMatchDist=maxMatchDist,
231 sourceFluxField=self.sourceSelector.fluxField,
232 verbose=debug.verbose,
238 for match
in usableMatches:
241 matches.append(match)
243 self.log.debug(
"Found %d usable matches, of which %d had good sources",
244 len(usableMatches), len(matches))
246 if len(matches) == 0:
247 raise RuntimeError(
"Unable to match sources")
249 self.log.info(
"Matched %d sources" % len(matches))
250 if len(matches) < minMatchedPairs:
251 self.log.warn(
"Number of matches is smaller than request")
253 return pipeBase.Struct(
255 usableSourceCat=usableSourceCat,
259 self.
edgeKey = schema[
"base_PixelFlags_flag_edge"].asKey()
265 This is a hard coded version of the isGood flag from the old SourceInfo class that used to be
266 part of this class. This is done current as the API for sourceSelector does not currently
269 return (
not source.get(self.
edgeKey)
and
274 def _doMatch(self, refCat, sourceCat, wcs, refFluxField, numUsableSources, minMatchedPairs,
275 maxMatchDist, sourceFluxField, verbose):
276 """!Implementation of matching sources to position reference stars
278 Unlike matchObjectsToSources, this method does not check if the sources are suitable.
280 @param[in] refCat catalog of position reference stars that overlap an exposure
281 @param[in] sourceCat catalog of sources found on the exposure
282 @param[in] wcs estimated WCS of exposure
283 @param[in] refFluxField field of refCat to use for flux
284 @param[in] numUsableSources number of usable sources (sources with known centroid
285 that are not near the edge, but may be saturated)
286 @param[in] minMatchedPairs minimum number of matches
287 @param[in] maxMatchDist maximum on-sky distance between reference objects and sources
288 (an lsst.afw.geom.Angle); if specified then the smaller of config.maxMatchDistArcSec or
289 maxMatchDist is used; if None then config.maxMatchDistArcSec is used
290 @param[in] sourceInfo SourceInfo for the sourceCat
291 @param[in] verbose true to print diagnostic information to std::cout
293 @return a list of matches, an instance of lsst.afw.table.ReferenceMatch
295 numSources = len(sourceCat)
296 posRefBegInd = numUsableSources - numSources
297 if maxMatchDist
is None:
298 maxMatchDistArcSec = self.config.maxMatchDistArcSec
300 maxMatchDistArcSec = min(maxMatchDist.asArcseconds(), self.config.maxMatchDistArcSec)
301 configMatchDistPix = maxMatchDistArcSec/wcs.pixelScale().asArcseconds()
304 matchControl.refFluxField = refFluxField
305 matchControl.sourceFluxField = sourceFluxField
306 matchControl.numBrightStars = self.config.numBrightStars
307 matchControl.minMatchedPairs = self.config.minMatchedPairs
308 matchControl.maxOffsetPix = self.config.maxOffsetPix
309 matchControl.numPointsForShape = self.config.numPointsForShape
310 matchControl.maxDeterminant = self.config.maxDeterminant
312 for maxRotInd
in range(4):
313 matchControl.maxRotationDeg = self.config.maxRotationDeg * math.pow(2.0, 0.5*maxRotInd)
314 for matchRadInd
in range(3):
315 matchControl.matchingAllowancePix = configMatchDistPix * math.pow(1.25, matchRadInd)
317 for angleDiffInd
in range(3):
318 matchControl.allowedNonperpDeg = self.config.allowedNonperpDeg*(angleDiffInd+1)
327 if matches
is not None and len(matches) > 0:
Match sources to reference objects.
def matchObjectsToSources
Match 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 _doMatch
Implementation of matching sources to position reference stars.