-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompute_sep.py
90 lines (79 loc) · 3.27 KB
/
compute_sep.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
import numpy as np
import pandas as pd
from astropy import units as u
from radvel.basis import Basis
from radvel.utils import Msini
from orbitize.basis import tp_to_tau
from orbitize.kepler import calc_orbit
def compute_sep(
df, epochs, basis, m0, m0_err, plx, plx_err, n_planets=1, pl_num=1
):
"""
Computes a sky-projected angular separation posterior given a
RadVel-computed DataFrame.
Args:
df (pd.DataFrame): Radvel-computed posterior (in any orbital basis)
epochs (np.array of astropy.time.Time): epochs at which to compute
separations
basis (str): basis string of input posterior (see
radvel.basis.BASIS_NAMES` for the full list of possibilities).
m0 (float): median of primary mass distribution (assumed Gaussian).
m0_err (float): 1sigma error of primary mass distribution
(assumed Gaussian).
plx (float): median of parallax distribution (assumed Gaussian).
plx_err: 1sigma error of parallax distribution (assumed Gaussian).
n_planets (int): total number of planets in RadVel posterior
pl_num (int): planet number used in RadVel fits (e.g. a RadVel label of
'per1' implies `pl_num` == 1)
Example:
>> df = pandas.read_csv('sample_radvel_chains.csv.bz2', index_col=0)
>> epochs = astropy.time.Time([2022, 2024], format='decimalyear')
>> seps, df_orb = compute_sep(
df, epochs, 'per tc secosw sesinw k', 0.82, 0.02, 312.22, 0.47
)
Returns:
tuple of:
np.array of size (len(epochs) x len(df)): sky-projected angular
separations [mas] at each input epoch
pd.DataFrame: corresponding orbital posterior in orbitize basis
"""
myBasis = Basis(basis, n_planets)
df = myBasis.to_synth(df)
chain_len = len(df)
tau_ref_epoch = 58849
# convert RadVel posteriors -> orbitize posteriors
m_st = np.random.normal(m0, m0_err, size = chain_len)
semiamp = df['k{}'.format(pl_num)].values
per_day = df['per{}'.format(pl_num)].values
period_yr = per_day / 365.25
ecc = df['e{}'.format(pl_num)].values
msini = (
Msini(semiamp, per_day, m_st, ecc, Msini_units='Earth') *
(u.M_earth / u.M_sun).to('')
)
cosi = (2. * np.random.random(size = chain_len)) - 1.
inc = np.arccos(cosi)
m_pl = msini / np.sin(inc)
mtot = m_st + m_pl
sma = (period_yr**2 * mtot)**(1/3)
omega_st_rad = df['w{}'.format(pl_num)].values
omega_pl_rad = omega_st_rad + np.pi
parallax = np.random.normal(plx, plx_err, size = chain_len)
lan = np.random.random_sample(size = chain_len) * 2. * np.pi
tp_mjd = df['tp{}'.format(pl_num)].values - 2400000.5
tau = tp_to_tau(tp_mjd, tau_ref_epoch, period_yr)
# compute projected separation in mas
raoff, deoff, _ = calc_orbit(
epochs.mjd, sma, ecc, inc,
omega_pl_rad, lan, tau,
parallax, mtot, tau_ref_epoch=tau_ref_epoch
)
seps = np.sqrt(raoff**2 + deoff**2)
df_orb = pd.DataFrame(
np.transpose([sma, ecc, inc, omega_pl_rad, lan, tau, parallax, m_st, m_pl]),
columns=[
'sma', 'ecc', 'inc_rad', 'omega_pl_rad', 'lan_rad', 'tau_58849',
'plx', 'm_st', 'mp'
]
)
return seps, df_orb