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 builtins import zip 

2import unittest 

3import numpy as np 

4import lsst.utils.tests 

5 

6from lsst.sims.utils import raDecFromNativeLonLat, nativeLonLatFromRaDec 

7from lsst.sims.utils import _raDecFromNativeLonLat, _nativeLonLatFromRaDec 

8from lsst.sims.utils import observedFromICRS, icrsFromObserved 

9from lsst.sims.utils import ObservationMetaData, haversine 

10from lsst.sims.utils import arcsecFromRadians, raDecFromAltAz, Site 

11 

12 

13def setup_module(module): 

14 lsst.utils.tests.init() 

15 

16 

17class NativeLonLatTest(unittest.TestCase): 

18 

19 def testNativeLonLat(self): 

20 """ 

21 Test that nativeLonLatFromRaDec works by considering stars and pointings 

22 at intuitive locations 

23 """ 

24 

25 mjd = 53855.0 

26 

27 raList_obs = [0.0, 0.0, 0.0, 270.0] 

28 decList_obs = [90.0, 90.0, 0.0, 0.0] 

29 

30 raPointList_obs = [0.0, 270.0, 270.0, 0.0] 

31 decPointList_obs = [0.0, 0.0, 0.0, 0.0] 

32 

33 lonControlList = [180.0, 180.0, 90.0, 270.0] 

34 latControlList = [0.0, 0.0, 0.0, 0.0] 

35 

36 for rr_obs, dd_obs, rp_obs, dp_obs, lonc, latc in \ 

37 zip(raList_obs, decList_obs, raPointList_obs, decPointList_obs, 

38 lonControlList, latControlList): 

39 

40 obsTemp = ObservationMetaData(mjd=mjd) 

41 

42 rr, dd = icrsFromObserved(np.array([rr_obs, rp_obs]), 

43 np.array([dd_obs, dp_obs]), 

44 obs_metadata=obsTemp, 

45 epoch=2000.0, includeRefraction=True) 

46 

47 obs = ObservationMetaData( 

48 pointingRA=rr[1], pointingDec=dd[1], mjd=mjd) 

49 lon, lat = nativeLonLatFromRaDec(rr[0], dd[0], obs) 

50 distance = arcsecFromRadians(haversine(lon, lat, lonc, latc)) 

51 self.assertLess(distance, 1.0) 

52 

53 def testNativeLongLatComplicated(self): 

54 """ 

55 Test that nativeLongLatFromRaDec works by considering stars and pointings 

56 at non-intuitive locations. 

57 """ 

58 

59 rng = np.random.RandomState(42) 

60 nPointings = 10 

61 raPointingList_icrs = rng.random_sample(nPointings) * 360.0 

62 decPointingList_icrs = rng.random_sample( 

63 nPointings) * 180.0 - 90.0 

64 mjdList = rng.random_sample(nPointings) * 10000.0 + 43000.0 

65 

66 nStars = 10 

67 for raPointing_icrs, decPointing_icrs, mjd in \ 

68 zip(raPointingList_icrs, decPointingList_icrs, mjdList): 

69 

70 obs = ObservationMetaData(pointingRA=raPointing_icrs, pointingDec=decPointing_icrs, mjd=mjd) 

71 raList_icrs = rng.random_sample(nStars) * 360.0 

72 decList_icrs = rng.random_sample(nStars) * 180.0 - 90.0 

73 raList_obs, decList_obs = observedFromICRS(raList_icrs, decList_icrs, obs_metadata=obs, 

74 epoch=2000.0, includeRefraction=True) 

75 

76 obsTemp = ObservationMetaData(mjd=mjd) 

77 raPointing_obs, decPointing_obs = observedFromICRS(raPointing_icrs, 

78 decPointing_icrs, 

79 obs_metadata=obsTemp, epoch=2000.0, 

80 includeRefraction=True) 

81 

82 for ra_obs, dec_obs, ra_icrs, dec_icrs in \ 

83 zip(raList_obs, decList_obs, raList_icrs, decList_icrs): 

84 

85 raRad = np.radians(ra_obs) 

86 decRad = np.radians(dec_obs) 

87 sinRa = np.sin(raRad) 

88 cosRa = np.cos(raRad) 

89 sinDec = np.sin(decRad) 

90 cosDec = np.cos(decRad) 

91 

92 # the three dimensional position of the star 

93 controlPosition = np.array([-cosDec * sinRa, cosDec * cosRa, sinDec]) 

94 

95 # calculate the rotation matrices needed to transform the 

96 # x, y, and z axes into the local x, y, and z axes 

97 # (i.e. the axes with z lined up with raPointing_obs, decPointing_obs) 

98 alpha = 0.5 * np.pi - np.radians(decPointing_obs) 

99 ca = np.cos(alpha) 

100 sa = np.sin(alpha) 

101 rotX = np.array([[1.0, 0.0, 0.0], 

102 [0.0, ca, sa], 

103 [0.0, -sa, ca]]) 

104 

105 cb = np.cos(np.radians(raPointing_obs)) 

106 sb = np.sin(np.radians(raPointing_obs)) 

107 rotZ = np.array([[cb, -sb, 0.0], 

108 [sb, cb, 0.0], 

109 [0.0, 0.0, 1.0]]) 

110 

111 # rotate the coordinate axes into the local basis 

112 xAxis = np.dot(rotZ, np.dot(rotX, np.array([1.0, 0.0, 0.0]))) 

113 yAxis = np.dot(rotZ, np.dot(rotX, np.array([0.0, 1.0, 0.0]))) 

114 zAxis = np.dot(rotZ, np.dot(rotX, np.array([0.0, 0.0, 1.0]))) 

115 

116 # calculate the local longitude and latitude of the star 

117 lon, lat = nativeLonLatFromRaDec(ra_icrs, dec_icrs, obs) 

118 cosLon = np.cos(np.radians(lon)) 

119 sinLon = np.sin(np.radians(lon)) 

120 cosLat = np.cos(np.radians(lat)) 

121 sinLat = np.sin(np.radians(lat)) 

122 

123 # the x, y, z position of the star in the local coordinate 

124 # basis 

125 transformedPosition = np.array([-cosLat * sinLon, 

126 cosLat * cosLon, 

127 sinLat]) 

128 

129 # convert that position back into the un-rotated bases 

130 testPosition = transformedPosition[0] * xAxis + \ 

131 transformedPosition[1] * yAxis + \ 

132 transformedPosition[2] * zAxis 

133 

134 # assert that testPosition and controlPosition should be equal 

135 distance = np.sqrt(np.power(controlPosition - testPosition, 2).sum()) 

136 self.assertLess(distance, 1.0e-12) 

137 

138 def testNativeLonLatVector(self): 

139 """ 

140 Test that nativeLonLatFromRaDec works in a vectorized way; we do this 

141 by performing a bunch of tansformations passing in ra and dec as numpy arrays 

142 and then comparing them to results computed in an element-wise way 

143 """ 

144 

145 obs = ObservationMetaData(pointingRA=123.0, pointingDec=43.0, mjd=53467.2) 

146 

147 nSamples = 100 

148 rng = np.random.RandomState(42) 

149 raList = rng.random_sample(nSamples) * 360.0 

150 decList = rng.random_sample(nSamples) * 180.0 - 90.0 

151 

152 lonList, latList = nativeLonLatFromRaDec(raList, decList, obs) 

153 

154 for rr, dd, lon, lat in zip(raList, decList, lonList, latList): 

155 lonControl, latControl = nativeLonLatFromRaDec(rr, dd, obs) 

156 distance = arcsecFromRadians(haversine(np.radians(lon), np.radians(lat), 

157 np.radians(lonControl), np.radians(latControl))) 

158 

159 self.assertLess(distance, 0.0001) 

160 

161 def testRaDec(self): 

162 """ 

163 Test that raDecFromNativeLonLat does invert 

164 nativeLonLatFromRaDec 

165 """ 

166 rng = np.random.RandomState(42) 

167 nSamples = 100 

168 # because raDecFromNativeLonLat is only good 

169 rrList = rng.random_sample(nSamples) * 50.0 

170 # out to a zenith distance of ~ 70 degrees 

171 

172 thetaList = rng.random_sample(nSamples) * 2.0 * np.pi 

173 

174 rrPointingList = rng.random_sample(10) * 50.0 

175 thetaPointingList = rng.random_sample(10) * 2.0 * np.pi 

176 mjdList = rng.random_sample(nSamples) * 10000.0 + 43000.0 

177 

178 for rrp, thetap, mjd in \ 

179 zip(rrPointingList, thetaPointingList, mjdList): 

180 

181 site = Site(name='LSST') 

182 raZenith, decZenith = raDecFromAltAz(180.0, 0.0, 

183 ObservationMetaData(mjd=mjd, site=site)) 

184 

185 rp = raZenith + rrp * np.cos(thetap) 

186 dp = decZenith + rrp * np.sin(thetap) 

187 obs = ObservationMetaData(pointingRA=rp, pointingDec=dp, mjd=mjd, site=site) 

188 

189 raList_icrs = (raZenith + rrList * np.cos(thetaList)) % 360.0 

190 decList_icrs = decZenith + rrList * np.sin(thetaList) 

191 

192 raList_obs, decList_obs = observedFromICRS(raList_icrs, decList_icrs, 

193 obs_metadata=obs, 

194 epoch=2000.0, includeRefraction=True) 

195 

196 # calculate the distance between the ICRS position and the observed 

197 # geocentric position 

198 dd_icrs_obs_list = arcsecFromRadians(haversine(np.radians(raList_icrs), 

199 np.radians(decList_icrs), 

200 np.radians(raList_obs), 

201 np.radians(decList_obs))) 

202 

203 for rr, dd, dd_icrs_obs in zip(raList_icrs, decList_icrs, dd_icrs_obs_list): 

204 lon, lat = nativeLonLatFromRaDec(rr, dd, obs) 

205 r1, d1 = raDecFromNativeLonLat(lon, lat, obs) 

206 

207 # the distance between the input RA, Dec and the round-trip output 

208 # RA, Dec 

209 distance = arcsecFromRadians(haversine(np.radians(r1), np.radians(d1), 

210 np.radians(rr), np.radians(dd))) 

211 

212 rr_obs, dec_obs = observedFromICRS(rr, dd, 

213 obs_metadata=obs, epoch=2000.0, includeRefraction=True) 

214 

215 # verify that the round trip through nativeLonLat only changed 

216 # RA, Dec by less than an arcsecond 

217 self.assertLess(distance, 1.0) 

218 

219 # verify that any difference in the round trip is much less 

220 # than the distance between the ICRS and the observed geocentric 

221 # RA, Dec 

222 self.assertLess(distance, dd_icrs_obs * 0.01) 

223 

224 def testRaDecVector(self): 

225 """ 

226 Test that raDecFromNativeLonLat does invert 

227 nativeLonLatFromRaDec (make sure it works in a vectorized way) 

228 """ 

229 rng = np.random.RandomState(42) 

230 nSamples = 100 

231 latList = rng.random_sample(nSamples) * 360.0 

232 lonList = rng.random_sample(nSamples) * 180.0 - 90.0 

233 raPoint = 95.0 

234 decPoint = 75.0 

235 

236 obs = ObservationMetaData( 

237 pointingRA=raPoint, pointingDec=decPoint, mjd=53467.89) 

238 

239 raList, decList = raDecFromNativeLonLat(lonList, latList, obs) 

240 

241 for lon, lat, ra0, dec0 in zip(lonList, latList, raList, decList): 

242 ra1, dec1 = raDecFromNativeLonLat(lon, lat, obs) 

243 distance = arcsecFromRadians(haversine(np.radians(ra0), np.radians(dec0), 

244 np.radians(ra1), np.radians(dec1))) 

245 self.assertLess(distance, 0.1) 

246 

247 def testDegreesVersusRadians(self): 

248 """ 

249 Test that the radian and degree versions of nativeLonLatFromRaDec 

250 and raDecFromNativeLonLat are consistent with each other 

251 """ 

252 

253 rng = np.random.RandomState(873) 

254 nSamples = 1000 

255 obs = ObservationMetaData( 

256 pointingRA=45.0, pointingDec=-34.5, mjd=54656.76) 

257 raList = rng.random_sample(nSamples) * 360.0 

258 decList = rng.random_sample(nSamples) * 180.0 - 90.0 

259 

260 lonDeg, latDeg = nativeLonLatFromRaDec(raList, decList, obs) 

261 lonRad, latRad = _nativeLonLatFromRaDec(np.radians(raList), np.radians(decList), obs) 

262 np.testing.assert_array_almost_equal(np.radians(lonDeg), lonRad, 15) 

263 np.testing.assert_array_almost_equal(np.radians(latDeg), latRad, 15) 

264 

265 raDeg, decDeg = raDecFromNativeLonLat(raList, decList, obs) 

266 raRad, decRad = _raDecFromNativeLonLat(np.radians(raList), np.radians(decList), obs) 

267 np.testing.assert_array_almost_equal(np.radians(raDeg), raRad, 15) 

268 np.testing.assert_array_almost_equal(np.radians(decDeg), decRad, 15) 

269 

270 

271class MemoryTestClass(lsst.utils.tests.MemoryTestCase): 

272 pass 

273 

274if __name__ == "__main__": 274 ↛ 275line 274 didn't jump to line 275, because the condition on line 274 was never true

275 lsst.utils.tests.init() 

276 unittest.main()