Coverage for python/lsst/sims/maf/stackers/coordStackers.py : 32%

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
5from .baseStacker import BaseStacker
6from .ditherStackers import wrapRA
8__all__ = ['mjd2djd', 'raDec2AltAz', 'GalacticStacker', 'EclipticStacker']
11def mjd2djd(mjd):
12 """Convert MJD to the Dublin Julian date used by ephem.
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
28def raDec2AltAz(ra, dec, lat, lon, mjd, altonly=False):
29 """Convert RA/Dec (and telescope site lat/lon) to alt/az.
31 This uses simple equations and ignores aberation, precession, nutation, etc.
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.
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
78class GalacticStacker(BaseStacker):
79 """Add the galactic coordinates of each RA/Dec pointing: gall, galb
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']
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']
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
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.
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']
131 def __init__(self, mjdCol='observationStartMJD', raCol='fieldRA', decCol='fieldDec', degrees=True,
132 subtractSunLon=False):
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
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