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

1import numpy as np 

2from lsst.sims.utils import calcLmstLast 

3 

4__all__ = ['_approx_altAz2RaDec', '_approx_RaDec2AltAz', 'approx_altAz2RaDec', 

5 'approx_RaDec2AltAz', '_approx_altaz2pa', 'approx_altaz2pa'] 

6 

7 

8def _approx_altaz2pa(alt_rad, az_rad, latitude_rad): 

9 """ 

10 A fast calculation of parallactic angle 

11 Parameters 

12 ---------- 

13 alt_rad : float 

14 Altitude (radians) 

15 az_rad : float 

16 Azimuth (radians) 

17 latitude_rad : float 

18 The latitude of the observatory (radians) 

19 """ 

20 

21 y = np.sin(-az_rad)*np.cos(latitude_rad) 

22 x = np.cos(alt_rad)*np.sin(latitude_rad) - np.sin(alt_rad)*np.cos(latitude_rad)*np.cos(-az_rad) 

23 pa = np.arctan2(y, x) 

24 # Make it run from 0-360 deg instead of of -180 to 180 

25 pa = pa % (2.*np.pi) 

26 return pa 

27 

28 

29def approx_altaz2pa(alt_deg, az_deg, latitude_deg): 

30 """ 

31 A fast calculation of parallactic angle 

32 Parameters 

33 ---------- 

34 alt_rad : float 

35 Altitude (degrees) 

36 az_rad : float 

37 Azimuth (degrees) 

38 latitude_rad : float 

39 The latitude of the observatory (degrees) 

40 """ 

41 pa = _approx_altaz2pa(np.radians(alt_deg), np.radians(az_deg), np.radians(latitude_deg)) 

42 return np.degrees(pa) 

43 

44 

45def approx_altAz2RaDec(alt, az, lat, lon, mjd, lmst=None): 

46 """ 

47 Convert alt, az to RA, Dec without taking into account aberration, precession, diffraction, etc. 

48 

49 Parameters 

50 ---------- 

51 alt : numpy.array 

52 Altitude, same length as `ra` and `dec`. Degrees. 

53 az : numpy.array 

54 Azimuth, same length as `ra` and `dec`. Must be same length as `alt`. Degrees. 

55 lat : float 

56 Latitude of the observatory in degrees. 

57 lon : float 

58 Longitude of the observatory in degrees. 

59 mjd : float 

60 Modified Julian Date. 

61 lmst : float (None) 

62 The local mean sidereal time (computed if not given). (hours) 

63 

64 Returns 

65 ------- 

66 ra : array_like 

67 RA, in degrees. 

68 dec : array_like 

69 Dec, in degrees. 

70 """ 

71 ra, dec = _approx_altAz2RaDec(np.radians(alt), np.radians(az), np.radians(lat), 

72 np.radians(lon), mjd, lmst=lmst) 

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

74 

75 

76def _approx_altAz2RaDec(alt, az, lat, lon, mjd, lmst=None): 

77 """ 

78 Convert alt, az to RA, Dec without taking into account aberration, precession, diffraction, etc. 

79 

80 Parameters 

81 ---------- 

82 alt : numpy.array 

83 Altitude, same length as `ra` and `dec`. Radians. 

84 az : numpy.array 

85 Azimuth, same length as `ra` and `dec`. Must be same length as `alt`. Radians. 

86 lat : float 

87 Latitude of the observatory in radians. 

88 lon : float 

89 Longitude of the observatory in radians. 

90 mjd : float 

91 Modified Julian Date. 

92 lmst : float (None) 

93 The local mean sidereal time (computed if not given). (hours) 

94 

95 Returns 

96 ------- 

97 ra : array_like 

98 RA, in radians. 

99 dec : array_like 

100 Dec, in radians. 

101 """ 

102 if lmst is None: 

103 lmst, last = calcLmstLast(mjd, lon) 

104 lmst = lmst/12.*np.pi # convert to rad 

105 sindec = np.sin(lat)*np.sin(alt) + np.cos(lat)*np.cos(alt)*np.cos(az) 

106 sindec = np.clip(sindec, -1, 1) 

107 dec = np.arcsin(sindec) 

108 ha = np.arctan2(-np.sin(az)*np.cos(alt), -np.cos(az)*np.sin(lat)*np.cos(alt)+np.sin(alt)*np.cos(lat)) 

109 ra = (lmst-ha) 

110 raneg = np.where(ra < 0) 

111 ra[raneg] = ra[raneg] + 2.*np.pi 

112 raover = np.where(ra > 2.*np.pi) 

113 ra[raover] -= 2.*np.pi 

114 return ra, dec 

115 

116 

117def approx_RaDec2AltAz(ra, dec, lat, lon, mjd, lmst=None): 

118 """ 

119 Convert Ra,Dec to Altitude and Azimuth. 

120 

121 Coordinate transformation is killing performance. Just use simple equations to speed it up 

122 and ignore aberration, precession, nutation, nutrition, etc. 

123 

124 Parameters 

125 ---------- 

126 ra : array_like 

127 RA, in degrees. 

128 dec : array_like 

129 Dec, in degrees. Must be same length as `ra`. 

130 lat : float 

131 Latitude of the observatory in degrees. 

132 lon : float 

133 Longitude of the observatory in degrees. 

134 mjd : float 

135 Modified Julian Date. 

136 lmst : float (None) 

137 The local mean sidereal time (computed if not given). (hours) 

138 

139 Returns 

140 ------- 

141 alt : numpy.array 

142 Altitude, same length as `ra` and `dec`. degrees. 

143 az : numpy.array 

144 Azimuth, same length as `ra` and `dec`. degrees. 

145 """ 

146 alt, az = _approx_RaDec2AltAz(np.radians(ra), np.radians(dec), np.radians(lat), 

147 np.radians(lon), mjd, lmst=lmst) 

148 return np.degrees(alt), np.degrees(az) 

149 

150 

151def _approx_RaDec2AltAz(ra, dec, lat, lon, mjd, lmst=None, return_pa=False): 

152 """ 

153 Convert Ra,Dec to Altitude and Azimuth. 

154 

155 Coordinate transformation is killing performance. Just use simple equations to speed it up 

156 and ignore aberration, precession, nutation, nutrition, etc. 

157 

158 Parameters 

159 ---------- 

160 ra : array_like 

161 RA, in radians. 

162 dec : array_like 

163 Dec, in radians. Must be same length as `ra`. 

164 lat : float 

165 Latitude of the observatory in radians. 

166 lon : float 

167 Longitude of the observatory in radians. 

168 mjd : float 

169 Modified Julian Date. 

170 lmst : float (None) 

171 The local mean sidereal time (computed if not given). (hours) 

172 

173 Returns 

174 ------- 

175 alt : numpy.array 

176 Altitude, same length as `ra` and `dec`. Radians. 

177 az : numpy.array 

178 Azimuth, same length as `ra` and `dec`. Radians. 

179 """ 

180 if lmst is None: 

181 lmst, last = calcLmstLast(mjd, lon) 

182 lmst = lmst/12.*np.pi # convert to rad 

183 ha = lmst-ra 

184 sindec = np.sin(dec) 

185 sinlat = np.sin(lat) 

186 coslat = np.cos(lat) 

187 sinalt = sindec*sinlat+np.cos(dec)*coslat*np.cos(ha) 

188 sinalt = np.clip(sinalt, -1, 1) 

189 alt = np.arcsin(sinalt) 

190 cosaz = (sindec-np.sin(alt)*sinlat)/(np.cos(alt)*coslat) 

191 cosaz = np.clip(cosaz, -1, 1) 

192 az = np.arccos(cosaz) 

193 if np.size(ha) < 2: 

194 if np.sin(ha) > 0: 

195 az = 2.*np.pi-az 

196 else: 

197 signflip = np.where(np.sin(ha) > 0) 

198 az[signflip] = 2.*np.pi-az[signflip] 

199 if return_pa: 

200 pa = _approx_altaz2pa(alt, az, lat) 

201 return alt, az, pa 

202 return alt, az