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 

2import ephem 

3from lsst.sims.utils import _galacticFromEquatorial, calcLmstLast 

4 

5from .baseStacker import BaseStacker 

6from .ditherStackers import wrapRA 

7 

8__all__ = ['mjd2djd', 'raDec2AltAz', 'GalacticStacker', 'EclipticStacker'] 

9 

10 

11def mjd2djd(mjd): 

12 """Convert MJD to the Dublin Julian date used by ephem. 

13 

14 Parameters 

15 ---------- 

16 mjd : float or numpy.ndarray 

17 The modified julian date. 

18 Returns 

19 ------- 

20 float or numpy.ndarray 

21 The dublin julian date. 

22 """ 

23 doff = ephem.Date(0)-ephem.Date('1858/11/17') 

24 djd = mjd-doff 

25 return djd 

26 

27 

28def raDec2AltAz(ra, dec, lat, lon, mjd, altonly=False): 

29 """Convert RA/Dec (and telescope site lat/lon) to alt/az. 

30 

31 This uses simple equations and ignores aberation, precession, nutation, etc. 

32 

33 Parameters 

34 ---------- 

35 ra : array_like 

36 RA, in radians. 

37 dec : array_like 

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

39 lat : float 

40 Latitude of the observatory in radians. 

41 lon : float 

42 Longitude of the observatory in radians. 

43 mjd : float 

44 Modified Julian Date. 

45 altonly : bool, opt 

46 Calculate altitude only. 

47 

48 Returns 

49 ------- 

50 alt : numpy.array 

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

52 az : numpy.array 

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

54 """ 

55 lmst, last = calcLmstLast(mjd, lon) 

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

57 ha = lmst - ra 

58 sindec = np.sin(dec) 

59 sinlat = np.sin(lat) 

60 coslat = np.cos(lat) 

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

62 # make sure sinalt is in the expected range. 

63 sinalt = np.where(sinalt < -1, -1, sinalt) 

64 sinalt = np.where(sinalt > 1, 1, sinalt) 

65 alt = np.arcsin(sinalt) 

66 if altonly: 

67 az = None 

68 else: 

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

70 cosaz = np.where(cosaz < -1, -1, cosaz) 

71 cosaz = np.where(cosaz > 1, 1, cosaz) 

72 az = np.arccos(cosaz) 

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

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

75 return alt, az 

76 

77 

78class GalacticStacker(BaseStacker): 

79 """Add the galactic coordinates of each RA/Dec pointing: gall, galb 

80 

81 Parameters 

82 ---------- 

83 raCol : str, opt 

84 Name of the RA column. Default fieldRA. 

85 decCol : str, opt 

86 Name of the Dec column. Default fieldDec. 

87 """ 

88 colsAdded = ['gall', 'galb'] 

89 

90 def __init__(self, raCol='fieldRA', decCol='fieldDec', degrees=True): 

91 self.colsReq = [raCol, decCol] 

92 self.raCol = raCol 

93 self.decCol = decCol 

94 self.degrees = degrees 

95 if self.degrees: 95 ↛ 98line 95 didn't jump to line 98, because the condition on line 95 was never false

96 self.units = ['degrees', 'degrees'] 

97 else: 

98 self.units = ['radians', 'radians'] 

99 

100 def _run(self, simData, cols_present=False): 

101 # raCol and DecCol in radians, gall/b in radians. 

102 if cols_present: 

103 # Column already present in data; assume it is correct and does not need recalculating. 

104 return simData 

105 if self.degrees: 

106 simData['gall'], simData['galb'] = _galacticFromEquatorial(np.radians(simData[self.raCol]), 

107 np.radians(simData[self.decCol])) 

108 else: 

109 simData['gall'], simData['galb'] = _galacticFromEquatorial(simData[self.raCol], 

110 simData[self.decCol]) 

111 return simData 

112 

113 

114class EclipticStacker(BaseStacker): 

115 """Add the ecliptic coordinates of each RA/Dec pointing: eclipLat, eclipLon 

116 Optionally subtract off the sun's ecliptic longitude and wrap. 

117 

118 Parameters 

119 ---------- 

120 mjdCol : str, opt 

121 Name of the MJD column. Default expMJD. 

122 raCol : str, opt 

123 Name of the RA column. Default fieldRA. 

124 decCol : str, opt 

125 Name of the Dec column. Default fieldDec. 

126 subtractSunLon : bool, opt 

127 Flag to subtract the sun's ecliptic longitude. Default False. 

128 """ 

129 colsAdded = ['eclipLat', 'eclipLon'] 

130 

131 def __init__(self, mjdCol='observationStartMJD', raCol='fieldRA', decCol='fieldDec', degrees=True, 

132 subtractSunLon=False): 

133 

134 self.colsReq = [mjdCol, raCol, decCol] 

135 self.subtractSunLon = subtractSunLon 

136 self.degrees = degrees 

137 if self.degrees: 137 ↛ 140line 137 didn't jump to line 140, because the condition on line 137 was never false

138 self.units = ['degrees', 'degrees'] 

139 else: 

140 self.units = ['radians', 'radians'] 

141 self.mjdCol = mjdCol 

142 self.raCol = raCol 

143 self.decCol = decCol 

144 

145 def _run(self, simData, cols_present=False): 

146 if cols_present: 

147 # Column already present in data; assume it is correct and does not need recalculating. 

148 return simData 

149 for i in np.arange(simData.size): 

150 if self.degrees: 

151 coord = ephem.Equatorial(np.radians(simData[self.raCol][i]), 

152 np.radians(simData[self.decCol][i]), epoch=2000) 

153 else: 

154 coord = ephem.Equatorial(simData[self.raCol][i], 

155 simData[self.decCol][i], epoch=2000) 

156 ecl = ephem.Ecliptic(coord) 

157 simData['eclipLat'][i] = ecl.lat 

158 if self.subtractSunLon: 

159 djd = mjd2djd(simData[self.mjdCol][i]) 

160 sun = ephem.Sun(djd) 

161 sunEcl = ephem.Ecliptic(sun) 

162 lon = wrapRA(ecl.lon - sunEcl.lon) 

163 simData['eclipLon'][i] = lon 

164 else: 

165 simData['eclipLon'][i] = ecl.lon 

166 if self.degrees: 

167 simData['eclipLon'] = np.degrees(simData['eclipLon']) 

168 simData['eclipLat'] = np.degrees(simData['eclipLat']) 

169 return simData