lsst.meas.astrom  14.0-5-ge815445
approximateWcs.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008-2017 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 from __future__ import absolute_import, division, print_function
23 
24 __all__ = ["approximateWcs"]
25 
26 from builtins import range
27 from builtins import object
28 import numpy as np
29 
30 import lsst.afw.image as afwImage
31 import lsst.afw.table as afwTable
32 import lsst.afw.geom as afwGeom
33 from lsst.meas.base import SingleFrameMeasurementTask
34 from lsst.meas.astrom.sip import makeCreateWcsWithSip
35 from lsst.afw.image.basicUtils import assertWcsAlmostEqualOverBBox
36 
37 
38 class _MockTestCase(object):
39  """A fake unit test case class that will enable us to call
40  assertWcsAlmostEqualOverBBox from the method approximateWcs"""
41 
42  def fail(self, msgStr):
43  raise UserWarning("WCS fitting failed " + msgStr)
44 
45 
46 def approximateWcs(wcs, bbox, order=3, nx=20, ny=20, iterations=3,
47  skyTolerance=0.001*afwGeom.arcseconds, pixelTolerance=0.02, useTanWcs=False):
48  """Approximate an existing WCS as a TAN-SIP WCS
49 
50  The fit is performed by evaluating the WCS at a uniform grid of points within a bounding box.
51 
52  @param[in] wcs wcs to approximate
53  @param[in] bbox the region over which the WCS will be fit
54  @param[in] order order of SIP fit
55  @param[in] nx number of grid points along x
56  @param[in] ny number of grid points along y
57  @param[in] iterations number of times to iterate over fitting
58  @param[in] skyTolerance maximum allowed difference in world coordinates between
59  input wcs and approximate wcs (default is 0.001 arcsec)
60  @param[in] pixelTolerance maximum allowed difference in pixel coordinates between
61  input wcs and approximate wcs (default is 0.02 pixels)
62  @param[in] useTanWcs send a TAN version of wcs to the fitter? It is documented to require that,
63  but I don't think the fitter actually cares
64  @return the fit TAN-SIP WCS
65  """
66  if useTanWcs:
67  crCoord = wcs.getSkyOrigin()
68  crPix = wcs.getPixelOrigin()
69  cdMat = wcs.getCDMatrix()
70  tanWcs = afwImage.makeWcs(crCoord, crPix, cdMat[0, 0], cdMat[0, 1], cdMat[1, 0], cdMat[1, 1])
71  else:
72  tanWcs = wcs
73 
74  # create a matchList consisting of a grid of points covering the bbox
75  refSchema = afwTable.SimpleTable.makeMinimalSchema()
76  refCoordKey = afwTable.CoordKey(refSchema["coord"])
77  refCat = afwTable.SimpleCatalog(refSchema)
78 
79  sourceSchema = afwTable.SourceTable.makeMinimalSchema()
80  SingleFrameMeasurementTask(schema=sourceSchema) # expand the schema
81  sourceCentroidKey = afwTable.Point2DKey(sourceSchema["slot_Centroid"])
82 
83  sourceCat = afwTable.SourceCatalog(sourceSchema)
84 
85  matchList = []
86 
87  bboxd = afwGeom.Box2D(bbox)
88  for x in np.linspace(bboxd.getMinX(), bboxd.getMaxX(), nx):
89  for y in np.linspace(bboxd.getMinY(), bboxd.getMaxY(), ny):
90  pixelPos = afwGeom.Point2D(x, y)
91  skyCoord = wcs.pixelToSky(pixelPos)
92 
93  refObj = refCat.addNew()
94  refObj.set(refCoordKey, skyCoord)
95 
96  source = sourceCat.addNew()
97  source.set(sourceCentroidKey, pixelPos)
98 
99  matchList.append(afwTable.ReferenceMatch(refObj, source, 0.0))
100 
101  # The TAN-SIP fitter is fitting x and y separately, so we have to iterate to make it converge
102  for indx in range(iterations):
103  sipObject = makeCreateWcsWithSip(matchList, tanWcs, order, bbox)
104  tanWcs = sipObject.getNewWcs()
105  fitWcs = sipObject.getNewWcs()
106 
107  mockTest = _MockTestCase()
108  assertWcsAlmostEqualOverBBox(mockTest, wcs, fitWcs, bbox, maxDiffSky=skyTolerance,
109  maxDiffPix=pixelTolerance)
110 
111  return fitWcs
CreateWcsWithSip< MatchT > makeCreateWcsWithSip(std::vector< MatchT > const &matches, afw::image::Wcs const &linearWcs, int const order, afw::geom::Box2I const &bbox=afw::geom::Box2I(), int const ngrid=0)
Factory function for CreateWcsWithSip.
def approximateWcs(wcs, bbox, order=3, nx=20, ny=20, iterations=3, skyTolerance=0.001 *afwGeom.arcseconds, pixelTolerance=0.02, useTanWcs=False)