# Path: skyfield/constants.py
# AU_KM = 149597870.700
# 
# DAY_S = 86400.0
# 
# Path: skyfield/errors.py
# class EphemerisRangeError(ValueError):
#     """An ephemeris has been asked about positions outside its time range.
# 
#     Attributes:
# 
#     - `start_time`, `end_time`: the range of times supported by the segment
#     - `time_mask`: Boolean array where ``True`` marks out-of-range times
#     - `segment`: the ephemeris segment that was asked for positions
# 
#     """
#     def __init__(self, message, start_time, end_time, time_mask, segment):
#         self.args = message,
#         self.start_time = start_time
#         self.end_time = end_time
#         self.time_mask = time_mask
#         self.segment = segment
# 
# Path: skyfield/timelib.py
# def compute_calendar_date(jd_integer, julian_before=None):
#     """Convert Julian day ``jd_integer`` into a calendar (year, month, day).
# 
#     Uses the proleptic Gregorian calendar unless ``julian_before`` is
#     set to a specific Julian day, in which case the Julian calendar is
#     used for dates older than that.
# 
#     """
#     use_gregorian = (julian_before is None) or (jd_integer >= julian_before)
# 
#     # See the Explanatory Supplement to the Astronomical Almanac 15.11.
#     f = jd_integer + 1401
#     f += use_gregorian * ((4 * jd_integer + 274277) // 146097 * 3 // 4 - 38)
#     e = 4 * f + 3
#     g = e % 1461 // 4
#     h = 5 * g + 2
#     day = h % 153 // 5 + 1
#     month = (h // 153 + 2) % 12 + 1
#     year = e // 1461 - 4716 + (12 + 2 - month) // 12
#     return year, month, day
# 
# Path: skyfield/vectorlib.py
# class VectorFunction(object):
# class ReversedVector(VectorFunction):
# class VectorSum(VectorFunction):
#     def vector_name(self):
#     def center_name(self):
#     def target_name(self):
#     def __repr__(self):
#     def __str__(self):
#     def arrow_str(self):
#     def __add__(self, other):
#     def __neg__(self):
#     def __sub__(self, other):
#     def at(self, t):
#     def _observe_from_bcrs(self, observer):
#     def geometry_of(self, other):
#     def topos(self, latitude=None, longitude=None, latitude_degrees=None,
#               longitude_degrees=None, elevation_m=0.0, x=0.0, y=0.0):
#     def satellite(self, text):
#     def __init__(self, vector_function):
#     def vector_name(self):
#     def center_name(self):
#     def target_name(self):
#     def __neg__(self):
#     def _at(self, t):
#     def __init__(self, center, target, vector_functions):
#     def __str__(self):
#     def __repr__(self):
#     def _at(self, t):
# def _correct_for_light_travel_time(observer, target):
# def _jpl_name(target):


import os
from collections import defaultdict
from jplephem.exceptions import OutOfRangeError
from jplephem.spk import SPK
from jplephem.names import target_name_pairs
from .constants import AU_KM, DAY_S
from .errors import EphemerisRangeError
from .timelib import compute_calendar_date
from .vectorlib import VectorFunction, VectorSum, _jpl_code_name_dict
        ``KeyError`` if the target is missing from this kernel.  You can
        supply an integer code if you already have one and just want to
        check whether it is present in this kernel.

        """
        if isinstance(name, int):
            code = name
        else:
            name = name.upper()
            code = _jpl_name_code_dict.get(name)
            if code is None:
                raise ValueError('unknown SPICE target {0!r}'.format(name))
        if code not in self.codes:
            targets = ', '.join(_format_code_and_name(c) for c in self.codes)
            raise KeyError('kernel {0!r} is missing {1!r} -'
                           ' the targets it supports are: {2}'
                           .format(self.filename, name, targets))
        return code

    def __getitem__(self, target):
        """Return a vector function for computing the location of `target`."""
        target = self.decode(target)
        segments = self.segments
        segment_dict = dict((segment.target, segment) for segment in segments)
        chain = tuple(_center(target, segment_dict))
        if len(chain) == 1:
            return chain[0]
        chain = chain[::-1]
        center = chain[0].center
        target = chain[-1].target

# Path: skyfield/constants.py
# AU_KM = 149597870.700
# 
# DAY_S = 86400.0
# 
# Path: skyfield/errors.py
# class EphemerisRangeError(ValueError):
#     """An ephemeris has been asked about positions outside its time range.
# 
#     Attributes:
# 
#     - `start_time`, `end_time`: the range of times supported by the segment
#     - `time_mask`: Boolean array where ``True`` marks out-of-range times
#     - `segment`: the ephemeris segment that was asked for positions
# 
#     """
#     def __init__(self, message, start_time, end_time, time_mask, segment):
#         self.args = message,
#         self.start_time = start_time
#         self.end_time = end_time
#         self.time_mask = time_mask
#         self.segment = segment
# 
# Path: skyfield/timelib.py
# def compute_calendar_date(jd_integer, julian_before=None):
#     """Convert Julian day ``jd_integer`` into a calendar (year, month, day).
# 
#     Uses the proleptic Gregorian calendar unless ``julian_before`` is
#     set to a specific Julian day, in which case the Julian calendar is
#     used for dates older than that.
# 
#     """
#     use_gregorian = (julian_before is None) or (jd_integer >= julian_before)
# 
#     # See the Explanatory Supplement to the Astronomical Almanac 15.11.
#     f = jd_integer + 1401
#     f += use_gregorian * ((4 * jd_integer + 274277) // 146097 * 3 // 4 - 38)
#     e = 4 * f + 3
#     g = e % 1461 // 4
#     h = 5 * g + 2
#     day = h % 153 // 5 + 1
#     month = (h // 153 + 2) % 12 + 1
#     year = e // 1461 - 4716 + (12 + 2 - month) // 12
#     return year, month, day
# 
# Path: skyfield/vectorlib.py
# class VectorFunction(object):
# class ReversedVector(VectorFunction):
# class VectorSum(VectorFunction):
#     def vector_name(self):
#     def center_name(self):
#     def target_name(self):
#     def __repr__(self):
#     def __str__(self):
#     def arrow_str(self):
#     def __add__(self, other):
#     def __neg__(self):
#     def __sub__(self, other):
#     def at(self, t):
#     def _observe_from_bcrs(self, observer):
#     def geometry_of(self, other):
#     def topos(self, latitude=None, longitude=None, latitude_degrees=None,
#               longitude_degrees=None, elevation_m=0.0, x=0.0, y=0.0):
#     def satellite(self, text):
#     def __init__(self, vector_function):
#     def vector_name(self):
#     def center_name(self):
#     def target_name(self):
#     def __neg__(self):
#     def _at(self, t):
#     def __init__(self, center, target, vector_functions):
#     def __str__(self):
#     def __repr__(self):
#     def _at(self, t):
# def _correct_for_light_travel_time(observer, target):
# def _jpl_name(target):


# Path: skyfield/jpllib.py
import os
from collections import defaultdict
from jplephem.exceptions import OutOfRangeError
from jplephem.spk import SPK
from jplephem.names import target_name_pairs
from .constants import AU_KM, DAY_S
from .errors import EphemerisRangeError
from .timelib import compute_calendar_date
from .vectorlib import VectorFunction, VectorSum, _jpl_code_name_dict

        ``KeyError`` if the target is missing from this kernel.  You can
        supply an integer code if you already have one and just want to
        check whether it is present in this kernel.

        """
        if isinstance(name, int):
            code = name
        else:
            name = name.upper()
            code = _jpl_name_code_dict.get(name)
            if code is None:
                raise ValueError('unknown SPICE target {0!r}'.format(name))
        if code not in self.codes:
            targets = ', '.join(_format_code_and_name(c) for c in self.codes)
            raise KeyError('kernel {0!r} is missing {1!r} -'
                           ' the targets it supports are: {2}'
                           .format(self.filename, name, targets))
        return code

    def __getitem__(self, target):
        """Return a vector function for computing the location of `target`."""
        target = self.decode(target)
        segments = self.segments
        segment_dict = dict((segment.target, segment) for segment in segments)
        chain = tuple(_center(target, segment_dict))
        if len(chain) == 1:
            return chain[0]
        chain = chain[::-1]
        center = chain[0].center
        target = chain[-1].target

        return VectorSum(center, target, chain)