Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# 

2# LSST Data Management System 

3# Copyright 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__ = ["getSipMatrixFromMetadata", "makeDistortedTanWcs", "computePixelToDistortedPixel"] 

24 

25from deprecated.sphinx import deprecated 

26 

27import lsst.geom 

28from ..transformFactory import linearizeTransform, makeTransform 

29from ..skyWcs import makeModifiedWcs 

30from .wcsUtils import _getSipMatrixFromMetadata 

31 

32 

33def getSipMatrixFromMetadata(metadata, name): 

34 """Extract a SIP matrix from FITS TAN-SIP WCS metadata. 

35 

36 Omitted coefficients are set to 0 and all coefficients may be omitted. 

37 

38 Parameters 

39 ---------- 

40 metadata : `lsst.daf.base.PropertySet` 

41 FITS metadata. 

42 name : `str` 

43 Name of TAN-SIP matrix (``"A"``, ``"B"``, ``"Ap"``, or ``"Bp"``). 

44 

45 Returns 

46 ------- 

47 `numpy.array` 

48 The SIP matrix. 

49 

50 Raises 

51 ------ 

52 TypeError 

53 If the order keyword ``<name>_ORDER`` (e.g. ``AP_ORDER``) is not found, 

54 the value of the order keyword cannot be read as an integer, 

55 the value of the order keyword is negative, 

56 or if a matrix parameter (e.g. ``AP_5_0``) cannot be read as a float. 

57 """ 

58 arr = _getSipMatrixFromMetadata(metadata, name) 

59 if arr.shape == (): # order=0 

60 arr.shape = (1, 1) 

61 return arr 

62 

63 

64@deprecated(reason="Camera geometry-based SkyWcs are now set when reading raws. To be removed after v20.", 

65 category=FutureWarning) 

66def makeDistortedTanWcs(tanWcs, pixelToFocalPlane, focalPlaneToFieldAngle): 

67 """Compute a WCS that includes a model of optical distortion. 

68 

69 This is useful in the common case that the initial WCS entirely ignores 

70 the effect of optical distortion. 

71 

72 Parameters 

73 ---------- 

74 tanWcs : `lsst.afw.geom.SkyWcs` 

75 A pure TAN WCS, such as is usually provided in raw data. 

76 This should have no existing compensation for optical distortion 

77 (though it may include an ``ACTUAL_PIXELS`` frame to model pixel-level 

78 distortions). 

79 pixelToFocalPlane : `lsst.afw.geom.TransformPoint2ToPoint2` 

80 Transform parent pixel coordinates to focal plane coordinates. 

81 This models the location of the CCD on the focal plane 

82 and is almost always an affine transformation. 

83 This can be obtained from the detector of an exposure. 

84 focalPlaneToFieldAngle : `lsst.afw.geom.TransformPoint2ToPoint2` 

85 Transform focal plane coordinates to field angle coordinates. 

86 This is a model for optical distortion, and is often a radial 

87 polynomial. This can be obtained from the camera geometry. 

88 

89 

90 Returns 

91 ------- 

92 lsst.afw.geom.SkyWcs 

93 A copy of `tanWcs` that includes the effect of optical distortion. 

94 

95 Raises 

96 ------ 

97 RuntimeError 

98 If the current frame of `wcs` is not a SkyFrame; 

99 LookupError 

100 If 2-dimensional Frames with Domain "PIXELS" and "IWC" 

101 are not all found. 

102 """ 

103 # The math is as follows: 

104 # 

105 # Our input TAN WCS is: 

106 # tanWcs = PIXELS frame -> pixelToIwc -> IWC frame -> iwcToSky -> SkyFrame 

107 # See lsst.afw.geom.SkyWcs for a description of these frames. 

108 # tanWcs may also contain an ACTUAL_PIXELS frame before the PIXELS frame; 

109 # if so it will be preserved, but it is irrelevant to the computation 

110 # and so not discussed further. 

111 # 

112 # Our desired WCS must still contain the PIXELS and IWC frames. 

113 # The distortion will be inserted just after the PIXELS frame, 

114 # So the new WCS will be as follows: 

115 # wcs = PIXELS frame -> pixelToDistortedPixel -> pixelToIwc -> IWC frame -> iwcToSky -> SkyFrame 

116 # 

117 # We compute pixelToDistortedPixel as follows... 

118 # 

119 # We will omit the frames from now on, for simplicity. Thus: 

120 # tanWcs = pixelToIwc -> iwcToSksy 

121 # and: 

122 # wcs = pixelToDistortedPixel -> pixelToIwc -> iwcToSky 

123 # 

124 # We also know pixelToFocalPlane and focalPlaneToFieldAngle, 

125 # and can use them as follows: 

126 # 

127 # The tan WCS can be expressed as: 

128 # tanWcs = pixelToFocalPlane -> focalPlaneToTanFieldAngle -> fieldAngleToIwc -> iwcToSky 

129 # where: 

130 # - focalPlaneToTanFieldAngle is the linear approximation to 

131 # focalPlaneToFieldAngle at the center of the focal plane 

132 # 

133 # The desired WCS can be expressed as: 

134 # wcs = pixelToFocalPlane -> focalPlaneToFieldAngle -> fieldAngleToIwc -> iwcToSky 

135 # 

136 # By equating the two expressions for tanWcs, we get: 

137 # pixelToIwc = pixelToFocalPlane -> focalPlaneToTanFieldAngle -> fieldAngleToIwc 

138 # fieldAngleToIwc = tanFieldAngleToFocalPlane -> focalPlaneToPixel -> pixelToIwc 

139 # 

140 # By equating the two expressions for desired wcs we get: 

141 # pixelToDistortedPixel -> pixelToIwc = pixelToFocalPlane -> focalPlaneToFieldAngle -> fieldAngleToIwc 

142 # 

143 # Substitute our expression for fieldAngleToIwc from tanWcs into the 

144 # previous equation, we get: 

145 # pixelToDistortedPixel -> pixelToIwc 

146 # = pixelToFocalPlane -> focalPlaneToFieldAngle -> tanFieldAngleToFocalPlane -> focalPlaneToPixel 

147 # -> pixelToIwc 

148 # 

149 # Thus: 

150 # pixelToDistortedPixel 

151 # = pixelToFocalPlane -> focalPlaneToFieldAngle -> tanFieldAngleToFocalPlane -> focalPlaneToPixel 

152 

153 pixelToDistortedPixel = computePixelToDistortedPixel(pixelToFocalPlane, focalPlaneToFieldAngle) 

154 return makeModifiedWcs(pixelTransform=pixelToDistortedPixel, wcs=tanWcs, modifyActualPixels=False) 

155 

156 

157def computePixelToDistortedPixel(pixelToFocalPlane, focalPlaneToFieldAngle): 

158 """Compute the transform ``pixelToDistortedPixel``, which applies optical 

159 distortion specified by ``focalPlaneToFieldAngle``. 

160 

161 The resulting transform is designed to be used to convert a pure TAN WCS 

162 to a WCS that includes a model for optical distortion. In detail, 

163 the initial WCS will contain these frames and transforms:: 

164 

165 PIXELS frame -> pixelToIwc -> IWC frame -> gridToIwc -> SkyFrame 

166 

167 To produce the WCS with distortion, replace ``pixelToIwc`` with:: 

168 

169 pixelToDistortedPixel -> pixelToIwc 

170 

171 Parameters 

172 ---------- 

173 pixelToFocalPlane : `lsst.afw.geom.TransformPoint2ToPoint2` 

174 Transform parent pixel coordinates to focal plane coordinates 

175 focalPlaneToFieldAngle : `lsst.afw.geom.TransformPoint2ToPoint2` 

176 Transform focal plane coordinates to field angle coordinates 

177 

178 Returns 

179 ------- 

180 pixelToDistortedPixel : `lsst.afw.geom.TransformPoint2ToPoint2` 

181 A transform that applies the effect of the optical distortion model. 

182 """ 

183 # return pixelToFocalPlane -> focalPlaneToFieldAngle -> tanFieldAngleToocalPlane -> focalPlaneToPixel 

184 focalPlaneToTanFieldAngle = makeTransform(linearizeTransform(focalPlaneToFieldAngle, 

185 lsst.geom.Point2D(0, 0))) 

186 return pixelToFocalPlane.then(focalPlaneToFieldAngle) \ 

187 .then(focalPlaneToTanFieldAngle.inverted()) \ 

188 .then(pixelToFocalPlane.inverted())