-
Notifications
You must be signed in to change notification settings - Fork 35
/
orbit.py
executable file
·104 lines (94 loc) · 3.34 KB
/
orbit.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# Module to calculate relative positions and radial velocities for
# binary system. Written by Suzanne Aigrain.
import numpy
f = numpy.MachAr()
machep = f.eps
def eccan(Ecc, M, Tol = 1.0e-8, Nmax = 50):
"""Calculate eccentric anomaly using Newton-Raphson process."""
if M < Tol: return M
x = Ecc * numpy.sin(M) / (1 - Ecc * numpy.cos(M))
Eo = M + x * (1-x*x/2.)
Diff = 1
Flag = 0
i = 0
while (Diff > Tol):
En = Eo + (M + Ecc * numpy.sin(Eo) - Eo) / (1 - Ecc * numpy.cos(Eo))
Diff = abs((En - Eo) / Eo)
Eo = En
i += 1
if i >= Nmax:
if Flag ==1:
print Ecc, M
print 'Eccan did not converge'
return M
Flag = 1
i = 0
Eo = M
Diff = 1
return En
def phase(JD, P, T0 = 0.0):
"""Phase-fold array of dates; result in range [0:1]."""
Phase = ((JD-T0) % P) / P
# ensure > 0
Phase = numpy.select([Phase >= 0., numpy.ones(len(Phase))], \
[Phase, Phase + 1])
return Phase
def truean(JD, P, T0 = 0, Ecc = 0):
"""Calculate true anomaly for array of dates."""
Phase = phase(JD, P, T0) # phases
M = 2 * numpy.pi * Phase # mean anomaly
if Ecc <= machep:
return M
eccanV = numpy.vectorize(eccan)
E = eccanV(Ecc, M) % (2 * numpy.pi) # eccentric anomaly
cosE = numpy.cos(E)
cosNu = (cosE - Ecc) / (1 - Ecc * cosE)
Nu = numpy.arccos(cosNu) # true anomaly
Nu = numpy.select([E <= numpy.pi, numpy.ones(len(Nu))], \
[Nu, 2 * numpy.pi - Nu]) # E>pi cases
return Nu
def truedist(Nu, a, Ecc = 0):
"""True distance from true anomaly, orbital distance & eccentricity."""
return a * (1 - Ecc**2) / (1 + Ecc * numpy.cos(Nu))
def orbitcoord(JD, P, T0 = 0, Ecc = 0, a = 1):
"""Coordinates in orbital plane. X is towards observer."""
Nu = truean(JD, P, T0, Ecc)
r = truedist(Nu, a, Ecc)
X = r * numpy.cos(Nu)
Y = r * numpy.sin(Nu)
return X, Y, Nu
def skycoord(JD, P, T0 = 0, Ecc = 0, a = 1, \
incl = numpy.pi/2, Omega = 0, omega = 0):
"""Coordinates in plane of sky. y is North."""
X, Y, Nu = orbitcoord(JD, P, T0, Ecc, a)
cosi = numpy.cos(incl)
sini = numpy.sin(incl)
cosO = numpy.cos(Omega)
sinO = numpy.sin(Omega)
coso = numpy.cos(omega)
sino = numpy.sin(omega)
cosxX = - cosi * sinO * sino + cosO * coso
cosxY = - cosi * sinO * coso - cosO * sino
cosyX = cosi * cosO * sino + sinO * coso
cosyY = cosi * cosO * coso - sinO * sino
x = X * cosxX + Y * cosxY
y = X * cosyX + Y * cosyY
z = numpy.sqrt(X**2+Y**2) * sini * numpy.sin(omega+Nu)
return x, y, z
def radvel(JD, P, K, T0 = 0, V0 = 0, Ecc = 0, omega = 0):
"""Radial velocity (user-defined semi-amplitude)"""
Nu = truean(JD, P, T0, Ecc)
Vr = V0 + K * (numpy.cos(omega + Nu) + Ecc * numpy.cos(omega))
if (K < 0): Vr[:] = -999
return Vr
def getT0(P, Ttr, omega = 0, Ecc = 0):
"""Compute time of periastron passage from time of transit centre
and other orbital elements."""
nu = numpy.pi/2 - omega
cosnu = numpy.cos(nu)
cosE = (Ecc + cosnu) / (1 + Ecc * cosnu)
E = numpy.arccos(cosE)
if (nu > -numpy.pi) and (nu < 0.0): E = -E #mcquillan:1/4/10
M = E - Ecc * numpy.sin(E)
T0 = Ttr - M * P / (2 * numpy.pi)
return T0