Coverage for python/lsst/meas/astrom/approximateWcs.py: 22%

43 statements  

« prev     ^ index     » next       coverage.py v7.2.5, created at 2023-05-18 02:38 -0700

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 

23__all__ = ["approximateWcs"] 

24 

25import numpy as np 

26 

27import lsst.geom 

28import lsst.afw.table as afwTable 

29import lsst.afw.geom as afwGeom 

30from lsst.meas.base import SingleFrameMeasurementTask 

31from lsst.meas.astrom.sip import makeCreateWcsWithSip 

32from lsst.afw.geom.utils import assertWcsAlmostEqualOverBBox 

33 

34 

35class _MockTestCase: 

36 """A fake unit test case class that will enable us to call 

37 assertWcsAlmostEqualOverBBox from the method approximateWcs""" 

38 

39 def fail(self, msgStr): 

40 raise UserWarning("WCS fitting failed " + msgStr) 

41 

42 

43def approximateWcs(wcs, bbox, order=3, nx=20, ny=20, iterations=3, 

44 skyTolerance=0.001*lsst.geom.arcseconds, pixelTolerance=0.02, useTanWcs=False): 

45 """Approximate an existing WCS as a TAN-SIP WCS 

46 

47 The fit is performed by evaluating the WCS at a uniform grid of points 

48 within a bounding box. 

49 

50 Parameters 

51 ---------- 

52 wcs : `lsst.afw.geom.SkyWcs` 

53 wcs to approximate 

54 bbox : `lsst.geom.Box2I` 

55 the region over which the WCS will be fit 

56 order : `int` 

57 order of SIP fit 

58 nx : `int` 

59 number of grid points along x 

60 ny : `int` 

61 number of grid points along y 

62 iterations : `int` 

63 number of times to iterate over fitting 

64 skyTolerance : `lsst.geom.Angle` 

65 maximum allowed difference in world coordinates between 

66 input wcs and approximate wcs (default is 0.001 arcsec) 

67 pixelTolerance : `float` 

68 maximum allowed difference in pixel coordinates between 

69 input wcs and approximate wcs (default is 0.02 pixels) 

70 useTanWcs : `bool` 

71 send a TAN version of wcs to the fitter? It is documented to require that, 

72 but I don't think the fitter actually cares 

73 

74 Returns 

75 ------- 

76 fitWcs : `lsst.afw.geom.SkyWcs` 

77 the fit TAN-SIP WCS 

78 """ 

79 if useTanWcs: 

80 crpix = wcs.getPixelOrigin() 

81 crval = wcs.getSkyOrigin() 

82 cdMatrix = wcs.getCdMatrix(crpix) 

83 tanWcs = afwGeom.makeSkyWcs(crpix=crpix, crval=crval, cdMatrix=cdMatrix) 

84 else: 

85 tanWcs = wcs 

86 

87 # create a matchList consisting of a grid of points covering the bbox 

88 refSchema = afwTable.SimpleTable.makeMinimalSchema() 

89 refCoordKey = afwTable.CoordKey(refSchema["coord"]) 

90 refCat = afwTable.SimpleCatalog(refSchema) 

91 

92 sourceSchema = afwTable.SourceTable.makeMinimalSchema() 

93 SingleFrameMeasurementTask(schema=sourceSchema) # expand the schema 

94 sourceCentroidKey = afwTable.Point2DKey(sourceSchema["slot_Centroid"]) 

95 

96 sourceCat = afwTable.SourceCatalog(sourceSchema) 

97 

98 matchList = [] 

99 

100 bboxd = lsst.geom.Box2D(bbox) 

101 for x in np.linspace(bboxd.getMinX(), bboxd.getMaxX(), nx): 

102 for y in np.linspace(bboxd.getMinY(), bboxd.getMaxY(), ny): 

103 pixelPos = lsst.geom.Point2D(x, y) 

104 skyCoord = wcs.pixelToSky(pixelPos) 

105 

106 refObj = refCat.addNew() 

107 refObj.set(refCoordKey, skyCoord) 

108 

109 source = sourceCat.addNew() 

110 source.set(sourceCentroidKey, pixelPos) 

111 

112 matchList.append(afwTable.ReferenceMatch(refObj, source, 0.0)) 

113 

114 # The TAN-SIP fitter is fitting x and y separately, so we have to iterate to make it converge 

115 for indx in range(iterations): 

116 sipObject = makeCreateWcsWithSip(matchList, tanWcs, order, bbox) 

117 tanWcs = sipObject.getNewWcs() 

118 fitWcs = sipObject.getNewWcs() 

119 

120 mockTest = _MockTestCase() 

121 assertWcsAlmostEqualOverBBox(mockTest, wcs, fitWcs, bbox, maxDiffSky=skyTolerance, 

122 maxDiffPix=pixelTolerance) 

123 

124 return fitWcs