LSST Applications  21.0.0-147-g0e635eb1+1acddb5be5,22.0.0+052faf71bd,22.0.0+1ea9a8b2b2,22.0.0+6312710a6c,22.0.0+729191ecac,22.0.0+7589c3a021,22.0.0+9f079a9461,22.0.1-1-g7d6de66+b8044ec9de,22.0.1-1-g87000a6+536b1ee016,22.0.1-1-g8e32f31+6312710a6c,22.0.1-10-gd060f87+016f7cdc03,22.0.1-12-g9c3108e+df145f6f68,22.0.1-16-g314fa6d+c825727ab8,22.0.1-19-g93a5c75+d23f2fb6d8,22.0.1-19-gb93eaa13+aab3ef7709,22.0.1-2-g8ef0a89+b8044ec9de,22.0.1-2-g92698f7+9f079a9461,22.0.1-2-ga9b0f51+052faf71bd,22.0.1-2-gac51dbf+052faf71bd,22.0.1-2-gb66926d+6312710a6c,22.0.1-2-gcb770ba+09e3807989,22.0.1-20-g32debb5+b8044ec9de,22.0.1-23-gc2439a9a+fb0756638e,22.0.1-3-g496fd5d+09117f784f,22.0.1-3-g59f966b+1e6ba2c031,22.0.1-3-g849a1b8+f8b568069f,22.0.1-3-gaaec9c0+c5c846a8b1,22.0.1-32-g5ddfab5d3+60ce4897b0,22.0.1-4-g037fbe1+64e601228d,22.0.1-4-g8623105+b8044ec9de,22.0.1-5-g096abc9+d18c45d440,22.0.1-5-g15c806e+57f5c03693,22.0.1-7-gba73697+57f5c03693,master-g6e05de7fdc+c1283a92b8,master-g72cdda8301+729191ecac,w.2021.39
LSST Data Management Base Package
Public Member Functions | Public Attributes | Static Public Attributes | List of all members
lsst.meas.astrom.astrometry.AstrometryTask Class Reference
Inheritance diagram for lsst.meas.astrom.astrometry.AstrometryTask:
lsst.meas.astrom.ref_match.RefMatchTask

Public Member Functions

def __init__ (self, refObjLoader, schema=None, **kwargs)
 
def run (self, sourceCat, exposure)
 
def solve (self, exposure, sourceCat)
 
def setRefObjLoader (self, refObjLoader)
 
def loadAndMatch (self, exposure, sourceCat)
 

Public Attributes

 usedKey
 
 refObjLoader
 

Static Public Attributes

 ConfigClass = AstrometryConfig
 

Detailed Description

Match an input source catalog with objects from a reference catalog and
solve for the WCS.

This task is broken into two main subasks: matching and WCS fitting which
are very interactive. The matching here can be considered in part a first
pass WCS fitter due to the fitter's sensitivity to outliers.

Parameters
----------
refObjLoader : `lsst.meas.algorithms.ReferenceLoader`
    A reference object loader object
schema : `lsst.afw.table.Schema`
    Used to set "calib_astrometry_used" flag in output source catalog.
**kwargs
    additional keyword arguments for pipe_base
    `lsst.pipe.base.Task.__init__`

Definition at line 89 of file astrometry.py.

Constructor & Destructor Documentation

◆ __init__()

def lsst.meas.astrom.astrometry.AstrometryTask.__init__ (   self,
  refObjLoader,
  schema = None,
**  kwargs 
)

Definition at line 110 of file astrometry.py.

110  def __init__(self, refObjLoader, schema=None, **kwargs):
111  RefMatchTask.__init__(self, refObjLoader, **kwargs)
112 
113  if schema is not None:
114  self.usedKey = schema.addField("calib_astrometry_used", type="Flag",
115  doc="set if source was used in astrometric calibration")
116  else:
117  self.usedKey = None
118 
119  self.makeSubtask("wcsFitter")
120 

Member Function Documentation

◆ loadAndMatch()

def lsst.meas.astrom.ref_match.RefMatchTask.loadAndMatch (   self,
  exposure,
  sourceCat 
)
inherited
Load reference objects overlapping an exposure and match to sources
detected on that exposure.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    exposure that the sources overlap
sourceCat : `lsst.afw.table.SourceCatalog.`
    catalog of sources detected on the exposure

Returns
-------
result : `lsst.pipe.base.Struct`
    Result struct with Components:

    - ``refCat`` : reference object catalog of objects that overlap the
      exposure (`lsst.afw.table.SimpleCatalog`)
    - ``matches`` :  Matched sources and references
      (`list` of `lsst.afw.table.ReferenceMatch`)
    - ``matchMeta`` : metadata needed to unpersist matches
      (`lsst.daf.base.PropertyList`)

Notes
-----
ignores config.matchDistanceSigma

Definition at line 116 of file ref_match.py.

116  def loadAndMatch(self, exposure, sourceCat):
117  """Load reference objects overlapping an exposure and match to sources
118  detected on that exposure.
119 
120  Parameters
121  ----------
122  exposure : `lsst.afw.image.Exposure`
123  exposure that the sources overlap
124  sourceCat : `lsst.afw.table.SourceCatalog.`
125  catalog of sources detected on the exposure
126 
127  Returns
128  -------
129  result : `lsst.pipe.base.Struct`
130  Result struct with Components:
131 
132  - ``refCat`` : reference object catalog of objects that overlap the
133  exposure (`lsst.afw.table.SimpleCatalog`)
134  - ``matches`` : Matched sources and references
135  (`list` of `lsst.afw.table.ReferenceMatch`)
136  - ``matchMeta`` : metadata needed to unpersist matches
137  (`lsst.daf.base.PropertyList`)
138 
139  Notes
140  -----
141  ignores config.matchDistanceSigma
142  """
143  if self.refObjLoader is None:
144  raise RuntimeError("Running matcher task with no refObjLoader set in __ini__ or setRefObjLoader")
145  import lsstDebug
146  debug = lsstDebug.Info(__name__)
147 
148  expMd = self._getExposureMetadata(exposure)
149 
150  sourceSelection = self.sourceSelector.run(sourceCat)
151 
152  sourceFluxField = "slot_%sFlux_instFlux" % (self.config.sourceFluxType)
153 
154  loadRes = self.refObjLoader.loadPixelBox(
155  bbox=expMd.bbox,
156  wcs=expMd.wcs,
157  filterName=expMd.filterName,
158  photoCalib=expMd.photoCalib,
159  epoch=expMd.epoch,
160  )
161 
162  refSelection = self.referenceSelector.run(loadRes.refCat)
163 
164  matchMeta = self.refObjLoader.getMetadataBox(
165  bbox=expMd.bbox,
166  wcs=expMd.wcs,
167  filterName=expMd.filterName,
168  photoCalib=expMd.photoCalib,
169  epoch=expMd.epoch,
170  )
171 
172  matchRes = self.matcher.matchObjectsToSources(
173  refCat=refSelection.sourceCat,
174  sourceCat=sourceSelection.sourceCat,
175  wcs=expMd.wcs,
176  sourceFluxField=sourceFluxField,
177  refFluxField=loadRes.fluxField,
178  match_tolerance=None,
179  )
180 
181  distStats = self._computeMatchStatsOnSky(matchRes.matches)
182  self.log.info(
183  "Found %d matches with scatter = %0.3f +- %0.3f arcsec; " %
184  (len(matchRes.matches), distStats.distMean.asArcseconds(), distStats.distStdDev.asArcseconds())
185  )
186 
187  if debug.display:
188  frame = int(debug.frame)
190  refCat=refSelection.sourceCat,
191  sourceCat=sourceSelection.sourceCat,
192  matches=matchRes.matches,
193  exposure=exposure,
194  bbox=expMd.bbox,
195  frame=frame,
196  title="Matches",
197  )
198 
199  return pipeBase.Struct(
200  refCat=loadRes.refCat,
201  refSelection=refSelection,
202  sourceSelection=sourceSelection,
203  matches=matchRes.matches,
204  matchMeta=matchMeta,
205  )
206 
def run(self, coaddExposures, bbox, wcs)
Definition: getTemplate.py:603
def displayAstrometry(refCat=None, sourceCat=None, distortedCentroidKey=None, bbox=None, exposure=None, matches=None, frame=1, title="", pause=True)
Definition: display.py:34

◆ run()

def lsst.meas.astrom.astrometry.AstrometryTask.run (   self,
  sourceCat,
  exposure 
)
Load reference objects, match sources and optionally fit a WCS.

This is a thin layer around solve or loadAndMatch, depending on
config.forceKnownWcs.

Parameters
----------
exposure : `lsst.afw.image.Exposure`
    exposure whose WCS is to be fit
    The following are read only:

    - bbox
    - photoCalib (may be absent)
    - filter (may be unset)
    - detector (if wcs is pure tangent; may be absent)

    The following are updated:

    - wcs (the initial value is used as an initial guess, and is
      required)

sourceCat : `lsst.afw.table.SourceCatalog`
    catalog of sources detected on the exposure

Returns
-------
result : `lsst.pipe.base.Struct`
    with these fields:

    - ``refCat`` : reference object catalog of objects that overlap the
      exposure (with some margin) (`lsst.afw.table.SimpleCatalog`).
    - ``matches`` : astrometric matches
      (`list` of `lsst.afw.table.ReferenceMatch`).
    - ``scatterOnSky`` :  median on-sky separation between reference
      objects and sources in "matches"
      (`lsst.afw.geom.Angle`) or `None` if config.forceKnownWcs True
    - ``matchMeta`` :  metadata needed to unpersist matches
      (`lsst.daf.base.PropertyList`)

Definition at line 122 of file astrometry.py.

122  def run(self, sourceCat, exposure):
123  """Load reference objects, match sources and optionally fit a WCS.
124 
125  This is a thin layer around solve or loadAndMatch, depending on
126  config.forceKnownWcs.
127 
128  Parameters
129  ----------
130  exposure : `lsst.afw.image.Exposure`
131  exposure whose WCS is to be fit
132  The following are read only:
133 
134  - bbox
135  - photoCalib (may be absent)
136  - filter (may be unset)
137  - detector (if wcs is pure tangent; may be absent)
138 
139  The following are updated:
140 
141  - wcs (the initial value is used as an initial guess, and is
142  required)
143 
144  sourceCat : `lsst.afw.table.SourceCatalog`
145  catalog of sources detected on the exposure
146 
147  Returns
148  -------
149  result : `lsst.pipe.base.Struct`
150  with these fields:
151 
152  - ``refCat`` : reference object catalog of objects that overlap the
153  exposure (with some margin) (`lsst.afw.table.SimpleCatalog`).
154  - ``matches`` : astrometric matches
155  (`list` of `lsst.afw.table.ReferenceMatch`).
156  - ``scatterOnSky`` : median on-sky separation between reference
157  objects and sources in "matches"
158  (`lsst.afw.geom.Angle`) or `None` if config.forceKnownWcs True
159  - ``matchMeta`` : metadata needed to unpersist matches
160  (`lsst.daf.base.PropertyList`)
161  """
162  if self.refObjLoader is None:
163  raise RuntimeError("Running matcher task with no refObjLoader set in __init__ or setRefObjLoader")
164  if self.config.forceKnownWcs:
165  res = self.loadAndMatch(exposure=exposure, sourceCat=sourceCat)
166  res.scatterOnSky = None
167  else:
168  res = self.solve(exposure=exposure, sourceCat=sourceCat)
169  return res
170 

◆ setRefObjLoader()

def lsst.meas.astrom.ref_match.RefMatchTask.setRefObjLoader (   self,
  refObjLoader 
)
inherited
Sets the reference object loader for the task

Parameters
----------
refObjLoader
    An instance of a reference object loader task or class

Definition at line 105 of file ref_match.py.

105  def setRefObjLoader(self, refObjLoader):
106  """Sets the reference object loader for the task
107 
108  Parameters
109  ----------
110  refObjLoader
111  An instance of a reference object loader task or class
112  """
113  self.refObjLoader = refObjLoader
114 

◆ solve()

def lsst.meas.astrom.astrometry.AstrometryTask.solve (   self,
  exposure,
  sourceCat 
)
Load reference objects overlapping an exposure, match to sources and
fit a WCS

Returns
-------
result : `lsst.pipe.base.Struct`
    Result struct with components:

    - ``refCat`` : reference object catalog of objects that overlap the
      exposure (with some margin) (`lsst::afw::table::SimpleCatalog`).
    - ``matches`` :  astrometric matches
      (`list` of `lsst.afw.table.ReferenceMatch`).
    - ``scatterOnSky`` :  median on-sky separation between reference
      objects and sources in "matches" (`lsst.geom.Angle`)
    - ``matchMeta`` :  metadata needed to unpersist matches
      (`lsst.daf.base.PropertyList`)

Notes
-----
ignores config.forceKnownWcs

Definition at line 172 of file astrometry.py.

172  def solve(self, exposure, sourceCat):
173  """Load reference objects overlapping an exposure, match to sources and
174  fit a WCS
175 
176  Returns
177  -------
178  result : `lsst.pipe.base.Struct`
179  Result struct with components:
180 
181  - ``refCat`` : reference object catalog of objects that overlap the
182  exposure (with some margin) (`lsst::afw::table::SimpleCatalog`).
183  - ``matches`` : astrometric matches
184  (`list` of `lsst.afw.table.ReferenceMatch`).
185  - ``scatterOnSky`` : median on-sky separation between reference
186  objects and sources in "matches" (`lsst.geom.Angle`)
187  - ``matchMeta`` : metadata needed to unpersist matches
188  (`lsst.daf.base.PropertyList`)
189 
190  Notes
191  -----
192  ignores config.forceKnownWcs
193  """
194  if self.refObjLoader is None:
195  raise RuntimeError("Running matcher task with no refObjLoader set in __init__ or setRefObjLoader")
196  import lsstDebug
197  debug = lsstDebug.Info(__name__)
198 
199  expMd = self._getExposureMetadata(exposure)
200 
201  sourceSelection = self.sourceSelector.run(sourceCat)
202 
203  self.log.info("Purged %d sources, leaving %d good sources" %
204  (len(sourceCat) - len(sourceSelection.sourceCat),
205  len(sourceSelection.sourceCat)))
206 
207  loadRes = self.refObjLoader.loadPixelBox(
208  bbox=expMd.bbox,
209  wcs=expMd.wcs,
210  filterName=expMd.filterName,
211  photoCalib=expMd.photoCalib,
212  epoch=expMd.epoch,
213  )
214 
215  refSelection = self.referenceSelector.run(loadRes.refCat)
216 
217  matchMeta = self.refObjLoader.getMetadataBox(
218  bbox=expMd.bbox,
219  wcs=expMd.wcs,
220  filterName=expMd.filterName,
221  photoCalib=expMd.photoCalib,
222  epoch=expMd.epoch,
223  )
224 
225  if debug.display:
226  frame = int(debug.frame)
228  refCat=refSelection.sourceCat,
229  sourceCat=sourceSelection.sourceCat,
230  exposure=exposure,
231  bbox=expMd.bbox,
232  frame=frame,
233  title="Reference catalog",
234  )
235 
236  res = None
237  wcs = expMd.wcs
238  match_tolerance = None
239  for i in range(self.config.maxIter):
240  iterNum = i + 1
241  try:
242  tryRes = self._matchAndFitWcs(
243  refCat=refSelection.sourceCat,
244  sourceCat=sourceCat,
245  goodSourceCat=sourceSelection.sourceCat,
246  refFluxField=loadRes.fluxField,
247  bbox=expMd.bbox,
248  wcs=wcs,
249  exposure=exposure,
250  match_tolerance=match_tolerance,
251  )
252  except Exception as e:
253  # if we have had a succeessful iteration then use that; otherwise fail
254  if i > 0:
255  self.log.info("Fit WCS iter %d failed; using previous iteration: %s" % (iterNum, e))
256  iterNum -= 1
257  break
258  else:
259  raise
260 
261  match_tolerance = tryRes.match_tolerance
262  tryMatchDist = self._computeMatchStatsOnSky(tryRes.matches)
263  self.log.debug(
264  "Match and fit WCS iteration %d: found %d matches with scatter = %0.3f +- %0.3f arcsec; "
265  "max match distance = %0.3f arcsec",
266  iterNum, len(tryRes.matches), tryMatchDist.distMean.asArcseconds(),
267  tryMatchDist.distStdDev.asArcseconds(), tryMatchDist.maxMatchDist.asArcseconds())
268 
269  maxMatchDist = tryMatchDist.maxMatchDist
270  res = tryRes
271  wcs = res.wcs
272  if maxMatchDist.asArcseconds() < self.config.minMatchDistanceArcSec:
273  self.log.debug(
274  "Max match distance = %0.3f arcsec < %0.3f = config.minMatchDistanceArcSec; "
275  "that's good enough",
276  maxMatchDist.asArcseconds(), self.config.minMatchDistanceArcSec)
277  break
278  match_tolerance.maxMatchDist = maxMatchDist
279 
280  self.log.info(
281  "Matched and fit WCS in %d iterations; "
282  "found %d matches with scatter = %0.3f +- %0.3f arcsec" %
283  (iterNum, len(tryRes.matches), tryMatchDist.distMean.asArcseconds(),
284  tryMatchDist.distStdDev.asArcseconds()))
285  for m in res.matches:
286  if self.usedKey:
287  m.second.set(self.usedKey, True)
288  exposure.setWcs(res.wcs)
289 
290  # Record the scatter in the exposure metadata
291  md = exposure.getMetadata()
292  md['SFM_ASTROM_OFFSET_MEAN'] = tryMatchDist.distMean.asArcseconds()
293  md['SFM_ASTROM_OFFSET_STD'] = tryMatchDist.distStdDev.asArcseconds()
294 
295  return pipeBase.Struct(
296  refCat=refSelection.sourceCat,
297  matches=res.matches,
298  scatterOnSky=res.scatterOnSky,
299  matchMeta=matchMeta,
300  )
301 

Member Data Documentation

◆ ConfigClass

lsst.meas.astrom.astrometry.AstrometryTask.ConfigClass = AstrometryConfig
static

Definition at line 107 of file astrometry.py.

◆ refObjLoader

lsst.meas.astrom.ref_match.RefMatchTask.refObjLoader
inherited

Definition at line 92 of file ref_match.py.

◆ usedKey

lsst.meas.astrom.astrometry.AstrometryTask.usedKey

Definition at line 114 of file astrometry.py.


The documentation for this class was generated from the following file: