Coverage for python/lsst/sims/utils/CompoundCoordinateTransformations.py : 21%

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
1"""
2This file contains coordinate transformations that rely on both
3palpy and the contents of AstrometryUtils.py (basically, coordinate
4transformations that need to transform between observed geocentric RA, DEC
5and ICRS RA, Dec)
6"""
7from __future__ import division
9import numpy as np
10import palpy
11from lsst.sims.utils.CodeUtilities import _validate_inputs
12from lsst.sims.utils import _icrsFromObserved, _observedFromICRS, calcLmstLast
14__all__ = ["_altAzPaFromRaDec", "altAzPaFromRaDec",
15 "_raDecFromAltAz", "raDecFromAltAz",
16 "getRotTelPos", "_getRotTelPos",
17 "getRotSkyPos", "_getRotSkyPos"]
20def altAzPaFromRaDec(ra, dec, obs, includeRefraction=True):
21 """
22 Convert RA, Dec, longitude, latitude and MJD into altitude, azimuth
23 and parallactic angle using PALPY
25 @param [in] ra is RA in degrees. Can be a numpy array or a single value.
26 Assumed to be in the International Celestial Reference System.
28 @param [in] dec is Dec in degrees. Can be a numpy array or a single value.
29 Assumed to be in the International Celestial Reference System.
31 @param [in] obs is an ObservationMetaData characterizing
32 the site of the telescope and the MJD of the observation
34 @param [in] includeRefraction is a boolean that turns refraction on and off
35 (default True)
37 @param [out] altitude in degrees
39 @param [out] azimuth in degrees
41 @param [out] parallactic angle in degrees
43 WARNING: This method does not account for apparent motion due to parallax.
44 This method is only useful for mapping positions on a theoretical celestial
45 sphere.
46 """
48 alt, az, pa = _altAzPaFromRaDec(np.radians(ra), np.radians(dec),
49 obs, includeRefraction=includeRefraction)
51 return np.degrees(alt), np.degrees(az), np.degrees(pa)
54def _altAzPaFromRaDec(raRad, decRad, obs, includeRefraction=True):
55 """
56 Convert RA, Dec, longitude, latitude and MJD into altitude, azimuth
57 and parallactic angle using PALPY
59 @param [in] raRad is RA in radians. Can be a numpy array or a single value.
60 Assumed to be in the International Celestial Reference System.
62 @param [in] decRad is Dec in radians. Can be a numpy array or a single value.
63 Assumed to be in the International Celestial Reference System.
65 @param [in] obs is an ObservationMetaData characterizing
66 the site of the telescope and the MJD of the observation
68 @param [in] includeRefraction is a boolean that turns refraction on and off
69 (default True)
71 @param [out] altitude in radians
73 @param [out] azimuth in radians
75 @param [out] parallactic angle in radians
77 WARNING: This method does not account for apparent motion due to parallax.
78 This method is only useful for mapping positions on a theoretical focal plan
79 to positions on the celestial sphere.
80 """
82 are_arrays = _validate_inputs([raRad, decRad], ['ra', 'dec'],
83 "altAzPaFromRaDec")
85 raObs, decObs = \
86 _observedFromICRS(raRad, decRad, obs_metadata=obs,
87 epoch=2000.0, includeRefraction=includeRefraction)
89 lst = calcLmstLast(obs.mjd.UT1, obs.site.longitude_rad)
90 last = lst[1]
91 haRad = np.radians(last * 15.0) - raObs
93 if are_arrays:
94 az, azd, azdd, \
95 alt, altd, altdd, \
96 pa, pad, padd = palpy.altazVector(
97 haRad, decObs, obs.site.latitude_rad)
98 else:
99 az, azd, azdd, \
100 alt, altd, altdd, \
101 pa, pad, padd = palpy.altaz(haRad, decObs, obs.site.latitude_rad)
103 return alt, az, pa
106def raDecFromAltAz(alt, az, obs, includeRefraction=True):
107 """
108 Convert altitude and azimuth to RA and Dec
110 @param [in] alt is the altitude in degrees. Can be a numpy array or a single value.
112 @param [in] az is the azimuth in degrees. Cant be a numpy array or a single value.
114 @param [in] obs is an ObservationMetaData characterizing
115 the site of the telescope and the MJD of the observation
117 @param [in] includeRefraction is a boolean that turns refraction on and off
118 (default True)
120 @param [out] RA in degrees (in the International Celestial Reference System)
122 @param [out] Dec in degrees (in the International Celestial Reference System)
124 Note: This method is only accurate to within 0.01 arcsec near azimuth = 0 or pi
125 """
127 ra, dec = _raDecFromAltAz(np.radians(alt), np.radians(az), obs,
128 includeRefraction=includeRefraction)
130 return np.degrees(ra), np.degrees(dec)
133def _raDecFromAltAz(altRad, azRad, obs, includeRefraction=True):
134 """
135 Convert altitude and azimuth to RA and Dec
137 @param [in] altRad is the altitude in radians. Can be a numpy array or a single value.
139 @param [in] azRad is the azimuth in radians. Cant be a numpy array or a single value.
141 @param [in] obs is an ObservationMetaData characterizing
142 the site of the telescope and the MJD of the observation
144 @param [in] includeRefraction is a boolean that turns refraction on and off
145 (default True)
147 @param [out] RA in radians (in the International Celestial Reference System)
149 @param [out] Dec in radians (in the International Celestial Reference System)
151 Note: This method is only accurate to within 0.01 arcsec near azimuth = 0 or pi
152 """
154 with np.errstate(invalid='ignore', divide='ignore'):
155 are_arrays = _validate_inputs(
156 [altRad, azRad], ['altRad', 'azRad'], "raDecFromAltAz")
158 lst = calcLmstLast(obs.mjd.UT1, obs.site.longitude_rad)
159 last = lst[1]
160 sinAlt = np.sin(altRad)
161 cosLat = np.cos(obs.site.latitude_rad)
162 sinLat = np.sin(obs.site.latitude_rad)
163 decObs = np.arcsin(sinLat * sinAlt + cosLat *
164 np.cos(altRad) * np.cos(azRad))
165 costheta = (sinAlt - np.sin(decObs) * sinLat) / (np.cos(decObs) * cosLat)
166 if are_arrays:
167 haRad0 = np.arccos(costheta)
168 # Make sure there were no NaNs
169 nanSpots = np.where(np.isnan(haRad0))[0]
170 if np.size(nanSpots) > 0:
171 haRad0[nanSpots] = 0.5 * np.pi * \
172 (1.0 - np.sign(costheta[nanSpots]))
173 else:
174 haRad0 = np.arccos(costheta)
175 if np.isnan(haRad0):
176 if np.sign(costheta) > 0.0:
177 haRad0 = 0.0
178 else:
179 haRad0 = np.pi
181 haRad = np.where(np.sin(azRad) >= 0.0, -1.0 * haRad0, haRad0)
182 raObs = np.radians(last * 15.) - haRad
184 raRad, decRad = _icrsFromObserved(raObs, decObs,
185 obs_metadata=obs, epoch=2000.0,
186 includeRefraction=includeRefraction)
188 return raRad, decRad
191def getRotSkyPos(ra, dec, obs, rotTel):
192 """
193 @param [in] ra is the RA in degrees. Can be a numpy array or a single value.
194 (In the International Celestial Reference System)
196 @param [in] dec is Dec in degrees. Can be a numpy array or a single value.
197 (In the International Celestial Reference System)
199 @param [in] obs is an ObservationMetaData characterizing the telescope pointing
200 and site.
202 @param [in] rotTel is rotTelPos in degrees
203 (the angle of the camera rotator). Can be a numpy array or a single value.
204 If a numpy array, should have the same length as ra and dec. In this case,
205 each rotTel will be associated with the corresponding ra, dec pair.
207 @param [out] rotSkyPos in degrees
209 WARNING: As of 13 April 2015, this method does not agree with OpSim on
210 the relationship between rotSkyPos and rotTelPos. This is due to a
211 discrepancy between the time that OpSim uses as the MJD when calculating
212 rotTelPos and the time that OpSim reports as being the actual expmjd
213 of the exposure (rotTelPos is calculated at the beginning of the exposure;
214 expmjd is reckoned at the middle of the exposure).
215 """
217 rotSky = _getRotSkyPos(np.radians(ra), np.radians(dec),
218 obs, np.radians(rotTel))
220 return np.degrees(rotSky)
223def _getRotSkyPos(raRad, decRad, obs, rotTelRad):
224 """
225 @param [in] raRad is the RA in radians. Can be a numpy array or a single value.
226 (In the International Celestial Reference System)
228 @param [in] decRad is Dec in radians. Can be a numpy array or a single value.
229 (In the International Celestial Reference System)
231 @param [in] obs is an ObservationMetaData characterizing the telescope pointing
232 and site.
234 @param [in] rotTelRad is rotTelPos in radians
235 (the angle of the camera rotator). Can be a numpy array or a single value.
236 If a numpy array, should have the same length as raRad and decRad. In this case,
237 each rotTelRad will be associated with the corresponding raRad, decRad pair.
239 @param [out] rotSkyPos in radians
241 WARNING: As of 13 April 2015, this method does not agree with OpSim on
242 the relationship between rotSkyPos and rotTelPos. This is due to a
243 discrepancy between the time that OpSim uses as the MJD when calculating
244 rotTelPos and the time that OpSim reports as being the actual expmjd
245 of the exposure (rotTelPos is calculated at the beginning of the exposure;
246 expmjd is reckoned at the middle of the exposure).
247 """
248 altRad, azRad, paRad = _altAzPaFromRaDec(raRad, decRad, obs)
250 return (rotTelRad - paRad) % (2. * np.pi)
253def getRotTelPos(ra, dec, obs, rotSky):
254 """
255 @param [in] ra is RA in degrees. Can be a numpy array or a single value.
256 (In the International Celestial Reference System)
258 @param [in] dec is Dec in degrees. Can be a numpy array or a single value.
259 (In the International Celestial Reference System)
261 @param [in] obs is an ObservationMetaData characterizing the telescope pointing
262 and site.
264 @param [in] rotSky is rotSkyPos in degrees
265 (the angle of the field of view relative to the South pole given a
266 rotator angle). Can be a numpy array or a single value. If a numpy array, should
267 have the same length as ra and dec. In this case, each rotSkyPos
268 will be associated with the corresponding ra, dec pair.
270 @param [out] rotTelPos in degrees.
272 WARNING: As of 13 April 2015, this method does not agree with OpSim on
273 the relationship between rotSkyPos and rotTelPos. This is due to a
274 discrepancy between the time that OpSim uses as the MJD when calculating
275 rotTelPos and the time that OpSim reports as being the actual expmjd
276 of the exposure (rotTelPos is calculated at the beginning of the exposure;
277 expmjd is reckoned at the middle of the exposure).
278 """
279 rotTel = _getRotTelPos(np.radians(ra), np.radians(dec),
280 obs, np.radians(rotSky))
282 return np.degrees(rotTel)
285def _getRotTelPos(raRad, decRad, obs, rotSkyRad):
286 """
287 @param [in] raRad is RA in radians. Can be a numpy array or a single value.
288 (In the International Celestial Reference System)
290 @param [in] decRad is Dec in radians. Can be a numpy array or a single value.
291 (In the International Celestial Reference System)
293 @param [in] obs is an ObservationMetaData characterizing the telescope pointing
294 and site.
296 @param [in] rotSkyRad is rotSkyPos in radians
297 (the angle of the field of view relative to the South pole given a
298 rotator angle). Can be a numpy array or a single value. If a numpy array, should
299 have the same length as raRad and decRad. In this case, each rotSkyPos
300 will be associated with the corresponding raRad, decRad pair.
302 @param [out] rotTelPos in radians.
304 WARNING: As of 13 April 2015, this method does not agree with OpSim on
305 the relationship between rotSkyPos and rotTelPos. This is due to a
306 discrepancy between the time that OpSim uses as the MJD when calculating
307 rotTelPos and the time that OpSim reports as being the actual expmjd
308 of the exposure (rotTelPos is calculated at the beginning of the exposure;
309 expmjd is reckoned at the middle of the exposure).
310 """
311 altRad, azRad, paRad = _altAzPaFromRaDec(raRad, decRad, obs)
313 return (rotSkyRad + paRad) % (2. * np.pi)