Source code for twobody.transforms
# Third-party
import astropy.units as u
from astropy.utils.misc import isiterable
from astropy.constants import G
import numpy as np
# Project
from .utils import format_doc
__all__ = ['a_P_to_m', 'a_m_to_P', 'P_m_to_a', 'get_m2_min']
doc_a = """a : quantity_like [length]
Semi-major axis.
"""
doc_P = """P : quantity_like [time]
Orbital period.
"""
doc_m = """m : quantity_like [mass]
Total mass.
"""
[docs]@u.quantity_input(a=u.au, P=u.day)
@format_doc("""{__doc__}""", a=doc_a, P=doc_P)
def a_P_to_m(a, P):
"""Compute the total mass given the semi-major axis and period.
Parameters
----------
{a}
{P}
"""
return a**3 / G * (2*np.pi/P)**2
[docs]@u.quantity_input(a=u.au, m=u.Msun)
@format_doc("""{__doc__}""", a=doc_a, m=doc_m)
def a_m_to_P(a, m):
"""Compute the orbital period given the semi-major axis and total mass.
Parameters
----------
{a}
{m}
"""
return 2*np.pi * np.sqrt(a**3 / (G * m))
[docs]@u.quantity_input(P=u.day, m=u.Msun)
@format_doc("""{__doc__}""", P=doc_P, m=doc_m)
def P_m_to_a(P, m):
"""Compute the semi-major axis given the orbital period and total mass.
Parameters
----------
{P}
{m}
"""
return np.cbrt(G * m * (P/(2*np.pi))**2)
@u.quantity_input(P=u.day, K=u.km/u.s, i=u.deg)
@format_doc("""{__doc__}""", P=doc_P)
def PeKi_to_a(P, e, K, i=None):
"""Compute the semi-major axis given the orbital period, eccentricity,
semi-amplitude, and inclination. If you don't have a measured inclination,
use the default i=90ยบ and the returned semi-major axis will be a*sin(i)
instead.
Parameters
----------
{P}
e : numeric
Eccentricity.
K : quantity_like [speed]
Velocity semi-amplitude.
i : quantity_like [angle]
Inclination.
Returns
-------
a : `~astropy.units.Quantity` [length]
Semi-major axis.
"""
if i is None:
i = 90*u.deg
a = K / (2*np.pi * np.sin(i)) * (P * np.sqrt(1 - e**2))
return a
def _m2_func(m2, m1, sini, mf):
return (m2*sini)**3 / (m1 + m2)**2 - mf
[docs]@u.quantity_input(m1=u.Msun, mf=u.Msun)
def get_m2_min(m1, mf):
"""Compute the minimum companion mass given the primary mass and the binary
mass function.
Parameters
----------
m1 : quantity_like [mass]
Primary mass.
mf : quantity_like [mass]
Binary mass function.
Returns
-------
m2_min : `~astropy.units.Quantity` [mass]
The minimum companion mass.
"""
from scipy.optimize import root
mf = mf.to(m1.unit)
if isiterable(m1) and isiterable(mf):
m2s = []
for x, y in zip(m1, mf):
try:
res = root(_m2_func, x0=10., args=(x.value, 1., y.value))
if not res.success:
raise RuntimeError('Unsuccessful')
m2s.append(res.x[0])
except Exception as e:
m2s.append(np.nan)
return m2s * m1.unit
else:
res = root(_m2_func, x0=10., args=(m1.value, 1., mf.value))
if res.success:
return res.x[0] * m1.unit
else:
return np.nan * m1.unit