1
2 """
3 Compute the influence of earth's orbit around the sun, and absolute stellar velocities
4 """
5
6 import numpy as np
7 from ivs.units.conversions import convert
8
10 """
11 Calculates heliocentric and barycentric velocity components of Earth.
12
13 This function takes into account the Earth-Moon motion, and is useful for
14 radial velocity work to an accuracy of ~1 m/s.
15
16 dvel_hel, dvel_bary = baryvel(dje, deq)
17
18 Inputs:
19 @param dje: Julian ephemeris date.
20 @type dje: array
21 @param deq: epoch of mean equinox of dvelh and dvelb. If deq = 0 then deq is assumed to be equal to dje
22 @type deq: float
23 @return: heliocentric and barycentric velocity components in km/s (The 3-vectors dvelh and dvelb are given in a right-handed coordinate system with the +X axis toward the Vernal Equinox, and +Z axis toward the celestial pole.)
24 @rtype: array (2X3)
25
26 Functions called:
27 premat() -- computes precession matrix
28
29 NOTES:
30 Algorithm taken from FORTRAN program of Stumpff (1980, A&A Suppl, 41,1)
31 Stumpf claimed an accuracy of 42 cm/s for the velocity. A comparison with
32 the JPL FORTRAN planetary ephemeris program PLEPH found agreement to within
33 about 65 cm/s between 1986 and 1994
34
35 REVISION HISTORY:
36 Jeff Valenti, U.C. Berkeley Translated BARVEL.FOR to IDL.
37 W. Landsman, Cleaned up program sent by Chris McCarthy (SfSU) June 1994
38 Converted to IDL V5.0 W. Landsman September 1997
39 Added /JPL keyword W. Landsman July 2001
40 Documentation update W. Landsman Dec 2005
41 Converted to Python S. Koposov 2009-2010
42 Adapted for IvS library
43 """
44
45
46 dc2pi = 2 * np.pi
47 cc2pi = 2 * np.pi
48 dc1 = 1.0e0
49 dcto = 2415020.0e0
50 dcjul = 36525.0e0
51 dcbes = 0.313e0
52 dctrop = 365.24219572e0
53 dc1900 = 1900.0e0
54 au = 1.4959787e8
55
56
57 dcfel = np.array([1.7400353e00, 6.2833195099091e02, 5.2796e-6, 6.2565836e00, 6.2830194572674e02, -2.6180e-6, 4.7199666e00, 8.3997091449254e03, -1.9780e-5, 1.9636505e-1, 8.4334662911720e03, -5.6044e-5, 4.1547339e00, 5.2993466764997e01, 5.8845e-6, 4.6524223e00, 2.1354275911213e01, 5.6797e-6, 4.2620486e00, 7.5025342197656e00, 5.5317e-6, 1.4740694e00, 3.8377331909193e00, 5.6093e-6])
58 dcfel = np.reshape(dcfel, (8, 3))
59
60
61 dceps = np.array([4.093198e-1, -2.271110e-4, -2.860401e-8])
62 ccsel = np.array([1.675104e-2, -4.179579e-5, -1.260516e-7, 2.220221e-1, 2.809917e-2, 1.852532e-5, 1.589963e00, 3.418075e-2, 1.430200e-5, 2.994089e00, 2.590824e-2, 4.155840e-6, 8.155457e-1, 2.486352e-2, 6.836840e-6, 1.735614e00, 1.763719e-2, 6.370440e-6, 1.968564e00, 1.524020e-2, -2.517152e-6, 1.282417e00, 8.703393e-3, 2.289292e-5, 2.280820e00, 1.918010e-2, 4.484520e-6, 4.833473e-2, 1.641773e-4, -4.654200e-7, 5.589232e-2, -3.455092e-4, -7.388560e-7, 4.634443e-2, -2.658234e-5, 7.757000e-8, 8.997041e-3, 6.329728e-6, -1.939256e-9, 2.284178e-2, -9.941590e-5, 6.787400e-8, 4.350267e-2, -6.839749e-5, -2.714956e-7, 1.348204e-2, 1.091504e-5, 6.903760e-7, 3.106570e-2, -1.665665e-4, -1.590188e-7])
63 ccsel = np.reshape(ccsel, (17, 3))
64
65
66 dcargs = np.array([5.0974222e0, -7.8604195454652e2, 3.9584962e0, -5.7533848094674e2, 1.6338070e0, -1.1506769618935e3, 2.5487111e0, -3.9302097727326e2, 4.9255514e0, -5.8849265665348e2, 1.3363463e0, -5.5076098609303e2, 1.6072053e0, -5.2237501616674e2, 1.3629480e0, -1.1790629318198e3, 5.5657014e0, -1.0977134971135e3, 5.0708205e0, -1.5774000881978e2, 3.9318944e0, 5.2963464780000e1, 4.8989497e0, 3.9809289073258e1, 1.3097446e0, 7.7540959633708e1, 3.5147141e0, 7.9618578146517e1, 3.5413158e0, -5.4868336758022e2])
67 dcargs = np.reshape(dcargs, (15, 2))
68
69
70 ccamps = np.array([-2.279594e-5, 1.407414e-5, 8.273188e-6, 1.340565e-5, -2.490817e-7, -3.494537e-5, 2.860401e-7, 1.289448e-7, 1.627237e-5, -1.823138e-7, 6.593466e-7, 1.322572e-5, 9.258695e-6, -4.674248e-7, -3.646275e-7, 1.140767e-5, -2.049792e-5, -4.747930e-6, -2.638763e-6, -1.245408e-7, 9.516893e-6, -2.748894e-6, -1.319381e-6, -4.549908e-6, -1.864821e-7, 7.310990e-6, -1.924710e-6, -8.772849e-7, -3.334143e-6, -1.745256e-7, -2.603449e-6, 7.359472e-6, 3.168357e-6, 1.119056e-6, -1.655307e-7, -3.228859e-6, 1.308997e-7, 1.013137e-7, 2.403899e-6, -3.736225e-7, 3.442177e-7, 2.671323e-6, 1.832858e-6, -2.394688e-7, -3.478444e-7, 8.702406e-6, -8.421214e-6, -1.372341e-6, -1.455234e-6, -4.998479e-8, -1.488378e-6, -1.251789e-5, 5.226868e-7, -2.049301e-7, 0.e0, -8.043059e-6, -2.991300e-6, 1.473654e-7, -3.154542e-7, 0.e0, 3.699128e-6, -3.316126e-6, 2.901257e-7, 3.407826e-7, 0.e0, 2.550120e-6, -1.241123e-6, 9.901116e-8, 2.210482e-7, 0.e0, -6.351059e-7, 2.341650e-6, 1.061492e-6, 2.878231e-7, 0.e0])
71 ccamps = np.reshape(ccamps, (15, 5))
72
73
74 ccsec3 = -7.757020e-8
75 ccsec = np.array([1.289600e-6, 5.550147e-1, 2.076942e00, 3.102810e-5, 4.035027e00, 3.525565e-1, 9.124190e-6, 9.990265e-1, 2.622706e00, 9.793240e-7, 5.508259e00, 1.559103e01])
76 ccsec = np.reshape(ccsec, (4, 3))
77
78
79 dcsld = 1.990987e-7
80 ccsgd = 1.990969e-7
81
82
83 cckm = 3.122140e-5
84 ccmld = 2.661699e-6
85 ccfdi = 2.399485e-7
86
87
88
89 dcargm = np.array([5.1679830e0, 8.3286911095275e3, 5.4913150e0, -7.2140632838100e3, 5.9598530e0, 1.5542754389685e4])
90 dcargm = np.reshape(dcargm, (3, 2))
91
92
93 ccampm = np.array([1.097594e-1, 2.896773e-7, 5.450474e-2, 1.438491e-7, -2.223581e-2, 5.083103e-8, 1.002548e-2, -2.291823e-8, 1.148966e-2, 5.658888e-8, 8.249439e-3, 4.063015e-8])
94 ccampm = np.reshape(ccampm, (3, 4))
95
96
97 ccpamv = np.array([8.326827e-11, 1.843484e-11, 1.988712e-12, 1.881276e-12])
98 dc1mme = 0.99999696e0
99
100
101 dt = (dje - dcto) / dcjul
102 tvec = np.array([1e0, dt, dt * dt])
103
104
105 temp = (np.transpose(np.dot(np.transpose(tvec), np.transpose(dcfel)))) % dc2pi
106 dml = temp[0]
107 forbel = temp[1:8]
108 g = forbel[0]
109
110 deps = (tvec * dceps).sum() % dc2pi
111 sorbel = (np.transpose(np.dot(np.transpose(tvec), np.transpose(ccsel)))) % dc2pi
112 e = sorbel[0]
113
114
115 dummy = np.cos(2.0)
116 sn = np.sin((np.transpose(np.dot(np.transpose(tvec[0:2]), np.transpose(ccsec[:,1:3])))) % cc2pi)
117
118
119 pertl = (ccsec[:,0] * sn).sum() + dt * ccsec3 * sn[2]
120 pertld = 0.0
121 pertr = 0.0
122 pertrd = 0.0
123 for k in range(0, 15):
124 a = (dcargs[k,0] + dt * dcargs[k,1]) % dc2pi
125 cosa = np.cos(a)
126 sina = np.sin(a)
127 pertl = pertl + ccamps[k,0] * cosa + ccamps[k,1] * sina
128 pertr = pertr + ccamps[k,2] * cosa + ccamps[k,3] * sina
129 if k < 11:
130 pertld = pertld + (ccamps[k,1] * cosa - ccamps[k,0] * sina) * ccamps[k,4]
131 pertrd = pertrd + (ccamps[k,3] * cosa - ccamps[k,2] * sina) * ccamps[k,4]
132
133
134 phi = (e * e / 4e0) * (((8e0 / e) - e) * np.sin(g) + 5 * np.sin(2 * g) + (13 / 3e0) * e * np.sin(3 * g))
135 f = g + phi
136 sinf = np.sin(f)
137 cosf = np.cos(f)
138 dpsi = (dc1 - e * e) / (dc1 + e * cosf)
139 phid = 2 * e * ccsgd * ((1 + 1.5 * e * e) * cosf + e * (1.25 - 0.5 * sinf * sinf))
140 psid = ccsgd * e * sinf / np.sqrt(dc1 - e * e)
141
142
143 d1pdro = dc1 + pertr
144 drd = d1pdro * (psid + dpsi * pertrd)
145 drld = d1pdro * dpsi * (dcsld + phid + pertld)
146 dtl = (dml + phi + pertl) % dc2pi
147 dsinls = np.sin(dtl)
148 dcosls = np.cos(dtl)
149 dxhd = drd * dcosls - drld * dsinls
150 dyhd = drd * dsinls + drld * dcosls
151
152
153
154 pertl = 0.0
155 pertld = 0.0
156 pertp = 0.0
157 pertpd = 0.0
158 for k in range(0, 3):
159 a = (dcargm[k,0] + dt * dcargm[k,1]) % dc2pi
160 sina = np.sin(a)
161 cosa = np.cos(a)
162 pertl = pertl + ccampm[k,0] * sina
163 pertld = pertld + ccampm[k,1] * cosa
164 pertp = pertp + ccampm[k,2] * cosa
165 pertpd = pertpd - ccampm[k,3] * sina
166
167
168 tl = forbel[1] + pertl
169 sinlm = np.sin(tl)
170 coslm = np.cos(tl)
171 sigma = cckm / (1.0 + pertp)
172 a = sigma * (ccmld + pertld)
173 b = sigma * pertpd
174 dxhd = dxhd + a * sinlm + b * coslm
175 dyhd = dyhd - a * coslm + b * sinlm
176 dzhd = -sigma * ccfdi * np.cos(forbel[2])
177
178
179 dxbd = dxhd * dc1mme
180 dybd = dyhd * dc1mme
181 dzbd = dzhd * dc1mme
182 for k in range(0, 4):
183 plon = forbel[k + 3]
184 pomg = sorbel[k + 1]
185 pecc = sorbel[k + 9]
186 tl = (plon + 2.0 * pecc * np.sin(plon - pomg)) % cc2pi
187 dxbd = dxbd + ccpamv[k] * (np.sin(tl) + pecc * np.sin(pomg))
188 dybd = dybd - ccpamv[k] * (np.cos(tl) + pecc * np.cos(pomg))
189 dzbd = dzbd - ccpamv[k] * sorbel[k + 13] * np.cos(plon - sorbel[k + 5])
190
191
192 dcosep = np.cos(deps)
193 dsinep = np.sin(deps)
194 dyahd = dcosep * dyhd - dsinep * dzhd
195 dzahd = dsinep * dyhd + dcosep * dzhd
196 dyabd = dcosep * dybd - dsinep * dzbd
197 dzabd = dsinep * dybd + dcosep * dzbd
198
199
200
201 if deq == 0:
202 dvelh = au * (np.array([dxhd, dyahd, dzahd]))
203 dvelb = au * (np.array([dxbd, dyabd, dzabd]))
204 return (dvelh,dvelb)
205
206
207 deqdat = (dje - dcto - dcbes) / dctrop + dc1900
208 prema = premat(deqdat, deq, fk4=True)
209 dvelh = au * (np.transpose(np.dot(np.transpose(prema), np.transpose(np.array([dxhd, dyahd, dzahd])))))
210 dvelb = au * (np.transpose(np.dot(np.transpose(prema), np.transpose(np.array([dxbd, dyabd, dzabd])))))
211
212 return (dvelh, dvelb)
213
214 -def bprecess(ra0, dec0, mu_radec=None, parallax=None, rad_vel=None, epoch=None):
215 """
216 Precess positions from J2000.0 (FK5) to B1950.0 (FK4)
217
218 Calculates the mean place of a star at B1950.0 on the FK4 system from the mean
219 place at J2000.0 on the FK5 system.
220
221 Input:
222 @param ra0: J2000 right ascension in degrees
223 @type ra0: N array
224 @param dec0: J2000 declination in degrees
225 @type dec0: N array
226 @keyword mu_radec: array containing the proper motion in seconds of arc per tropical *century* in right ascension and declination.
227 @type mu_radec: 2xN array
228 @keyword parallax: array giving stellar parallax (seconds of arc)
229 @type parallax: N array
230 @keyword rad_vel: array giving radial velocity in km/s
231 @type rad_vel: N array
232 @keyword epoch: scalar giving epoch of original observations, default 2000. This keyword value is only used if mu_radec is not given
233 @type epoch:
234 @return: The corresponding B1950 right ascension and declination in *degrees*.
235 @rtype: N array, N array
236
237 NOTES:
238 The algorithm is taken from the Explanatory Supplement to the Astronomical Almanac 1992, page 186. Also see Aoki et al (1983), A&A, 128,263
239
240 BPRECESS distinguishes between the following two cases:
241 (1) The proper motion is known and non-zero
242 (2) the proper motion is unknown or known to be exactly zero (i.e.
243 extragalactic radio sources). In this case, the reverse of the
244 algorithm in Appendix 2 of Aoki et al. (1983) is used to ensure that the
245 output proper motion is exactly zero. Better precision can be achieved
246 in this case by inputting the epoch of the original observations.
247
248 REVISION HISTORY:
249 Written (W. Landsman, october 1992)
250 Vectorized (W. Landsman, february, 1994)
251 Treat case where proper motion not known or exactly zero (november 1994)
252 Handling of arrays larger than 32767 (Lars L. Christensen, march 1995)
253 Converted to IDL V5.0 (W. Landsman, september 1997)
254 Fixed bug where A term not initialized for vector input (W. Landsman, february 2000)
255 Converted to python (Sergey Koposov, july 2010)
256 """
257 scal = True
258 if isinstance(ra0, np.ndarray):
259 ra = ra0
260 dec = dec0
261 n = ra.size
262 scal = False
263 else:
264 n = 1
265 ra = np.array([ra0])
266 dec = np.array([dec0])
267
268 if rad_vel is None:
269 rad_vel = np.zeros(n)
270 else:
271 if not isinstance(rad_vel, np.ndarray):
272 rad_vel = np.array([rad_vel],dtype=float)
273 if rad_vel.size != n:
274 raise Exception('ERROR - RAD_VEL keyword vector must be of the same length as RA and DEC')
275
276 if (mu_radec is not None):
277 if (np.array(mu_radec).size != 2 * n):
278 raise Exception('ERROR - MU_RADEC keyword (proper motion) be dimensioned (2,' + strtrim(n, 2) + ')')
279 mu_radec = mu_radec * 1.
280
281 if parallax is None:
282 parallax = np.zeros(n)
283 else:
284 if not isinstance(parallax, np.ndarray):
285 parallax = np.array([parallax],dtype=float)
286
287 if epoch is None:
288 epoch = 2000.0e0
289
290 radeg = 180.e0 / np.pi
291 sec_to_radian = lambda x : np.deg2rad(x/3600.)
292
293 m = np.array([np.array([+0.9999256795e0, -0.0111814828e0, -0.0048590040e0, -0.000551e0, -0.238560e0, +0.435730e0]),
294 np.array([+0.0111814828e0, +0.9999374849e0, -0.0000271557e0, +0.238509e0, -0.002667e0, -0.008541e0]),
295 np.array([+0.0048590039e0, -0.0000271771e0, +0.9999881946e0, -0.435614e0, +0.012254e0, +0.002117e0]),
296 np.array([-0.00000242389840e0, +0.00000002710544e0, +0.00000001177742e0, +0.99990432e0, -0.01118145e0, -0.00485852e0]),
297 np.array([-0.00000002710544e0, -0.00000242392702e0, +0.00000000006585e0, +0.01118145e0, +0.99991613e0, -0.00002716e0]),
298 np.array([-0.00000001177742e0, +0.00000000006585e0, -0.00000242404995e0, +0.00485852e0, -0.00002717e0, +0.99996684e0])])
299
300 a_dot = 1e-3 * np.array([1.244e0, -1.579e0, -0.660e0])
301
302 ra_rad = np.deg2rad(ra)
303 dec_rad = np.deg2rad(dec)
304 cosra = np.cos(ra_rad)
305 sinra = np.sin(ra_rad)
306 cosdec = np.cos(dec_rad)
307 sindec = np.sin(dec_rad)
308 dec_1950 = dec * 0.
309 ra_1950 = ra * 0.
310
311 for i in range(n):
312
313 a = 1e-6 * np.array([-1.62557e0, -0.31919e0, -0.13843e0])
314 r0 = np.array([cosra[i] * cosdec[i], sinra[i] * cosdec[i], sindec[i]])
315 if (mu_radec is not None):
316 mu_a = mu_radec[i,0]
317 mu_d = mu_radec[i,1]
318 r0_dot = np.array([-mu_a * sinra[i] * cosdec[i] - mu_d * cosra[i] * sindec[i], mu_a * cosra[i] * cosdec[i] - mu_d * sinra[i] * sindec[i], mu_d * cosdec[i]]) + 21.095e0 * rad_vel[i] * parallax[i] * r0
319 else:
320 r0_dot = np.array([0.0e0, 0.0e0, 0.0e0])
321
322 r_0 = np.concatenate((r0, r0_dot))
323 r_1 = np.transpose(np.dot(np.transpose(m), np.transpose(r_0)))
324
325
326 r1 = r_1[0:3]
327 r1_dot = r_1[3:6]
328 if mu_radec is None:
329 r1 = r1 + sec_to_radian ( r1_dot * (epoch - 1950.0e0) / 100. )
330 a = a + sec_to_radian ( a_dot * (epoch - 1950.0e0) / 100. )
331
332 x1 = r_1[0]
333 y1 = r_1[1]
334 z1 = r_1[2]
335 rmag = np.sqrt(x1 ** 2 + y1 ** 2 + z1 ** 2)
336 s1 = r1 / rmag
337 s1_dot = r1_dot / rmag
338 s = s1
339 for j in np.arange(0, 3):
340 r = s1 + a - ((s * a).sum()) * s
341 s = r / rmag
342
343 x = r[0]
344 y = r[1]
345 z = r[2]
346 r2 = x ** 2 + y ** 2 + z ** 2
347 rmag = np.sqrt(r2)
348
349 if mu_radec is not None:
350 r_dot = s1_dot + a_dot - ((s * a_dot).sum()) * s
351 x_dot = r_dot[0]
352 y_dot = r_dot[1]
353 z_dot = r_dot[2]
354 mu_radec[i,0] = (x * y_dot - y * x_dot) / (x ** 2 + y ** 2)
355 mu_radec[i,1] = (z_dot * (x ** 2 + y ** 2) - z * (x * x_dot + y * y_dot)) / (r2 * np.sqrt(x ** 2 + y ** 2))
356
357 dec_1950[i] = np.arcsin(z / rmag)
358 ra_1950[i] = np.arctan2(y, x)
359
360 if parallax[i] > 0.:
361 rad_vel[i] = (x * x_dot + y * y_dot + z * z_dot) / (21.095 * parallax[i] * rmag)
362 parallax[i] = parallax[i] / rmag
363
364 neg = (ra_1950 < 0)
365 if neg.any() > 0:
366 ra_1950[neg] = ra_1950[neg] + 2.e0 * np.pi
367
368 ra_1950 = np.rad2deg(ra_1950)
369 dec_1950 = np.rad2deg(dec_1950)
370
371
372 if scal:
373 return ra_1950[0],dec_1950[0]
374 else:
375 return ra_1950, dec_1950
376
377
378
379
380 -def convolve(image, psf, ft_psf=None, ft_image=None, no_ft=None, correlate=None, auto_correlation=None):
381 """
382 Convolution of an image with a Point Spread Function (PSF)
383 The default is to compute the convolution using a product of Fourier transforms (for speed).
384
385 Inputs:
386 @param image: 2-D array (matrix) to be convolved with psf
387 @type image: array
388 @param psf: the Point Spread Function, (size < or = to size of image).
389 @type psf array
390 @keyword ft_psf: passes out/in the Fourier transform of the PSF, (so that it can be re-used the next time function is called).
391 @type ft_psc: bool
392 @param ft_image: passes out/in the Fourier transform of image.
393 @type ft_image: bool
394 @param correlate: uses the conjugate of the Fourier transform of PSF to compute the cross-correlation of image and PSF (equivalent to IDL function convol() with NO rotation of PSF)
395 @type correlate: bool
396 @param auto_corr: computes the auto-correlation function of image using FFT.
397 @type auto_corr: bool
398
399 METHOD:
400 When using FFT, PSF is centered & expanded to size of image.
401
402 HISTORY:
403 Written (Frank Varosi, 1992)
404 Appropriate precision type for result depending on input image (Markus Hundertmark, february 2006)
405 Fix the bug causing the recomputation of FFT(psf) and/or FFT(image) (Sergey Koposov, december 2006)
406 """
407 from numpy.fft import fft2, ifft2
408 n_params = 2
409 psf_ft = ft_psf
410 imft = ft_image
411 noft = no_ft
412 auto = auto_correlation
413 sp = np.array(np.shape(psf_ft))
414 sif = np.array(np.shape(imft))
415 sim = np.array(np.shape(image))
416 sc = sim / 2
417 npix = np.array(image, copy=0).size
418
419 if image.ndim!=2 or noft!=None:
420 if (auto is not None):
421 message("auto-correlation only for images with FFT", inf=True)
422 return image
423 else:
424 if (correlate is not None):
425 return convol(image, psf)
426 else:
427 return convol(image, rotate(psf, 2))
428
429 if imft==None or (imft.ndim!=2) or imft.shape!=im.shape:
430 imft = ifft2(image)
431 if (auto is not None):
432 return np.roll(np.roll(npix * real(fft2(imft * conjugate(imft))), sc[0], 0),sc[1],1)
433
434 if (ft_psf==None or ft_psf.ndim!=2 or ft_psf.shape!=image.shape or ft_psf.dtype!=image.dtype):
435 sp = np.array(shape(psf))
436 loc = np.maximum((sc - sp / 2), 0)
437 s = np.maximum((sp / 2 - sc), 0)
438 l = np.minimum((s + sim - 1), (sp - 1))
439 psf_ft = np.conjugate(image) * 0
440 psf_ft[loc[1]:loc[1]+l[1]-s[1]+1,loc[0]:loc[0]+l[0]-s[0]+1] = psf[s[1]:(l[1])+1,s[0]:(l[0])+1]
441 psf_ft = ifft2(psf_ft)
442
443 if (correlate is not None):
444 conv = npix * np.real(fft2(imft * np.conjugate(psf_ft)))
445 else:
446 conv = npix * np.real(fft2(imft * psf_ft))
447
448 sc = sc + (sim % 2)
449 return np.roll(np.roll(conv, sc[0],0), sc[1],1)
450
451 -def cv_coord(a,b,c,fr=None,to=None,degr=False):
452
453 if degr:
454 degrad = np.deg2rad
455 raddeg = np.rad2deg
456 else:
457 degrad = lambda x: x
458 raddeg = lambda x: x
459 if fr=='sph':
460 cosa = np.cos(degrad(a))
461 sina = np.sin(degrad(a))
462 cosb = np.cos(degrad(b))
463 sinb = np.sin(degrad(b))
464 x=c*cosa*cosb
465 y=c*sina*cosb
466 z=c*sinb
467 elif fr=='rect':
468 x=a
469 y=b
470 z=c
471 elif fr is None:
472 raise Exception('You must specify the input coordinate system')
473 else:
474 raise Exception('Unknown input coordinate system')
475 if to=='rect':
476 return (x,y,z)
477 elif to=='sph':
478 ra = raddeg(np.arctan2(y,x))
479 dec = raddeg(np.arctan2(z,np.sqrt(x**2+y**2)))
480 rad = np.sqrt(x**2+y**2+z**2)
481 return (ra,dec,rad)
482 elif to is None:
483 raise Exception('You must specify the output coordinate system')
484 else:
485 raise Exception('Unknown output coordinate system')
486
488 """
489 Converts Julian dates to Gregorian calendar dates
490
491 @param xjd: Julian date, positive double precision scalar or vector
492 @type: array
493
494 OUTPUTS:
495 YR: Year (Integer)
496 MN: Month (Integer)
497 DAY: Day (Integer)
498 HR: Hours and fractional hours (Real). If XJD is a vector, then YR,MN,DAY and HR will be vectors of the same length.
499
500 REVISION HISTORY:
501 Converted to IDL from Yeoman's Comet Ephemeris Generator, B. Pfarr, STX, 6/16/88
502 Converted to IDL V5.0 W. Landsman September 1997
503 """
504
505
506 jd = np.array(xjd).astype(int)
507 frac = np.array(xjd).astype(float) - jd + 0.5
508 after_noon = (frac >= 1.0)
509
510 if after_noon.any():
511 if frac.ndim>0:
512 frac[after_noon] = frac[after_noon] - 1.0
513 jd[after_noon] = jd[after_noon] + 1
514 else:
515 frac = frac - 1.0
516 jd = jd + 1
517 hr = frac * 24.0
518 l = jd + 68569
519 n = 4 * l / 146097
520 l = l - (146097 * n + 3) / 4
521 yr = 4000 * (l + 1) / 1461001
522 l = l - 1461 * yr / 4 + 31
523 mn = 80 * l / 2447
524 day = l - 2447 * mn / 80
525 l = mn / 11
526 mn = mn + 2 - 12 * l
527 yr = 100. * (n - 49) + yr + l
528 return (yr, mn, day, hr)
529
530 -def euler(ai, bi, select=1, fk4=False):
531 """
532 Transform between Galactic, celestial, and ecliptic coordinates.
533
534 Input:
535 @param ai: Input longitude in degrees
536 @type ai: float
537 @param bi: Input latitude in degrees
538 @type bi: float
539 @keyword select: Integer (1-6) specifying type of coordinate transformation.
540 @type select: int 1-6
541 @keyword fk4: set the fk4, otherwise use J2000
542 @type fk4: bool
543
544 SELECT From To | SELECT From To
545 1 RA-Dec (2000) Galactic | 4 Ecliptic RA-Dec
546 2 Galactic RA-DEC | 5 Ecliptic Galactic
547 3 RA-Dec Ecliptic | 6 Galactic Ecliptic
548 """
549
550 twopi = 2.0e0 * np.pi
551 fourpi = 4.0e0 * np.pi
552
553 if fk4:
554 equinox = '(B1950)'
555 psi = np.array ([0.57595865315e0, 4.9261918136e0, 0.00000000000e0, 0.0000000000e0, 0.11129056012e0, 4.7005372834e0])
556 stheta = np.array ([0.88781538514e0, -0.88781538514e0, 0.39788119938e0, -0.39788119938e0, 0.86766174755e0, -0.86766174755e0])
557 ctheta = np.array([0.46019978478e0, 0.46019978478e0, 0.91743694670e0, 0.91743694670e0, 0.49715499774e0, 0.49715499774e0])
558 phi = np.array([4.9261918136e0, 0.57595865315e0, 0.0000000000e0, 0.00000000000e0, 4.7005372834e0, 0.11129056012e0])
559 else:
560 equinox = '(J2000)'
561 psi = np.array([0.57477043300e0, 4.9368292465e0, 0.00000000000e0, 0.0000000000e0, 0.11142137093e0, 4.71279419371e0])
562 stheta = np.array([0.88998808748e0, -0.88998808748e0, 0.39777715593e0, -0.39777715593e0, 0.86766622025e0, -0.86766622025e0])
563 ctheta = np.array([0.45598377618e0, 0.45598377618e0, 0.91748206207e0, 0.91748206207e0, 0.49714719172e0, 0.49714719172e0])
564 phi = np.array([4.9368292465e0, 0.57477043300e0, 0.0000000000e0, 0.00000000000e0, 4.71279419371e0, 0.11142137093e0])
565
566 i = select - 1
567 a = np.deg2rad(ai) - phi[i]
568 b = np.deg2rad(bi)
569 sb = np.sin(b)
570 cb = np.cos(b)
571 cbsa = cb * np.sin(a)
572 b = -stheta[i] * cbsa + ctheta[i] * sb
573 bo = np.rad2deg(arcsin(minimum(b, 1.0)))
574 del b
575 a = np.arctan2(ctheta[i] * cbsa + stheta[i] * sb, cb * np.cos(a))
576 del cb, cbsa, sb
577 ao = np.rad2deg(((a + psi[i] + fourpi) % twopi) )
578 return (ao, bo)
579
580 -def gal_uvw(distance=None, lsr=None, ra=None, dec=None, pmra=None, pmdec=None, vrad=None, plx=None):
581 """
582 Calculate the Galactic space velocity (U,V,W) of star
583
584 Calculates the Galactic space velocity U, V, W of star given its
585 (1) coordinates, (2) proper motion, (3) distance (or parallax), and (4) radial velocity.
586
587 OUTPUT PARAMETERS:
588 U - Velocity (km/s) positive toward the Galactic *anti*center
589 V - Velocity (km/s) positive in the direction of Galactic rotation
590 W - Velocity (km/s) positive toward the North Galactic Pole
591 INPUT KEYWORDS:
592 User must supply a position, proper motion,radial velocity and distance
593 (or parallax). Either scalars or vectors can be supplied.
594 (1) Position:
595 RA - Right Ascension in *Degrees*
596 Dec - Declination in *Degrees*
597 (2) Proper Motion
598 PMRA = Proper motion in RA in arc units (typically milli-arcseconds/yr)
599 PMDEC = Proper motion in Declination (typically mas/yr)
600 (3) Radial Velocity
601 VRAD = radial velocity in km/s
602 (4) Distance or Parallax
603 DISTANCE - distance in parsecs
604 or
605 PLX - parallax with same distance units as proper motion measurements
606 typically milliarcseconds (mas)
607
608 REVISION HISTORY:
609 Written, W. Landsman December 2000
610 fix the bug occuring if the input arrays are longer than 32767
611 and update the Sun velocity Sergey Koposov June 2008
612 vectorization of the loop -- performance on large arrays
613 is now 10 times higher Sergey Koposov December 2008
614 """
615
616 n_params = 3
617
618 if ra is None or dec is None:
619 raise Exception('ERROR - The RA, Dec (J2000) position keywords must be supplied (degrees)')
620 if plx is None and distance is None:
621 raise Exception('ERROR - Either a parallax or distance must be specified')
622 if distance is not None:
623 if np.any(distance == 0):
624 raise Exception('ERROR - All distances must be > 0')
625 plx = 1e3 / distance
626 if plx is not None and any(plx==0):
627 raise Exception('ERROR - Parallaxes must be > 0')
628
629 cosd = np.cos(np.deg2rad(dec))
630 sind = np.sin(np.deg2rad(dec))
631 cosa = np.cos(np.deg2rad(ra))
632 sina = np.sin(np.deg2rad(ra))
633 k = 4.74047
634 a_g = np.array([[0.0548755604, +0.4941094279, -0.8676661490], [0.8734370902, -0.4448296300, -0.1980763734], [0.4838350155, 0.7469822445, +0.4559837762]])
635 vec1 = vrad
636 vec2 = k * pmra / plx
637 vec3 = k * pmdec / plx
638 u = (a_g[0,0] * cosa * cosd + a_g[1,0] * sina * cosd + a_g[2,0] * sind) * vec1 + (-a_g[0,0] * sina + a_g[1,0] * cosa) * vec2 + (-a_g[0,0] * cosa * sind - a_g[1,0] * sina * sind + a_g[2,0] * cosd) * vec3
639 v = (a_g[0,1] * cosa * cosd + a_g[1,1] * sina * cosd + a_g[2,1] * sind) * vec1 + (-a_g[0,1] * sina + a_g[1,1] * cosa) * vec2 + (-a_g[0,1] * cosa * sind - a_g[1,1] * sina * sind + a_g[2,1] * cosd) * vec3
640 w = (a_g[0,2] * cosa * cosd + a_g[1,2] * sina * cosd + a_g[2,2] * sind) * vec1 + (-a_g[0,2] * sina + a_g[1,2] * cosa) * vec2 + (-a_g[0,2] * cosa * sind - a_g[1,2] * sina * sind + a_g[2,2] * cosd) * vec3
641 lsr_vel = np.array([-10.00, 5.25, 7.17])
642 if (lsr is not None):
643 u = u + lsr_vel[0]
644 v = v + lsr_vel[1]
645 w = w + lsr_vel[2]
646 return (u,v,w)
647
648 -def helcorr(ra2000, dec2000, jd, obs_long=None, obs_lat=None, obs_alt=None, debug=False):
649 """
650 calculates heliocentric Julian date, baricentric and heliocentric radial
651 velocity corrections from:
652
653 INPUT:
654 @param ra2000: Right ascension of object for epoch 2000.0 (hours)
655 @type ra2000: float
656 @param dec2000: declination of object for epoch 2000.0 (degrees)
657 @type dec2000: float
658 @param jd: julian date for the middle of exposure
659 @type jd: float
660 @keyword obs_long: longitude of observatory (degrees, western direction is positive)
661 @type obs_long: float
662 @keyword obs_lat: latitude of observatory (degrees)
663 @type obs_lat: float
664 @keyword obs_alt: altitude of observatory (meters)
665 @type obs_alt: float
666
667 Algorithms used are taken from the IRAF task noao.astutils.rvcorrect
668 and some procedures of the IDL Astrolib are used as well.
669 Accuracy is about 0.5 seconds in time and about 1 m/s in velocity.
670
671 History:
672 written by Peter Mittermayer, Nov 8,2003
673 2005-January-13 Kudryavtsev Made more accurate calculation of the sideral time.
674 Conformity with MIDAS compute/barycorr is checked.
675 2005-June-20 Kochukhov Included precession of RA2000 and DEC2000 to current epoch
676 """
677 _radeg = 180.0 / np.pi
678
679
680 if obs_long is None:
681 obs_long = 17.878333
682 if obs_lat is None:
683 obs_lat = 28.762222
684 if obs_alt is None:
685 obs_alt = 2333.
686
687
688 xjd = jd*1.0
689 jd = jd-2400000.0
690 year, month, dayraw = convert("JD", "CD", xjd)
691 day = dayraw-dayraw%24.
692 ut = 24.*(dayraw%24)
693
694
695 epoch = year + month / 12. + day / 365.
696
697
698 ra,dec=precess(ra2000*15., dec2000, 2000.0, epoch)
699
700
701 hjd = np.array(helio_jd(jd, ra, dec)).astype(float)
702
703
704 dlat = -(11. * 60. + 32.743) * np.sin(2 * obs_lat / _radeg) + 1.1633 * np.sin(4 * obs_lat / _radeg) - 0.0026 * np.sin(6 * obs_lat / _radeg)
705 lat = obs_lat + dlat / 3600
706
707
708 r = 6378160.0 * (0.998327073 + 0.001676438 * np.cos(2 * lat / _radeg) - 0.00000351 * np.cos(4 * lat / _radeg) + 0.000000008 * np.cos(6 * lat / _radeg)) + obs_alt
709
710
711
712 v = 2. * np.pi * (r / 1000.) / (23.934469591229 * 3600.)
713
714
715 tu = (jd - 51545.0) / 36525
716 gmst = 6.697374558 + ut + (236.555367908 * (jd - 51545.0) + 0.093104 * tu ** 2 - 6.2e-6 * tu ** 3) / 3600
717 lmst = (gmst - obs_long / 15) % 24
718
719
720 vdiurnal = v * np.cos(lat / _radeg) * np.cos(dec / _radeg) * np.sin((ra - lmst * 15) / _radeg)
721
722
723 vh,vb=baryvel(xjd, 0)
724
725
726 vbar = vb[0] * np.cos(dec / _radeg) * np.cos(ra / _radeg) + vb[1] * np.cos(dec / _radeg) * np.sin(ra / _radeg) + vb[2] * np.sin(dec / _radeg)
727 vhel = vh[0] * np.cos(dec / _radeg) * np.cos(ra / _radeg) + vh[1] * np.cos(dec / _radeg) * np.sin(ra / _radeg) + vh[2] * np.sin(dec / _radeg)
728 corr = (vdiurnal + vbar)
729
730 return (corr, hjd)
731
732 -def helio_jd(date, ra, dec, b1950=False, time_diff=False):
733 """
734 Convert geocentric (reduced) Julian date to heliocentric Julian date
735
736 This procedure correct for the extra light travel time between the Earth and the Sun.
737 An online calculator for this quantity is available at http://www.physics.sfasu.edu/astro/javascript/hjd.html
738
739 Input:
740 @param date: Reduced Julian date (= JD - 2400000)
741 @type date: float
742 @param ra: J2000 right ascension in DEGREES (unless B1950 keyword is set)
743 @type ra: float
744 @param dec: J2000 declination in DEGREES (unless B1950 keyword is set)
745 @type dec: float
746 @keyword b1950: if set, then input coordinates are assumed to be in equinox B1950 coordinates
747 @type b1950: bool
748 @keyword time_diff: if set, then HELIO_JD() returns the time difference (heliocentric JD - geocentric JD ) in seconds
749 @type time_diff: bool
750 @return: heliocentric reduced Julian date. If time_diff is True, then helio_jd() instead returns the time difference in seconds between the geocentric and heliocentric Julian date.
751 """
752
753 if not b1950:
754 ra1, dec1 = bprecess(ra, dec)
755 else:
756 ra1 = ra
757 dec1 = dec
758
759 delta_t = (np.array(date).astype(float) - 33282.42345905e0) / 36525.0e0
760 epsilon_sec = np.poly1d([44.836e0, -46.8495, -0.00429, 0.00181][::-1])(delta_t)
761 epsilon = np.deg2rad(23.433333e0 + epsilon_sec / 3600.0e0)
762 ra1 = np.deg2rad(ra1)
763 dec1 = np.deg2rad(dec1)
764 x, y, z, tmp, tmp, tmp = xyz(date)
765
766
767
768 time = -499.00522e0 * (np.cos(dec1) * np.cos(ra1) * x + (np.tan(epsilon) * np.sin(dec1) + np.cos(dec1) * np.sin(ra1)) * y)
769 if time_diff:
770 return time
771 else:
772 return np.array(date).astype(float) + time / 86400.0e0
773
774 -def precess(ra0, dec0, equinox1, equinox2, doprint=False, fk4=False, radian=False):
775 """
776 Precess coordinates from EQUINOX1 to EQUINOX2.
777
778 For interactive display, one can use the procedure ASTRO which calls PRECESS
779 or use the /PRINT keyword. The default (RA,DEC) system is FK5 based on epoch
780 J2000.0 but FK4 based on B1950.0 is available via the /FK4 keyword.
781
782 Input:
783 @param ra0: Input right ascension in DEGREES
784 @type ra0: float
785 @param dec0: Input declination in degrees
786 @type dec0: float
787 @param equinox1: first equinox
788 @type equinox1: float
789 @param equinox2: second equinox
790 @type equinox2: float
791 @keyword fk4: If this keyword is set and non-zero, the FK4 (B1950.0) system will be used otherwise FK5 (J2000.0) will be used instead.
792 @type fk4: float
793 @keyword radian: If this keyword is set, input is in radian instead of degrees
794 @type radian
795
796 Restrictions:
797 Accuracy of precession decreases for declination values near 90 degrees.
798 PRECESS should not be used more than 2.5 centuries from 2000 on the FK5 system (1950.0 on the FK4 system).
799
800 Procedure:
801 Algorithm from Computational Spherical Astronomy by Taff (1983), p24. (FK4).
802 FK5 constants from "Astronomical Almanac Explanatory Supplement 1992, page 104 Table 3.211.1.
803
804 Revision history
805 Written, Wayne Landsman, STI Corporation August 1986
806 Correct negative output RA values February 1989
807 Provided FK5 (J2000.0) I. Freedman January 1994
808 Precession Matrix computation now in PREMAT W. Landsman June 1994
809 Work for arrays, not just vectors (W. Landsman, september 2003)
810 Convert to Python (S. Koposov, july 2010)
811 Converted for use at IvS (K. Smolders)
812 """
813 scal = True
814 if isinstance(ra0, np.ndarray):
815 ra = ra0.copy()
816 dec = dec0.copy()
817 scal = False
818 else:
819 ra = np.array([ra0])
820 dec = np.array([dec0])
821 npts = ra.size
822
823 if not radian:
824 ra_rad = np.deg2rad(ra)
825 dec_rad = np.deg2rad(dec)
826 else:
827 ra_rad = ra
828 dec_rad = dec
829
830 a = np.cos(dec_rad)
831 x = np.zeros((npts, 3))
832 x[:,0] = a * np.cos(ra_rad)
833 x[:,1] = a * np.sin(ra_rad)
834 x[:,2] = np.sin(dec_rad)
835
836
837 r = premat(equinox1, equinox2, fk4=fk4)
838 x2 = np.transpose(np.dot(np.transpose(r), np.transpose(x)))
839 ra_rad = np.zeros(npts) + np.arctan2(x2[:,1], x2[:,0])
840 dec_rad = np.zeros(npts) + np.arcsin(x2[:,2])
841
842 if not radian:
843 ra = np.rad2deg(ra_rad)
844 ra = ra + (ra < 0.) * 360.e0
845 dec = np.rad2deg(dec_rad)
846 else:
847 ra = ra_rad
848 dec = dec_rad
849 ra = ra + (ra < 0.) * 2.0e0 * np.pi
850
851 if doprint:
852 print 'Equinox (%.2f): %f,%f' % (equinox2, ra, dec)
853 if scal:
854 ra, dec = ra[0], dec[0]
855 return ra, dec
856
857
859 """
860 Precess equatorial geocentric rectangular coordinates.
861
862 Input:
863 @param x: heliocentric rectangular x-coordinates
864 @type x: float
865 @param y: heliocentric rectangular y-coordinates
866 @type y: float
867 @param z: heliocentric rectangular z-coordinates
868 @type z: float
869 @param equinox1: first equinox
870 @type equinox1: float
871 @param equinox2: second equinox
872 @type equinox2: float
873
874 NOTES:
875 The equatorial geocentric rectangular coords are converted to RA and Dec,
876 precessed in the normal way, then changed back to x, y and z using unit
877 vectors.
878 """
879
880 ra = np.arctan2(y, x)
881 _del = np.sqrt(x * x + y * y + z * z)
882 dec = np.arcsin(z / _del)
883
884
885 ra,dec = precess(ra, dec, equinox1, equinox2, radian=True)
886
887
888 xunit = np.cos(ra) * np.cos(dec)
889 yunit = np.sin(ra) * np.cos(dec)
890 zunit = np.sin(dec)
891 x = xunit * _del
892 y = yunit * _del
893 z = zunit * _del
894 return x,y,z
895
896 -def premat(equinox1, equinox2, fk4=False):
897 """
898 Return the precession matrix needed to go from EQUINOX1 to EQUINOX2.
899
900 This matrix is used by the procedures PRECESS and BARYVEL to precess astronomical coordinates
901 @param equinox1: Original equinox of coordinates, numeric scalar.
902 @type equinox1: float
903 @param equinox2: Equinox of precessed coordinates.
904 @type equinox2: float
905 @return: double precision 3 x 3 precession matrix, used to precess equatorial rectangular coordinates
906 @rtype: 3 by 3 array
907 @keyword fk4: If this keyword is set, the FK4 (B1950.0) system precession angles are used to compute the precession matrix. The default is to use FK5 (J2000.0) precession angles
908
909 Revision history:
910 Written, Wayne Landsman, HSTX Corporation, June 1994
911 Converted to IDL V5.0 W. Landsman September 1997
912 """
913 deg_to_rad = np.pi / 180.0e0
914 sec_to_rad = deg_to_rad / 3600.e0
915 t = 0.001e0 * (equinox2 - equinox1)
916
917 if not fk4:
918 st = 0.001e0 * (equinox1 - 2000.e0)
919
920 a = sec_to_rad * t * (23062.181e0 + st * (139.656e0 + 0.0139e0 * st) + t * (30.188e0 - 0.344e0 * st + 17.998e0 * t))
921 b = sec_to_rad * t * t * (79.280e0 + 0.410e0 * st + 0.205e0 * t) + a
922 c = sec_to_rad * t * (20043.109e0 - st * (85.33e0 + 0.217e0 * st) + t * (-42.665e0 - 0.217e0 * st - 41.833e0 * t))
923 else:
924 st = 0.001e0 * (equinox1 - 1900.e0)
925
926 a = sec_to_rad * t * (23042.53e0 + st * (139.75e0 + 0.06e0 * st) + t * (30.23e0 - 0.27e0 * st + 18.0e0 * t))
927 b = sec_to_rad * t * t * (79.27e0 + 0.66e0 * st + 0.32e0 * t) + a
928 c = sec_to_rad * t * (20046.85e0 - st * (85.33e0 + 0.37e0 * st) + t * (-42.67e0 - 0.37e0 * st - 41.8e0 * t))
929
930 sina = np.sin(a)
931 sinb = np.sin(b)
932 sinc = np.sin(c)
933 cosa = np.cos(a)
934 cosb = np.cos(b)
935 cosc = np.cos(c)
936 r = np.zeros((3, 3))
937 r[0,:] = np.array([cosa * cosb * cosc - sina * sinb, sina * cosb + cosa * sinb * cosc, cosa * sinc])
938 r[1,:] = np.array([-cosa * sinb - sina * cosb * cosc, cosa * cosb - sina * sinb * cosc, -sina * sinc])
939 r[2,:] = np.array([-cosb * sinc, -sinb * sinc, cosc])
940
941 return r
942
943
944 -def sphdist (ra1, dec1, ra2, dec2):
945 """
946 Measures the spherical distance in degrees. The input has to be in degrees too
947 """
948 dec1_r = np.deg2rad(dec1)
949 dec2_r = no.deg2rad(dec2)
950 return 2 * np.rad2deg(np.arcsin(np.sqrt((np.sin((dec1_r - dec2_r) / 2))**2+np.cos(dec1_r) * np.cos(dec2_r) *(np.sin((np.deg2rad(ra1 - ra2)) / 2))**2)))
951
952 -def xyz(date, equinox=None):
953 """
954 Calculate geocentric X,Y, and Z and velocity coordinates of the Sun
955
956 Calculates geocentric X,Y, and Z vectors and velocity coordinates
957 (dx, dy and dz) of the Sun. (The positive X axis is directed towards the
958 equinox, the y-axis, towards the point on the equator at right ascension 6h,
959 and the z axis toward the north pole of the equator). Typical position
960 accuracy is <1e-4 AU (15000 km).
961
962 Input:
963 @param date: reduced julian date (=JD - 2400000)
964 @type date: float
965 @keyword equinox: equinox of output. Default is 1950.
966 @type equinox: float
967
968 Output:
969 x,y,z: scalars or vectors giving heliocentric rectangular coordinates
970 (in A.U) for each date supplied. Note that sqrt(x^2 + y^2 + z^2)
971 gives the Earth-Sun distance for the given date.
972 xvel, yvel, zvel: velocity vectors corresponding to X, Y and Z.
973 """
974 picon = np.pi / 180.0e0
975 t = (date - 15020.0e0) / 36525.0e0
976
977
978
979
980 pp = (1.396041e0 + 0.000308e0 * (t + 0.5e0)) * (t - 0.499998e0)
981
982
983 el = 279.696678e0 + 36000.76892e0 * t + 0.000303e0 * t * t - pp
984
985
986 c = 270.434164e0 + 480960.e0 * t + 307.883142e0 * t - 0.001133e0 * t * t - pp
987
988
989 n = 259.183275e0 - 1800.e0 * t - 134.142008e0 * t + 0.002078e0 * t * t - pp
990
991
992 g = 358.475833e0 + 35999.04975e0 * t - 0.00015e0 * t * t
993
994
995 j = 225.444651e0 + 2880.0e0 * t + 154.906654e0 * t * t
996
997
998 v = 212.603219e0 + 58320.e0 * t + 197.803875e0 * t + 0.001286e0 * t * t
999
1000
1001 m = 319.529425e0 + 19080.e0 * t + 59.8585e0 * t + 0.000181e0 * t * t
1002
1003
1004 el = el * picon
1005 g = g * picon
1006 j = j * picon
1007 c = c * picon
1008 v = v * picon
1009 n = n * picon
1010 m = m * picon
1011
1012
1013 x = 0.999860e0 * np.cos(el) - 0.025127e0 * np.cos(g - el) + 0.008374e0 * np.cos(g + el) + 0.000105e0 * np.cos(g + g + el) + 0.000063e0 * t * np.cos(g - el) + 0.000035e0 * np.cos(g + g - el) - 0.000026e0 * np.sin(g - el - j) - 0.000021e0 * t * np.cos(g + el) + 0.000018e0 * np.sin(2.e0 * g + el - 2.e0 * v) + 0.000017e0 * np.cos(c) - 0.000014e0 * np.cos(c - 2.e0 * el) + 0.000012e0 * np.cos(4.e0 * g + el - 8.e0 * m + 3.e0 * j) - 0.000012e0 * np.cos(4.e0 * g - el - 8.e0 * m + 3.e0 * j) - 0.000012e0 * np.cos(g + el - v) + 0.000011e0 * np.cos(2.e0 * g + el - 2.e0 * v) + 0.000011e0 * np.cos(2.e0 * g - el - 2.e0 * j)
1014 y = 0.917308e0 * np.sin(el) + 0.023053e0 * np.sin(g - el) + 0.007683e0 * np.sin(g + el) + 0.000097e0 * np.sin(g + g + el) - 0.000057e0 * t * np.sin(g - el) - 0.000032e0 * np.sin(g + g - el) - 0.000024e0 * np.cos(g - el - j) - 0.000019e0 * t * np.sin(g + el) - 0.000017e0 * np.cos(2.e0 * g + el - 2.e0 * v) + 0.000016e0 * np.sin(c) + 0.000013e0 * np.sin(c - 2.e0 * el) + 0.000011e0 * np.sin(4.e0 * g + el - 8.e0 * m + 3.e0 * j) + 0.000011e0 * np.sin(4.e0 * g - el - 8.e0 * m + 3.e0 * j) - 0.000011e0 * np.sin(g + el - v) + 0.000010e0 * np.sin(2.e0 * g + el - 2.e0 * v) - 0.000010e0 * np.sin(2.e0 * g - el - 2.e0 * j)
1015 z = 0.397825e0 * np.sin(el) + 0.009998e0 * np.sin(g - el) + 0.003332e0 * np.sin(g + el) + 0.000042e0 * np.sin(g + g + el) - 0.000025e0 * t * np.sin(g - el) - 0.000014e0 * np.sin(g + g - el) - 0.000010e0 * np.cos(g - el - j)
1016
1017
1018 if equinox is not None:
1019 x, y, z = precess_xyz(x, y, z, 1950, equinox)
1020
1021 xvel = -0.017200e0 * np.sin(el) - 0.000288e0 * np.sin(g + el) - 0.000005e0 * np.sin(2.e0 * g + el) - 0.000004e0 * np.sin(c) + 0.000003e0 * np.sin(c - 2.e0 * el) + 0.000001e0 * t * np.sin(g + el) - 0.000001e0 * np.sin(2.e0 * g - el)
1022 yvel = 0.015780 * np.cos(el) + 0.000264 * np.cos(g + el) + 0.000005 * np.cos(2.e0 * g + el) + 0.000004 * np.cos(c) + 0.000003 * np.cos(c - 2.e0 * el) - 0.000001 * t * np.cos(g + el)
1023 zvel = 0.006843 * np.cos(el) + 0.000115 * np.cos(g + el) + 0.000002 * np.cos(2.e0 * g + el) + 0.000002 * np.cos(c) + 0.000001 * np.cos(c - 2.e0 * el)
1024
1025
1026 if equinox is not None:
1027 xvel, yvel, zvel = precess_xyz(xvel, yvel, zvel, 1950, equinox)
1028
1029 return x, y, z, xvel, yvel, zvel
1030