Source code for twobody.anomaly
# Standard library
import inspect
from functools import wraps
# Third-party
import astropy.units as u
# Project
from .wrap import (cy_mean_anomaly_from_eccentric_anomaly,
cy_true_anomaly_from_eccentric_anomaly,
cy_eccentric_anomaly_from_true_anomaly,
cy_eccentric_anomaly_from_mean_anomaly_Newton1,
cy_eccentric_anomaly_from_mean_anomaly_Householder3)
from .utils import ArrayProcessor
__all__ = ['mean_anomaly_from_eccentric_anomaly',
'eccentric_anomaly_from_mean_anomaly',
'true_anomaly_from_eccentric_anomaly',
'eccentric_anomaly_from_true_anomaly']
def anomaly_wrapper(func):
"""This is a decorator that processes the input (strips units, enforces that
it is a 1D array), executes the cython function on the cleaned input, then
returns the output angle in the same units and with the same shape as the
input.
"""
sig = inspect.signature(func)
@wraps(func)
def function_wrapper(ang, e, *args, **kwargs):
in_unit = ang.unit
p = ArrayProcessor(ang.to(u.radian).value, e)
ang, e = p.prepare_arrays()
res = p.prepare_result(func(ang, e, *args, **kwargs))
return (res * u.radian).to(in_unit)
return function_wrapper
[docs]@u.quantity_input(E=u.radian)
@anomaly_wrapper
def mean_anomaly_from_eccentric_anomaly(E, e):
"""
Parameters
----------
E : quantity_like [angle]
Eccentric anomaly.
e : numeric, array_like
Eccentricity.
Returns
-------
M : numeric, array_like [radian]
Mean anomaly.
"""
return cy_mean_anomaly_from_eccentric_anomaly(E, e)
[docs]@u.quantity_input(M=u.radian)
@anomaly_wrapper
def eccentric_anomaly_from_mean_anomaly(M, e, tol=1E-10, maxiter=128,
method='Newton1'):
"""
Parameters
----------
M : quantity_like [angle]
Mean anomaly.
e : numeric
Eccentricity.
tol : numeric, optional
Numerical tolerance used in iteratively solving for eccentric anomaly.
maxiter : int, optional
Maximum number of iterations when iteratively solving for eccentric
anomaly.
method : str, optional
The method to use for iterative root-finding for the eccentric anomaly.
Options are: ``'Newton1'`` and ``'Householder3'``.
Returns
-------
E : numeric [radian]
Eccentric anomaly.
Issues
------
- Magic numbers ``tol`` and ``maxiter``
"""
func = eval('cy_eccentric_anomaly_from_mean_anomaly_{0}'.format(method))
return func(M, e, tol, maxiter)
[docs]@u.quantity_input(E=u.radian)
@anomaly_wrapper
def true_anomaly_from_eccentric_anomaly(E, e):
"""
Parameters
----------
E : quantity_like [angle]
Eccentric anomaly.
e : numeric, array_like
Eccentricity.
Returns
-------
f : numeric [radian]
True anomaly.
"""
return cy_true_anomaly_from_eccentric_anomaly(E, e)
[docs]@u.quantity_input(f=u.radian)
@anomaly_wrapper
def eccentric_anomaly_from_true_anomaly(f, e):
"""
Parameters
----------
f : quantity_like [angle]
True anomaly.
e : numeric, array_like
Eccentricity.
Returns
-------
E : numeric [radian]
Eccentric anomaly.
"""
return cy_eccentric_anomaly_from_true_anomaly(f, e)