# Path: skyfield/api.py
# N = E = +1.0
# S = W = -1.0
# 
# Path: skyfield/constants.py
# AU_M = 149597870700             # per IAU 2012 Resolution B2
# AU_KM = 149597870.700
# ASEC360 = 1296000.0
# DAY_S = 86400.0
# ASEC2RAD = 4.848136811095359935899141e-6
# DEG2RAD = 0.017453292519943296
# RAD2DEG = 57.295779513082321
# C = 299792458.0                            # m/s
# ANGVEL = 7.2921150e-5           # radians/s
# ERAD = 6378136.6                # meters
# IERS_2010_INVERSE_EARTH_FLATTENING = 298.25642
# GS = 1.32712440017987e+20
# T0 = 2451545.0
# B1950 = 2433282.4235
# C_AUDAY = C * DAY_S / AU_M
# 
# Path: skyfield/vectorlib.py
# class VectorSum(VectorFunction):
#     def __init__(self, center, target, vector_functions):
#         self.center = center
#         self.target = target
#         self.vector_functions = vector_functions
# 
#         # For now, just grab the first ephemeris we can find.
#         ephemerides = (segment.ephemeris for segment in vector_functions
#                        if segment.ephemeris)
#         self.ephemeris = next(ephemerides, None)
# 
#     def __str__(self):
#         vector_functions = self.vector_functions
#         lines = [' ' + segment.arrow_str() for segment in vector_functions]
#         return 'Sum of {0} vectors:\n{1}'.format(
#             len(vector_functions),
#             '\n'.join(lines),
#         )
# 
#     def __repr__(self):
#         return '<Vector{0}>'.format(self)
# 
#     def _at(self, t):
#         p, v = 0.0, 0.0
#         gcrs_position = None
#         vfs = self.vector_functions
#         for vf in vfs:
#             p2, v2, _, message = vf._at(t)
#             if vf.center == 399:
#                 gcrs_position = -p
#             p += p2
#             v += v2
#         if vfs[0].center == 0 and vf.center == 399:
#             gcrs_position = p2
#         return p, v, gcrs_position, message
# 
# Path: skyfield/elementslib.py
# def osculating_elements_of(position, reference_frame=None, gm_km3_s2=None):
#     """Produce the osculating orbital elements for a position.
# 
#     `position` is an instance of :class:`~skyfield.positionlib.ICRF`.
#     These are commonly returned by the ``at()`` method of any
#     Solar System body. ``reference_frame`` is an optional argument
#     and is a 3x3 numpy array. The reference frame by default
#     is the ICRF. Commonly used reference frames are found in
#     skyfield.data.spice.inertial_frames. ``gm_km3_s2`` is an optional
#     float argument representing the gravitational parameter (G*M) in
#     units of km^3/s^2, which is the sum of the masses of the orbiting
#     object and the object being orbited. If not specified, this is
#     calculated for you.
# 
#     This function returns an instance of :class:`~skyfield.elementslib.OsculatingElements`
# 
#     """
#     if gm_km3_s2 is None:
#         if not isinstance(position.center, int):
#             raise ValueError('Skyfield is unable to calculate a value for GM. You'
#                     ' should specify one using the `gm_km3_s2` keyword argument')
#         gm_km3_s2 = GM_dict.get(position.center, 0.0)
#         orbits_barycenter = 0 <= position.center <= 9
#         if not orbits_barycenter:
#             gm_km3_s2 += GM_dict.get(position.target, 0.0)
# 
#         if gm_km3_s2 == 0:
#             raise ValueError('Skyfield is unable to calculate a value for GM. You'
#                     ' should specify one using the `gm_km3_s2` keyword argument')
# 
#     if reference_frame is not None:
#         position_vec = Distance(reference_frame.dot(position.position.au))
#         velocity_vec = Velocity(reference_frame.dot(position.velocity.au_per_d))
#     else:
#         position_vec = position.position
#         velocity_vec = position.velocity
# 
#     return OsculatingElements(position_vec,
#                               velocity_vec,
#                               position.t,
#                               gm_km3_s2)


from skyfield.api import load, Topos, EarthSatellite, Angle, Star
from skyfield.constants import tau
from skyfield.vectorlib import VectorSum
from skyfield.elementslib import osculating_elements_of
from optimizelib import secant, brent_min
from numpy import (degrees, arcsin, isfinite, hstack, nan, empty, linspace, 
                   ceil, sign, nonzero, zeros, empty_like, array)
from functools import partial
"""
Rough outline of how this module finds times of phenomena:

    * Split the time interval evenly into partitions. The partitions 
    should be small enough that no partitions contain multiple target values.
    * Evaluate the objective function at the partition edges to determine which 
    partitions contain the points of interest.
    * Pass the partitions that contain points of interest to the vectorized 
    optimization routines.
    
Some other things to be aware of are:
    
    * The variable ``f`` is the plain objective function that returns numbers 
    directly from skyfield.
    * The variable ``g`` is ``f`` transformed such that either all the target 
    values appear to the secant method as roots, or such that all of the 
    extremes appear to Brent's method as minima.
    
"""

__all__ = ['meridian_transits', 'culminations', 'risings_settings', 
           'twilights', 'seasons', 'moon_phases']


# Path: skyfield/api.py
# N = E = +1.0
# S = W = -1.0
# 
# Path: skyfield/constants.py
# AU_M = 149597870700             # per IAU 2012 Resolution B2
# AU_KM = 149597870.700
# ASEC360 = 1296000.0
# DAY_S = 86400.0
# ASEC2RAD = 4.848136811095359935899141e-6
# DEG2RAD = 0.017453292519943296
# RAD2DEG = 57.295779513082321
# C = 299792458.0                            # m/s
# ANGVEL = 7.2921150e-5           # radians/s
# ERAD = 6378136.6                # meters
# IERS_2010_INVERSE_EARTH_FLATTENING = 298.25642
# GS = 1.32712440017987e+20
# T0 = 2451545.0
# B1950 = 2433282.4235
# C_AUDAY = C * DAY_S / AU_M
# 
# Path: skyfield/vectorlib.py
# class VectorSum(VectorFunction):
#     def __init__(self, center, target, vector_functions):
#         self.center = center
#         self.target = target
#         self.vector_functions = vector_functions
# 
#         # For now, just grab the first ephemeris we can find.
#         ephemerides = (segment.ephemeris for segment in vector_functions
#                        if segment.ephemeris)
#         self.ephemeris = next(ephemerides, None)
# 
#     def __str__(self):
#         vector_functions = self.vector_functions
#         lines = [' ' + segment.arrow_str() for segment in vector_functions]
#         return 'Sum of {0} vectors:\n{1}'.format(
#             len(vector_functions),
#             '\n'.join(lines),
#         )
# 
#     def __repr__(self):
#         return '<Vector{0}>'.format(self)
# 
#     def _at(self, t):
#         p, v = 0.0, 0.0
#         gcrs_position = None
#         vfs = self.vector_functions
#         for vf in vfs:
#             p2, v2, _, message = vf._at(t)
#             if vf.center == 399:
#                 gcrs_position = -p
#             p += p2
#             v += v2
#         if vfs[0].center == 0 and vf.center == 399:
#             gcrs_position = p2
#         return p, v, gcrs_position, message
# 
# Path: skyfield/elementslib.py
# def osculating_elements_of(position, reference_frame=None, gm_km3_s2=None):
#     """Produce the osculating orbital elements for a position.
# 
#     `position` is an instance of :class:`~skyfield.positionlib.ICRF`.
#     These are commonly returned by the ``at()`` method of any
#     Solar System body. ``reference_frame`` is an optional argument
#     and is a 3x3 numpy array. The reference frame by default
#     is the ICRF. Commonly used reference frames are found in
#     skyfield.data.spice.inertial_frames. ``gm_km3_s2`` is an optional
#     float argument representing the gravitational parameter (G*M) in
#     units of km^3/s^2, which is the sum of the masses of the orbiting
#     object and the object being orbited. If not specified, this is
#     calculated for you.
# 
#     This function returns an instance of :class:`~skyfield.elementslib.OsculatingElements`
# 
#     """
#     if gm_km3_s2 is None:
#         if not isinstance(position.center, int):
#             raise ValueError('Skyfield is unable to calculate a value for GM. You'
#                     ' should specify one using the `gm_km3_s2` keyword argument')
#         gm_km3_s2 = GM_dict.get(position.center, 0.0)
#         orbits_barycenter = 0 <= position.center <= 9
#         if not orbits_barycenter:
#             gm_km3_s2 += GM_dict.get(position.target, 0.0)
# 
#         if gm_km3_s2 == 0:
#             raise ValueError('Skyfield is unable to calculate a value for GM. You'
#                     ' should specify one using the `gm_km3_s2` keyword argument')
# 
#     if reference_frame is not None:
#         position_vec = Distance(reference_frame.dot(position.position.au))
#         velocity_vec = Velocity(reference_frame.dot(position.velocity.au_per_d))
#     else:
#         position_vec = position.position
#         velocity_vec = position.velocity
# 
#     return OsculatingElements(position_vec,
#                               velocity_vec,
#                               position.t,
#                               gm_km3_s2)


# Path: contrib/almanac2/almanac2.py
from skyfield.api import load, Topos, EarthSatellite, Angle, Star
from skyfield.constants import tau
from skyfield.vectorlib import VectorSum
from skyfield.elementslib import osculating_elements_of
from optimizelib import secant, brent_min
from numpy import (degrees, arcsin, isfinite, hstack, nan, empty, linspace, 
                   ceil, sign, nonzero, zeros, empty_like, array)
from functools import partial

"""
Rough outline of how this module finds times of phenomena:

    * Split the time interval evenly into partitions. The partitions 
    should be small enough that no partitions contain multiple target values.
    * Evaluate the objective function at the partition edges to determine which 
    partitions contain the points of interest.
    * Pass the partitions that contain points of interest to the vectorized 
    optimization routines.
    
Some other things to be aware of are:
    
    * The variable ``f`` is the plain objective function that returns numbers 
    directly from skyfield.
    * The variable ``g`` is ``f`` transformed such that either all the target 
    values appear to the secant method as roots, or such that all of the 
    extremes appear to Brent's method as minima.
    
"""

__all__ = ['meridian_transits', 'culminations', 'risings_settings', 
           'twilights', 'seasons', 'moon_phases']


ts = load.timescale()