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

1from __future__ import division 

2from builtins import zip 

3import numpy as np 

4import numbers 

5from lsst.sims.utils import _observedFromICRS, _icrsFromObserved 

6 

7__all__ = ["_nativeLonLatFromPointing", "_lonLatFromNativeLonLat", 

8 "_nativeLonLatFromRaDec", "_raDecFromNativeLonLat", 

9 "nativeLonLatFromRaDec", "raDecFromNativeLonLat"] 

10 

11 

12def _nativeLonLatFromPointing(lon, lat, lonPointing, latPointing): 

13 """ 

14 Convert the longitude and latitude of a point into `native' 

15 longitude and latitude defined by a telescope pointing. 

16 

17 Native longitude and latitude are defined as what longitude and latitude would be 

18 if the pole were at the location where the telescope is pointing. 

19 The transformation is achieved by rotating the vector pointing to the lon 

20 and lat being transformed once about the x axis and once about the z axis. 

21 These are the Euler rotations referred to in Section 2.3 of 

22 

23 Calabretta and Greisen (2002), A&A 395, p. 1077 

24 

25 Note: This method does not assume anything about the input coordinate 

26 system. It merely takes a longitude-like coordinate, a latitude-like coordinate 

27 and a longitude-like coordinate of the pointing and a latitude-like coordinate 

28 of the pointing and transforms them using spherical geometry. 

29 

30 @param [in] a longitude-like coordinate in radians 

31 

32 @param [in] a latitude-like coordinate in radians 

33 

34 @param [in] a longitude-like coordinate of the telescope pointing in radians 

35 

36 @param [in] a latitude-like coordinate of the telescope pointing in radians 

37 

38 @param [out] the native longitude of the transformed point(s) in radians 

39 

40 @param [out] the native latitude of the transformed point(s) in radians 

41 """ 

42 

43 x = -1.0 * np.cos(lat) * np.sin(lon) 

44 y = np.cos(lat) * np.cos(lon) 

45 z = np.sin(lat) 

46 

47 alpha = latPointing - 0.5 * np.pi 

48 beta = lonPointing 

49 

50 ca = np.cos(alpha) 

51 sa = np.sin(alpha) 

52 cb = np.cos(beta) 

53 sb = np.sin(beta) 

54 

55 v2 = np.dot(np.array([[1.0, 0.0, 0.0], [0.0, ca, sa], [0.0, -1.0 * sa, ca]]), 

56 np.dot(np.array([[cb, sb, 0.0], [-sb, cb, 0.0], [0.0, 0.0, 1.0]]), np.array([x, y, z]))) 

57 

58 cc = np.sqrt(v2[0] * v2[0] + v2[1] * v2[1]) 

59 latOut = np.arctan2(v2[2], cc) 

60 

61 _y = v2[1] / np.cos(latOut) 

62 _ra_raw = np.arccos(_y) 

63 

64 # control for _y=1.0, -1.0 but actually being stored as just outside 

65 # the bounds of -1.0<=_y<=1.0 because of floating point error 

66 if hasattr(_ra_raw, '__len__'): 

67 _ra = np.array([rr 

68 if not np.isnan(rr) 

69 else 0.5 * np.pi * (1.0 - np.sign(yy)) 

70 for rr, yy in zip(_ra_raw, _y)]) 

71 else: 

72 if np.isnan(_ra_raw): 

73 if np.sign(_y) < 0.0: 

74 _ra = np.pi 

75 else: 

76 _ra = 0.0 

77 else: 

78 _ra = _ra_raw 

79 

80 _x = -np.sin(_ra) 

81 

82 if isinstance(_ra, numbers.Number): 

83 if np.isnan(_ra): 

84 lonOut = 0.0 

85 elif (np.abs(_x) > 1.0e-9 and np.sign(_x) != np.sign(v2[0])) or \ 

86 (np.abs(_y) > 1.0e-9 and np.sign(_y) != np.sign(v2[1])): 

87 

88 lonOut = 2.0 * np.pi - _ra 

89 else: 

90 lonOut = _ra 

91 else: 

92 _lonOut = [2.0 * np.pi - rr 

93 if (np.abs(xx) > 1.0e-9 and np.sign(xx) != np.sign(v2_0)) or 

94 (np.abs(yy) > 1.0e-9 and np.sign(yy) != np.sign(v2_1)) 

95 else rr 

96 for rr, xx, yy, v2_0, v2_1 in zip(_ra, _x, _y, v2[0], v2[1])] 

97 

98 lonOut = np.array([0.0 if np.isnan(ll) else ll for ll in _lonOut]) 

99 

100 return lonOut, latOut 

101 

102 

103def _lonLatFromNativeLonLat(nativeLon, nativeLat, lonPointing, latPointing): 

104 """ 

105 Transform a position in native longitude and latitude into 

106 longitude and latitude in a coordinate system where the telescope pointing 

107 is defined. See the doc string for _nativeLonLatFromPointing for definitions 

108 of native longitude and latitude. 

109 

110 @param [in] nativeLon is the native longitude in radians 

111 

112 @param [in] nativeLat is the native latitude in radians 

113 

114 @param [in] lonPointing is the longitude-like coordinate of the telescope 

115 pointing in radians 

116 

117 @param [in] latPointing is the latitude-like coordinate of the telescope 

118 pointing in radians 

119 

120 @param [out] latOut is the latitude of the transformed point(s) 

121 in the same coordinate system as the telescope pointing in radians 

122 

123 @param [in] latOut is the latitude of the transformed point(s) 

124 in the same coordinate system as the telescope pointing in radians 

125 """ 

126 x = -1.0 * np.cos(nativeLat) * np.sin(nativeLon) 

127 y = np.cos(nativeLat) * np.cos(nativeLon) 

128 z = np.sin(nativeLat) 

129 

130 alpha = 0.5 * np.pi - latPointing 

131 beta = lonPointing 

132 

133 ca = np.cos(alpha) 

134 sa = np.sin(alpha) 

135 cb = np.cos(beta) 

136 sb = np.sin(beta) 

137 

138 v2 = np.dot(np.array([[cb, -1.0 * sb, 0.0], [sb, cb, 0.0], [0.0, 0.0, 1.0]]), 

139 np.dot(np.array([[1.0, 0.0, 0.0], [0.0, ca, sa], [0.0, -1.0 * sa, ca]]), np.array([x, y, z]))) 

140 

141 cc = np.sqrt(v2[0] * v2[0] + v2[1] * v2[1]) 

142 latOut = np.arctan2(v2[2], cc) 

143 

144 _y = v2[1] / np.cos(latOut) 

145 _lonOut = np.arccos(_y) 

146 _x = -np.sin(_lonOut) 

147 

148 if isinstance(_lonOut, numbers.Number): 

149 if np.isnan(_lonOut): 

150 lonOut = 0.0 

151 elif (np.abs(_x) > 1.0e-9 and np.sign(_x) != np.sign(v2[0])) or \ 

152 (np.abs(_y) > 1.0e-9 and np.sign(_y) != np.sign(v2[1])): 

153 

154 lonOut = 2.0 * np.pi - _lonOut 

155 else: 

156 lonOut = _lonOut 

157 else: 

158 _lonOut = [2.0 * np.pi - rr 

159 if (np.abs(xx) > 1.0e-9 and np.sign(xx) != np.sign(v2_0)) or 

160 (np.abs(yy) > 1.0e-9 and np.sign(yy) != np.sign(v2_1)) 

161 else rr 

162 for rr, xx, yy, v2_0, v2_1 in zip(_lonOut, _x, _y, v2[0], v2[1])] 

163 

164 lonOut = np.array([0.0 if np.isnan(rr) else rr for rr in _lonOut]) 

165 

166 return lonOut, latOut 

167 

168 

169def _nativeLonLatFromRaDec(ra_in, dec_in, obs_metadata): 

170 """ 

171 Convert the RA and Dec of a star into `native' longitude and latitude. 

172 

173 Native longitude and latitude are defined as what RA and Dec would be 

174 if the celestial pole were at the location where the telescope is pointing. 

175 The transformation is achieved by rotating the vector pointing to the RA 

176 and Dec being transformed once about the x axis and once about the z axis. 

177 These are the Euler rotations referred to in Section 2.3 of 

178 

179 Calabretta and Greisen (2002), A&A 395, p. 1077 

180 

181 Note: RA, and Dec are assumed to be in the International Celestial Reference 

182 System. Before calculating native longitude and latitude, this method will 

183 convert RA and Dec to observed geocentric coordinates. 

184 

185 WARNING: This method does not account for apparent motion due to parallax. 

186 This method is only useful for mapping positions on a theoretical 

187 celestial sphere. 

188 

189 @param [in] ra is the RA of the star being transformed in radians 

190 (in the International Celestial Reference System) 

191 

192 @param [in] dec is the Dec of the star being transformed in radians 

193 (in the International Celestial Reference System) 

194 

195 @param [in] obs_metadata is an ObservationMetaData characterizing the pointing of 

196 the telescope. 

197 

198 @param [out] lonOut is the native longitude in radians 

199 

200 @param [out] latOut is the native latitude in radians 

201 """ 

202 

203 ra, dec = _observedFromICRS(ra_in, dec_in, 

204 obs_metadata=obs_metadata, epoch=2000.0, 

205 includeRefraction=True) 

206 

207 raPointing, decPointing = _observedFromICRS(obs_metadata._pointingRA, 

208 obs_metadata._pointingDec, 

209 obs_metadata=obs_metadata, epoch=2000.0, 

210 includeRefraction=True) 

211 

212 return _nativeLonLatFromPointing(ra, dec, raPointing, decPointing) 

213 

214 

215def nativeLonLatFromRaDec(ra, dec, obs_metadata): 

216 """ 

217 Convert the RA and Dec of a star into `native' longitude and latitude. 

218 

219 Native longitude and latitude are defined as what RA and Dec would be 

220 if the celestial pole were at the location where the telescope is pointing. 

221 The coordinate basis axes for this system is achieved by taking the true 

222 coordinate basis axes and rotating them once about the z axis and once about 

223 the x axis (or, by rotating the vector pointing to the RA and Dec being 

224 transformed once about the x axis and once about the z axis). These 

225 are the Euler rotations referred to in Section 2.3 of 

226 

227 Calabretta and Greisen (2002), A&A 395, p. 1077 

228 

229 Note: RA, and Dec are assumed to be in the International Celestial Reference 

230 System. Before calculating native longitude and latitude, this method will 

231 convert RA and Dec to observed geocentric coordinates. 

232 

233 WARNING: This method does not account for apparent motion due to parallax. 

234 This method is only useful for mapping positions on a theoretical 

235 celestial sphere. 

236 

237 @param [in] ra is the RA of the star being transformed in degrees 

238 (in the International Celestial Reference System) 

239 

240 @param [in] dec is the Dec of the star being transformed in degrees 

241 (in the International Celestial Reference System) 

242 

243 @param [in] obs_metadata is an ObservationMetaData characterizing the pointing of 

244 the telescope. 

245 

246 @param [out] lonOut is the native longitude in degrees 

247 

248 @param [out] latOut is the native latitude in degrees 

249 """ 

250 

251 lon, lat = _nativeLonLatFromRaDec(np.radians(ra), np.radians(dec), 

252 obs_metadata) 

253 

254 return np.degrees(lon), np.degrees(lat) 

255 

256 

257def _raDecFromNativeLonLat(lon, lat, obs_metadata): 

258 """ 

259 Transform a star's position in native longitude and latitude into 

260 RA and Dec. See the doc string for _nativeLonLatFromRaDec for definitions 

261 of native longitude and latitude. 

262 

263 @param [in] lon is the native longitude in radians 

264 

265 @param [in] lat is the native latitude in radians 

266 

267 @param [in] obs_metadata is an ObservationMetaData characterizing the pointing 

268 of the telescope 

269 

270 @param [out] raOut is the RA of the star in radians 

271 (in the International Celestial Reference System) 

272 

273 @param [in] decOut is the Dec of the star in radians 

274 (in the International Celestial Reference System) 

275 

276 Note: Because of its reliance on icrsFromObserved, this 

277 method is only accurate at angular distances from the sun of greater 

278 than 45 degrees and zenith distances of less than 75 degrees. 

279 """ 

280 

281 raPointing, decPointing = _observedFromICRS(obs_metadata._pointingRA, 

282 obs_metadata._pointingDec, 

283 obs_metadata=obs_metadata, epoch=2000.0, 

284 includeRefraction=True) 

285 

286 raObs, decObs = _lonLatFromNativeLonLat(lon, lat, raPointing, decPointing) 

287 

288 # convert from observed geocentric coordinates to International Celestial Reference System 

289 # coordinates 

290 

291 raOut, decOut = _icrsFromObserved(raObs, decObs, obs_metadata=obs_metadata, 

292 epoch=2000.0, includeRefraction=True) 

293 

294 return raOut, decOut 

295 

296 

297def raDecFromNativeLonLat(lon, lat, obs_metadata): 

298 """ 

299 Transform a star's position in native longitude and latitude into 

300 RA and Dec. See the doc string for nativeLonLatFromRaDec for definitions 

301 of native longitude and latitude. 

302 

303 @param [in] lon is the native longitude in degrees 

304 

305 @param [in] lat is the native latitude in degrees 

306 

307 @param [in] obs_metadata is an ObservationMetaData characterizing the 

308 pointing of the telescope 

309 

310 @param [out] raOut is the RA of the star in degrees 

311 (in the International Celestial Reference System) 

312 

313 @param [in] decOut is the Dec of the star in degrees 

314 (in the International Celestial Reference System) 

315 

316 Note: Because of its reliance on icrsFromObserved, this 

317 method is only accurate at angular distances from the sun of greater 

318 than 45 degrees and zenith distances of less than 75 degrees. 

319 """ 

320 

321 ra, dec = _raDecFromNativeLonLat(np.radians(lon), 

322 np.radians(lat), 

323 obs_metadata) 

324 

325 return np.degrees(ra), np.degrees(dec)