# Path: spyce/physics.py
# def _(tabulated, uncertainty=None, computed=None):
# G = _(6.67384e-11, 80e-16)     # gravitational constant (N.(m/kg)^2)
# N_A = _(6.02214129e23, 27e15, A_r_e*M_u/m_e)  # Avogadro constant (1/mol)
# R = _(8.3144621, 75e-7)                       # molar gas constant (J/mol/K)
# T_P = _(1.416833e32, 85e26, m_P * c**2 / k_B)        # Planck temperature (K)
# T0 = _(288.15)   # standard temperature (K)
# 
# Path: spyce/coordinates.py
# class CelestialCoordinates:
#     """Celestial coordinates of a point or a direction
# 
#     Celestial coordinates are spherical coordinates. The referential is thus
#     given by an origin, a fundamental plane and a primary direction.
# 
#     * ecliptic coordinates: planet center, ecliptic, vernal equinox
#     * equatorial coordinates: planet center, celestial equator, vernal equinox
# 
#     Note that the vernal equinox, the celestial equator and the ecliptic are
#     respectively the northward equinox, the equatorial plane and the orbital
#     plane *of the Earth*. It does mean that the direction of the north pole of
#     Mars is given within a referential centered on Mars, oriented with Earth.
#     """
# 
#     # the obliquity of the ecliptic is Earth's obliquity (tilt); that is, the
#     # angle between the celestial equator (Earth's equatorial plane) and the
#     # ecliptic (Earth's orbital plane)
#     obliquity_of_the_ecliptic = 0.40910517666747087
# 
#     def __init__(self, right_ascension, declination, ecliptic_longitude,
#                  ecliptic_latitude, distance):
#         """Use from_equatorial() or from_ecliptic()"""
#         self.right_ascension = right_ascension
#         self.declination = declination
#         self.ecliptic_longitude = ecliptic_longitude
#         self.ecliptic_latitude = ecliptic_latitude
#         self.distance = distance
# 
#     @classmethod
#     def from_equatorial(cls, right_ascension, declination, distance=math.inf):
#         """Locate an object from its equatorial coordinates (see class doc)
# 
#         If distance is omitted, it is assumed to be infinite; the coordinates
#         then refer either to a point infinitely far away, or to a direction.
#         """
#         e = cls.obliquity_of_the_ecliptic
#         ecliptic_longitude = math.atan(
#             (
#                 math.sin(right_ascension) * math.cos(e) +
#                 math.tan(declination) * math.sin(e)
#             )
#             / math.cos(right_ascension)
#         )
#         ecliptic_latitude = math.asin(
#             math.sin(declination) * math.cos(e) -
#             math.cos(declination) * math.sin(e) * math.sin(right_ascension)
#         )
#         return cls(right_ascension, declination, ecliptic_longitude,
#                    ecliptic_latitude, distance)
# 
#     @classmethod
#     def from_ecliptic(cls, ecliptic_longitude, ecliptic_latitude,
#                       distance=math.inf):
#         """Locate an object from its ecliptic coordinates (see class doc)
# 
#         If distance is omitted, it is assumed to be infinite; the coordinates
#         then refer either to a point infinitely far away, or to a direction.
#         """
#         e = cls.obliquity_of_the_ecliptic
#         right_ascension = math.atan(
#             (
#                 math.sin(ecliptic_longitude) * math.cos(e) -
#                 math.tan(ecliptic_latitude) * math.sin(e)
#             ) / math.cos(ecliptic_longitude)
#         )
#         declination = math.asin(
#             math.sin(ecliptic_latitude) * math.cos(e) +
#             math.cos(ecliptic_latitude) * math.sin(e) *
#             math.sin(ecliptic_longitude)
#         )
#         return cls(right_ascension, declination, ecliptic_longitude,
#                    ecliptic_latitude, distance)


import json
import re
from math import acos, asin, cos, pi, radians, sin
from urllib.request import urlopen
from spyce.physics import au
from spyce.coordinates import CelestialCoordinates
?<TD>(.*?)</TD>
?<TD>(.*?)</TD>"""
            matches = re.findall(pattern, data)

            # save data
            for (name, semi_major_axis, eccentricity, argument_of_periapsis,
                 mean_anomaly_at_epoch, inclination,
                 longitude_of_ascending_node) in matches:

                # S/2003 J1 -> S/2003J1
                if re.match(r'^S/[0-9]{4} [A-Z] [0-9]*$', name):
                    name = ''.join(name.rsplit(' ', 1))

                # convert to standard units
                semi_major_axis = float(semi_major_axis) * 1e3
                eccentricity = float(eccentricity)
                inclination = radians(float(inclination))
                longitude_of_ascending_node = radians(float(longitude_of_ascending_node))
                argument_of_periapsis = radians(float(argument_of_periapsis))
                mean_anomaly_at_epoch = radians(float(mean_anomaly_at_epoch))

                # when given equatorial elements, convert to ecliptic elements
                # when given Laplacian elements, handle as equatorial elements
                if 'ecliptic' not in reference_plane.lower():
                    # inclination is given relative to the equatorial plane of
                    # the primary; longitude of the ascending node is given
                    # relative to the northward equinox

                    # recover ecliptic coordinates of the primary's north pole
                    north_pole = bodies[primary]['north_pole']

# Path: spyce/physics.py
# def _(tabulated, uncertainty=None, computed=None):
# G = _(6.67384e-11, 80e-16)     # gravitational constant (N.(m/kg)^2)
# N_A = _(6.02214129e23, 27e15, A_r_e*M_u/m_e)  # Avogadro constant (1/mol)
# R = _(8.3144621, 75e-7)                       # molar gas constant (J/mol/K)
# T_P = _(1.416833e32, 85e26, m_P * c**2 / k_B)        # Planck temperature (K)
# T0 = _(288.15)   # standard temperature (K)
# 
# Path: spyce/coordinates.py
# class CelestialCoordinates:
#     """Celestial coordinates of a point or a direction
# 
#     Celestial coordinates are spherical coordinates. The referential is thus
#     given by an origin, a fundamental plane and a primary direction.
# 
#     * ecliptic coordinates: planet center, ecliptic, vernal equinox
#     * equatorial coordinates: planet center, celestial equator, vernal equinox
# 
#     Note that the vernal equinox, the celestial equator and the ecliptic are
#     respectively the northward equinox, the equatorial plane and the orbital
#     plane *of the Earth*. It does mean that the direction of the north pole of
#     Mars is given within a referential centered on Mars, oriented with Earth.
#     """
# 
#     # the obliquity of the ecliptic is Earth's obliquity (tilt); that is, the
#     # angle between the celestial equator (Earth's equatorial plane) and the
#     # ecliptic (Earth's orbital plane)
#     obliquity_of_the_ecliptic = 0.40910517666747087
# 
#     def __init__(self, right_ascension, declination, ecliptic_longitude,
#                  ecliptic_latitude, distance):
#         """Use from_equatorial() or from_ecliptic()"""
#         self.right_ascension = right_ascension
#         self.declination = declination
#         self.ecliptic_longitude = ecliptic_longitude
#         self.ecliptic_latitude = ecliptic_latitude
#         self.distance = distance
# 
#     @classmethod
#     def from_equatorial(cls, right_ascension, declination, distance=math.inf):
#         """Locate an object from its equatorial coordinates (see class doc)
# 
#         If distance is omitted, it is assumed to be infinite; the coordinates
#         then refer either to a point infinitely far away, or to a direction.
#         """
#         e = cls.obliquity_of_the_ecliptic
#         ecliptic_longitude = math.atan(
#             (
#                 math.sin(right_ascension) * math.cos(e) +
#                 math.tan(declination) * math.sin(e)
#             )
#             / math.cos(right_ascension)
#         )
#         ecliptic_latitude = math.asin(
#             math.sin(declination) * math.cos(e) -
#             math.cos(declination) * math.sin(e) * math.sin(right_ascension)
#         )
#         return cls(right_ascension, declination, ecliptic_longitude,
#                    ecliptic_latitude, distance)
# 
#     @classmethod
#     def from_ecliptic(cls, ecliptic_longitude, ecliptic_latitude,
#                       distance=math.inf):
#         """Locate an object from its ecliptic coordinates (see class doc)
# 
#         If distance is omitted, it is assumed to be infinite; the coordinates
#         then refer either to a point infinitely far away, or to a direction.
#         """
#         e = cls.obliquity_of_the_ecliptic
#         right_ascension = math.atan(
#             (
#                 math.sin(ecliptic_longitude) * math.cos(e) -
#                 math.tan(ecliptic_latitude) * math.sin(e)
#             ) / math.cos(ecliptic_longitude)
#         )
#         declination = math.asin(
#             math.sin(ecliptic_latitude) * math.cos(e) +
#             math.cos(ecliptic_latitude) * math.sin(e) *
#             math.sin(ecliptic_longitude)
#         )
#         return cls(right_ascension, declination, ecliptic_longitude,
#                    ecliptic_latitude, distance)


# Path: get_nasa_data.py
import json
import re
from math import acos, asin, cos, pi, radians, sin
from urllib.request import urlopen
from spyce.physics import au
from spyce.coordinates import CelestialCoordinates

?<TD>(.*?)</TD>
?<TD>(.*?)</TD>"""
            matches = re.findall(pattern, data)

            # save data
            for (name, semi_major_axis, eccentricity, argument_of_periapsis,
                 mean_anomaly_at_epoch, inclination,
                 longitude_of_ascending_node) in matches:

                # S/2003 J1 -> S/2003J1
                if re.match(r'^S/[0-9]{4} [A-Z] [0-9]*$', name):
                    name = ''.join(name.rsplit(' ', 1))

                # convert to standard units
                semi_major_axis = float(semi_major_axis) * 1e3
                eccentricity = float(eccentricity)
                inclination = radians(float(inclination))
                longitude_of_ascending_node = radians(float(longitude_of_ascending_node))
                argument_of_periapsis = radians(float(argument_of_periapsis))
                mean_anomaly_at_epoch = radians(float(mean_anomaly_at_epoch))

                # when given equatorial elements, convert to ecliptic elements
                # when given Laplacian elements, handle as equatorial elements
                if 'ecliptic' not in reference_plane.lower():
                    # inclination is given relative to the equatorial plane of
                    # the primary; longitude of the ascending node is given
                    # relative to the northward equinox

                    # recover ecliptic coordinates of the primary's north pole
                    north_pole = bodies[primary]['north_pole']

                    north_pole = CelestialCoordinates.from_equatorial(