LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
LSSTDataManagementBasePackage
approximateWcs.py
Go to the documentation of this file.
1 from builtins import range
2 from builtins import object
3 #
4 # LSST Data Management System
5 # Copyright 2008, 2009, 2010 LSST Corporation.
6 #
7 # This product includes software developed by the
8 # LSST Project (http://www.lsst.org/).
9 #
10 # This program is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation, either version 3 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the LSST License Statement and
21 # the GNU General Public License along with this program. If not,
22 # see <http://www.lsstcorp.org/LegalNotices/>.
23 #
24 
25 import numpy as np
26 
27 import lsst.afw.image as afwImage
28 import lsst.afw.table as afwTable
29 import lsst.afw.geom as afwGeom
30 from lsst.meas.base import SingleFrameMeasurementTask
31 from lsst.meas.astrom.sip import makeCreateWcsWithSip
32 from lsst.afw.image.basicUtils import assertWcsNearlyEqualOverBBox
33 
34 __all__ = ["approximateWcs"]
35 
36 
37 class _MockTestCase(object):
38  """A fake unit test case class that will enable us to call
39  assertWcsNearlyEqualOverBBox from the method approximateWcs"""
40 
41  def fail(self, msgStr):
42  raise UserWarning("WCS fitting failed " + msgStr)
43 
44 
45 def approximateWcs(wcs, bbox, order=3, nx=20, ny=20, iterations=3,
46  skyTolerance=0.001*afwGeom.arcseconds, pixelTolerance=0.02, useTanWcs=False):
47  """Approximate an existing WCS as a TAN-SIP WCS
48 
49  The fit is performed by evaluating the WCS at a uniform grid of points within a bounding box.
50 
51  @param[in] wcs wcs to approximate
52  @param[in] bbox the region over which the WCS will be fit
53  @param[in] order order of SIP fit
54  @param[in] nx number of grid points along x
55  @param[in] ny number of grid points along y
56  @param[in] iterations number of times to iterate over fitting
57  @param[in] skyTolerance maximum allowed difference in world coordinates between
58  input wcs and approximate wcs (default is 0.001 arcsec)
59  @param[in] pixelTolerance maximum allowed difference in pixel coordinates between
60  input wcs and approximate wcs (default is 0.02 pixels)
61  @param[in] useTanWcs send a TAN version of wcs to the fitter? It is documented to require that,
62  but I don't think the fitter actually cares
63  @return the fit TAN-SIP WCS
64  """
65  if useTanWcs:
66  crCoord = wcs.getSkyOrigin()
67  crPix = wcs.getPixelOrigin()
68  cdMat = wcs.getCDMatrix()
69  tanWcs = afwImage.makeWcs(crCoord, crPix, cdMat[0, 0], cdMat[0, 1], cdMat[1, 0], cdMat[1, 1])
70  else:
71  tanWcs = wcs
72 
73  # create a matchList consisting of a grid of points covering the bbox
74  refSchema = afwTable.SimpleTable.makeMinimalSchema()
75  refCoordKey = afwTable.CoordKey(refSchema["coord"])
76  refCat = afwTable.SimpleCatalog(refSchema)
77 
78  sourceSchema = afwTable.SourceTable.makeMinimalSchema()
79  SingleFrameMeasurementTask(schema=sourceSchema) # expand the schema
80  sourceCentroidKey = afwTable.Point2DKey(sourceSchema["slot_Centroid"])
81 
82  sourceCat = afwTable.SourceCatalog(sourceSchema)
83 
84  matchList = afwTable.ReferenceMatchVector()
85 
86  bboxd = afwGeom.Box2D(bbox)
87  for x in np.linspace(bboxd.getMinX(), bboxd.getMaxX(), nx):
88  for y in np.linspace(bboxd.getMinY(), bboxd.getMaxY(), ny):
89  pixelPos = afwGeom.Point2D(x, y)
90  skyCoord = wcs.pixelToSky(pixelPos)
91 
92  refObj = refCat.addNew()
93  refObj.set(refCoordKey, skyCoord)
94 
95  source = sourceCat.addNew()
96  source.set(sourceCentroidKey, pixelPos)
97 
98  matchList.append(afwTable.ReferenceMatch(refObj, source, 0.0))
99 
100  # The TAN-SIP fitter is fitting x and y separately, so we have to iterate to make it converge
101  for indx in range(iterations):
102  sipObject = makeCreateWcsWithSip(matchList, tanWcs, order, bbox)
103  tanWcs = sipObject.getNewWcs()
104  fitWcs = sipObject.getNewWcs()
105 
106  mockTest = _MockTestCase()
107  assertWcsNearlyEqualOverBBox(mockTest, wcs, fitWcs, bbox, maxDiffSky=skyTolerance,
108  maxDiffPix=pixelTolerance)
109 
110  return fitWcs
std::vector< ReferenceMatch > ReferenceMatchVector
Definition: fwd.h:97
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.
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.
Definition: fwd.h:55
Lightweight representation of a geometric match between two records.
Definition: fwd.h:90
boost::shared_ptr< Wcs > makeWcs(coord::Coord const &crval, geom::Point2D const &crpix, double CD11, double CD12, double CD21, double CD22)
Create a Wcs object from crval, crpix, CD, using CD elements (useful from python) ...
Definition: makeWcs.cc:138
A floating-point coordinate rectangle geometry.
Definition: Box.h:271
def assertWcsNearlyEqualOverBBox
Compare pixelToSky and skyToPixel for two WCS over a rectangular grid of pixel positions.
Definition: basicUtils.py:152
A FunctorKey used to get or set celestial coordinates from a pair of Angle keys.
Definition: aggregates.h:119