Skip to content

Commit 233d6c3

Browse files
committed
Updated astrometry routines w/ output dictionaries.
1 parent 6b4b21f commit 233d6c3

14 files changed

+128
-38
lines changed

psoap/orbit.py

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
v_{r,2} = K_2 (\cos (\omega_2 + f) + e \cos \omega_2)
88
99
where a positive :math:`v_r` indicates a redshifted source and :math:`\omega_2 = \omega_1 + \pi`. In an RV-only paper, typically authors report :math:`\omega = \omega_1`.
10+
11+
In general, quantities like ``vA``, ``vB``, and ``vC`` refer to radial velocities relative to the heliocentric frame of the earth, i.e., quantities to directly compare to actual radial velocity measurements.
12+
13+
(Private) quantities like ``v1``, ``v2``, ``v1_in``, and ``v1_out`` have more subtle meanings---these are generally partial velocities used in the process of constructing ``vA``, etc...
1014
'''
1115

1216
import numpy as np
@@ -40,9 +44,15 @@ def __init__(self, K, e, omega, P, T0, gamma, obs_dates=None, **kwargs):
4044
self.obs_dates = obs_dates
4145

4246

43-
def _theta(self, t):
44-
'''Calculate the true anomoly for the A-B orbit.
45-
Input is in days.'''
47+
def _f(self, t):
48+
'''Calculate the true anomoly :math:`f` for the A-B orbit.
49+
50+
Args:
51+
t (float): time to evaluate true anomaly at [days].
52+
53+
Returns:
54+
float: true anomaly
55+
'''
4656

4757
# t is input in seconds
4858

@@ -63,7 +73,10 @@ def _theta(self, t):
6373

6474
def _v1_f(self, f):
6575
'''Calculate the component of A's velocity based on only the inner orbit.
66-
f is the true anomoly of this inner orbit.'''
76+
77+
Args: f (float): true anomaly of inner orbit.
78+
79+
Returns: velocity of A (no systemic velocity included).'''
6780

6881
return self.K * (np.cos(self.omega * np.pi/180 + f) + self.e * np.cos(self.omega * np.pi/180))
6982

@@ -72,7 +85,7 @@ def _vA_t(self, t):
7285
7386
'''
7487
# Get the true anomoly "f" from time
75-
f = self._theta(t)
88+
f = self._f(t)
7689

7790
# Feed this into the orbit equation and add the systemic velocity
7891
return self._v1_f(f) + self.gamma
@@ -127,7 +140,7 @@ def _v2_f(self, f):
127140
return self.K/self.q * (np.cos(self.omega_2 * np.pi/180 + f) + self.e * np.cos(self.omega_2 * np.pi/180))
128141

129142
def _vB_t(self, t):
130-
f = self._theta(t)
143+
f = self._f(t)
131144

132145
# Feed this into the orbit equation and add the systemic velocity
133146
return self._v2_f(f) + self.gamma
@@ -193,7 +206,7 @@ def __init__(self, K_in, e_in, omega_in, P_in, T0_in, K_out, e_out, omega_out, P
193206
# just store them to the object.
194207
self.obs_dates = obs_dates
195208

196-
def _theta_in(self, t):
209+
def _f_in(self, t):
197210
'''Calculate the true anomoly for the A-B orbit.'''
198211

199212
# t is input in seconds
@@ -213,7 +226,7 @@ def _theta_in(self, t):
213226
else:
214227
return th + 2 * np.pi
215228

216-
def _theta_out(self, t):
229+
def _f_out(self, t):
217230
'''Calculate the true anomoly for the (A-B) - C orbit.'''
218231

219232
# t is input in seconds
@@ -239,24 +252,50 @@ def _v1_f(self, f):
239252

240253
return self.K_in * (np.cos(self.omega_in * np.pi/180 + f) + self.e_in * np.cos(self.omega_in * np.pi/180))
241254

242-
243255
def _v3_f(self, f):
244256
'''Calculate the velocity of (A-B) based only on the outer orbit.
245257
f is the true anomoly of the outer orbit'''
246258
return self.K_out * (np.cos(self.omega_out * np.pi/180 + f) + self.e_out * np.cos(self.omega_out * np.pi/180))
247259

248-
249260
def _vA_t(self, t):
250261

251262
# Get the true anomoly "f" from time
252-
f_in = self._theta_in(t)
253-
f_out = self._theta_out(t)
263+
f_in = self._f_in(t)
264+
f_out = self._f_out(t)
254265

255266
v1 = self._v1_f(f_in)
256267
v3 = self._v3_f(f_out)
257268

258269
return v1 + v3 + self.gamma
259270

271+
def get_component_velocities(self, dates=None):
272+
'''
273+
Routine to grab v1_inner and v1_outer.
274+
275+
Args:
276+
dates (optional): if provided, calculate velocities at this new vector of dates, rather than the one provided when the object was initialized.
277+
278+
Returns:
279+
np.array: A ``(1, nvels)`` shape array of the primary velocities for the outer motion
280+
'''
281+
282+
if dates is None and self.obs_dates is None:
283+
raise RuntimeError("Must provide input dates or specify observation dates upon creation of orbit object.")
284+
285+
if dates is None and self.obs_dates is not None:
286+
dates = self.obs_dates
287+
288+
dates = np.atleast_1d(dates)
289+
290+
# calculate f_in and f_out for all dates
291+
f_ins = np.array([self._f_in(date) for date in dates])
292+
f_outs = np.array([self._f_out(date) for date in dates])
293+
294+
v1s = np.array([self._v1_f(f) for f in f_ins])
295+
v3s = np.array([self._v3_f(f) for f in f_outs])
296+
297+
return np.vstack((v1s, v3s))
298+
260299
def get_velocities(self, dates=None):
261300
'''
262301
Calculate the velocities of the primary (``vA``) for all dates provided.
@@ -280,6 +319,7 @@ def get_velocities(self, dates=None):
280319

281320
return np.atleast_2d(vAs)
282321

322+
283323
class ST2(ST1):
284324
'''
285325
Orbital model for a double-line (inner orbit) hierarchical spectroscopic triple.
@@ -314,14 +354,43 @@ def _v2_f(self, f):
314354
def _vB_t(self, t):
315355

316356
# Get the true anolomy "f" from time
317-
f_in = self._theta_in(t)
318-
f_out = self._theta_out(t)
357+
f_in = self._f_in(t)
358+
f_out = self._f_out(t)
319359

320360
v2 = self._v2_f(f_in)
321361
v3 = self._v3_f(f_out)
322362

323363
return v2 + v3 + self.gamma
324364

365+
def get_component_velocities(self, dates=None):
366+
'''
367+
Routine to grab v1_inner and v1_outer.
368+
369+
Args:
370+
dates (optional): if provided, calculate velocities at this new vector of dates, rather than the one provided when the object was initialized.
371+
372+
Returns:
373+
np.array: A ``(1, nvels)`` shape array of the primary velocities for the outer motion
374+
'''
375+
376+
if dates is None and self.obs_dates is None:
377+
raise RuntimeError("Must provide input dates or specify observation dates upon creation of orbit object.")
378+
379+
if dates is None and self.obs_dates is not None:
380+
dates = self.obs_dates
381+
382+
dates = np.atleast_1d(dates)
383+
384+
# calculate f_in and f_out for all dates
385+
f_ins = np.array([self._f_in(date) for date in dates])
386+
f_outs = np.array([self._f_out(date) for date in dates])
387+
388+
v1s = np.array([self._v1_f(f) for f in f_ins])
389+
v2s = np.array([self._v2_f(f) for f in f_ins])
390+
v3s = np.array([self._v3_f(f) for f in f_outs])
391+
392+
return np.vstack((v1s, v2s, v3s))
393+
325394
def get_velocities(self, dates=None):
326395
'''
327396
Calculate the velocities of the primary (``vA``) and secondary (``vB``) for all dates provided.
@@ -384,7 +453,7 @@ def _v3_f_C(self, f):
384453
def _vC_t(self, t):
385454

386455
# Get the true anolomy "f" from time
387-
f_out = self._theta_out(t)
456+
f_out = self._f_out(t)
388457

389458
v3 = self._v3_f_C(f_out)
390459

psoap/orbit_astrometry.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,15 @@ class Binary:
5353
omega (float): argument of periastron of the *primary*, i.e. :math:`\omega_1` [degrees]
5454
Omega (float): position angle of the ascending node (going into sky) [deg] east of north
5555
T0 (float): epoch of periastron passage [JD]
56-
M_tot (float): sum of the masses [:math:`M_\odot`]
56+
M_tot (float): sum of the masses :math:`M_\mathrm{A} + M_\mathrm{B}` [:math:`M_\odot`]
5757
M_2 (float): mass of B [:math:`M_\odot`]
5858
gamma (float): systemic velocity (km/s)
5959
obs_dates (1D np.array): dates of observation (JD)
6060
'''
6161

6262
def __init__(self, a, e, i, omega, Omega, T0, M_tot, M_2, gamma, obs_dates=None, **kwargs):
6363
assert (e >= 0.0) and (e < 1.0), "Eccentricity must be between [0, 1)"
64+
assert (i >= 0.0) and (i <= 180.), "Inclination must be between [0, 180]"
6465
self.a = a # [AU] semi-major axis
6566
self.e = e # eccentricity
6667
self.i = i # [deg] inclination
@@ -349,6 +350,8 @@ class Triple:
349350
def __init__(self, a_in, e_in, i_in, omega_in, Omega_in, T0_in, a_out, e_out, i_out, omega_out, Omega_out, T0_out, M_1, M_2, M_3, gamma, obs_dates=None, **kwargs):
350351
assert (e_in >= 0.0) and (e_in < 1.0), "Inner eccentricity must be between [0, 1)"
351352
assert (e_out >= 0.0) and (e_out < 1.0), "Outer eccentricity must be between [0, 1)"
353+
assert (i_in >= 0.0) and (i_in <= 180.), "Inner inclination must be between [0, 180]"
354+
assert (i_out >= 0.0) and (i_out <= 180.), "Outur inclination must be between [0, 180]"
352355
self.a_in = a_in # [AU]
353356
self.e_in = e_in #
354357
self.i_in = i_in # [deg]
-18.3 KB
Loading
-11.9 KB
Loading
-3.43 KB
Loading
-6.09 KB
Loading
-46.9 KB
Loading
-66.2 KB
Loading
-20.6 KB
Loading

tests/plots/triple/orbit_A_B_X.png

-28.2 KB
Loading

0 commit comments

Comments
 (0)