def _init_if_needed(cls):
     if cls._ephemeris is None:
         cls._ephemeris = load_file(_EPHEMERIS_FILE_PATH)
         cls._sun = cls._ephemeris['sun']
         cls._earth = cls._ephemeris['earth']
         cls._moon = cls._ephemeris['moon']
         cls._timescale = load.timescale()
def test_callisto_astrometric(ts):
    e = api.load_file(_data_path('jup310-2053-10-08.bsp'))
    # This date was utc(2053, 10, 9), but new leap seconds keep breaking
    # the test, so:
    a = e['earth'].at(ts.tt(jd=2471184.5007775929)).observe(e['callisto'])
    ra, dec, distance = a.radec()
    compare(ra._degrees, 217.1839292, 0.001 * arcsecond)
    compare(dec.degrees, -13.6892791, 0.001 * arcsecond)
    compare(distance.au, 6.31079291776184, 0.1 * meter)
def test_boston_geometry():
    e = api.load_file(_data_path('jup310-2015-03-02.bsp'))
    t = api.load.timescale(delta_t=67.185390 + 0.5285957).tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8),
                                x=0.003483, y=0.358609)
    a = (e['earth'] - boston).at(t)
    compare(a.position.km,
      [-1.764697476371664E+02, -4.717131288041386E+03, -4.274926422016179E+03],
      0.0027)  # TODO: try to get this < 1 meter
Example #4
0
def test_moon_from_boston_geometry():
    e = api.load_file(_data_path('de430-2015-03-02.bsp'))
    t = api.load.timescale(delta_t=67.185390 + 0.5285957).tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8),
                                x=0.003483, y=0.358609)
    a = (e['moon'] - boston).at(t)
    compare(a.position.au,
      [-1.341501206552443E-03, 2.190483327459023E-03, 6.839177007993498E-04],
      1.7 * meter)  # TODO: improve this
def test_moon_from_boston_geometry():
    e = api.load_file(_data_path('de430-2015-03-02.bsp'))
    t = api.load.timescale(delta_t=67.185390 + 0.5285957).tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8),
                                x=0.003483, y=0.358609)
    a = (e['moon'] - boston).at(t)
    compare(a.position.au,
      [-1.341501206552443E-03, 2.190483327459023E-03, 6.839177007993498E-04],
      1.7 * meter)  # TODO: improve this
Example #6
0
def test_boston_geometry():
    e = api.load_file(_data_path('jup310-2015-03-02.bsp'))
    t = api.load.timescale(delta_t=67.185390 + 0.5285957).tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8),
                                x=0.003483, y=0.358609)
    a = (e['earth'] - boston).at(t)
    compare(a.position.km,
      [-1.764697476371664E+02, -4.717131288041386E+03, -4.274926422016179E+03],
      0.0027)  # TODO: try to get this < 1 meter
def test_callisto_astrometric(ts):
    e = api.load_file(_data_path('jup310-2053-10-08.bsp'))
    # This date was utc(2053, 10, 9), but new leap seconds keep breaking
    # the test, so:
    a = e['earth'].at(ts.tt(jd=2471184.5007775929)).observe(e['callisto'])
    ra, dec, distance = a.radec()
    compare(ra._degrees, 217.1839292, 0.001 * arcsecond)
    compare(dec.degrees, -13.6892791, 0.001 * arcsecond)
    compare(distance.au, 6.31079291776184, 0.2 * meter)
Example #8
0
def test_moon_from_boston_astrometric():
    e = api.load_file(_data_path('de430-2015-03-02.bsp'))
    t = api.load.timescale(delta_t=67.185390 + 0.5285957).tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8),
                                x=0.003483, y=0.358609)
    a = boston.at(t).observe(e['moon'])
    ra, dec, distance = a.radec()
    compare(ra._degrees, 121.4796470, 0.001 * arcsecond)
    compare(dec.degrees, 14.9108450, 0.001 * arcsecond)
    compare(distance.au, 0.00265828588792, 1.4 * meter)  # TODO: improve this
def test_moon_from_boston_astrometric():
    e = api.load_file(_data_path('de430-2015-03-02.bsp'))
    t = api.load.timescale(delta_t=67.185390 + 0.5285957).tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8),
                                x=0.003483, y=0.358609)
    a = boston.at(t).observe(e['moon'])
    ra, dec, distance = a.radec()
    compare(ra._degrees, 121.4796470, 0.001 * arcsecond)
    compare(dec.degrees, 14.9108450, 0.001 * arcsecond)
    compare(distance.au, 0.00265828588792, 1.4 * meter)  # TODO: improve this
def test_callisto_geometry(ts):
    e = api.load_file(_data_path('jup310-2053-10-08.bsp'))
    a = (e['callisto'] - e['earth']).at(ts.tdb(jd=2471184.5))
    print(a)
    compare(a.position.au,
      [-4.884815926454119E+00, -3.705745549073268E+00, -1.493487818022234E+00],
      0.001 * meter)
    compare(a.velocity.au_per_d,
      [9.604665478763035E-03, -1.552997751083403E-02, -6.678445860769302E-03],
      0.00001 * meter)
def test_callisto_geometry(ts):
    e = api.load_file(_data_path('jup310-2053-10-08.bsp'))
    a = (e['callisto'] - e['earth']).at(ts.tdb(jd=2471184.5))
    print(a)
    compare(a.position.au, [
        -4.884815926454119E+00, -3.705745549073268E+00, -1.493487818022234E+00
    ], 0.001 * meter)
    compare(a.velocity.au_per_d, [
        9.604665478763035E-03, -1.552997751083403E-02, -6.678445860769302E-03
    ], 0.00001 * meter)
def test_moon_from_boston_geometry():
    e = api.load_file(_data_path('de430-2015-03-02.bsp'))
    ts = api.load.timescale(delta_t=67.185390 + 0.5285957)
    ts.polar_motion_table = [0.0], [0.003483], [0.358609]
    t = ts.tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8))
    a = (e['moon'] - boston).at(t)
    compare(
        a.position.au,
        [-1.341501206552443E-03, 2.190483327459023E-03, 6.839177007993498E-04],
        1.1 * meter)
def test_boston_geometry():
    e = api.load_file(_data_path('jup310-2015-03-02.bsp'))
    ts = api.load.timescale(delta_t=67.185390 + 0.5285957)
    ts.polar_motion_table = [0.0], [0.003483], [0.358609]
    t = ts.tdb(2015, 3, 2)
    boston = e['earth'] + Topos((42, 21, 24.1), (-71, 3, 24.8))
    a = (e['earth'] - boston).at(t)
    meter = 1e-3
    compare(a.position.km, [
        -1.764697476371664E+02, -4.717131288041386E+03, -4.274926422016179E+03
    ], 0.7 * meter)
def test_position_angle_from_boston(ts):
    t = ts.utc(2053, 10, 9)
    eph = api.load_file(_data_path('jup310-2053-10-08.bsp'))
    boston = eph['earth'] + Topos(longitude_degrees=(-71, 3, 24.8),
                                  latitude_degrees=(42, 21, 24.1))

    b = boston.at(t)
    j = b.observe(eph['jupiter'])  #.apparent()
    i = b.observe(eph['io'])  #.apparent()

    a = position_angle_of(j.radec(epoch='date'), i.radec(epoch='date'))

    assert abs(a.degrees - 293.671) < 0.002

    print(a)
    a = position_angle_of(j.ecliptic_latlon(epoch='date'),
                          i.ecliptic_latlon(epoch='date'))
    print(a)
    def _get_times(self, now: datetime) -> (datetime, datetime):
        midnight = now.replace(hour=0, minute=0, second=0, microsecond=0)
        next_midnight = midnight + timedelta(days=1)

        ts = load.timescale()
        t0 = ts.from_datetime(midnight)
        t1 = ts.from_datetime(next_midnight)
        eph = load_file(config['DE421_PATH'])
        bluffton = wgs84.latlon(config['COORDINATES']['N'] * N, config['COORDINATES']['E'] * E)
        f = almanac.dark_twilight_day(eph, bluffton)
        times, events = almanac.find_discrete(t0, t1, f)

        result = []
        previous_e = None
        for t, e in zip(times, events):
            if e == 4:
                result.append(t.astimezone(self.zone))
            if previous_e == 4:
                result.append(t.astimezone(self.zone))
            previous_e = e

        return result[0], result[1]
Example #16
0
def get_sunrise_sunset_times():
    pownal = api.Topos('43.921554 N', '70.147969 W')
    ts = api.load.timescale(builtin=True)
    eph = api.load_file(settings.SKYFIELD_DATA_PATH)
    now = datetime.now().astimezone()
    today_start = datetime(now.year, now.month, now.day).astimezone()
    today_end = today_start + timedelta(days=1)
    today_start_ts = ts.utc(today_start)
    today_end_ts = ts.utc(today_end)
    traversals, is_sunrise = almanac.find_discrete(
        today_start_ts, today_end_ts, almanac.sunrise_sunset(eph, pownal))
    # If there are multiple sunrises in a day then we have bigger problems than opening the coop door at the right time
    sunrise_iso = traversals[0].utc_iso(
    ) if is_sunrise[0] else traversals[1].utc_iso()
    sunset_iso = traversals[1].utc_iso(
    ) if not is_sunrise[1] else traversals[0].utc_iso()
    sunrise_dtm = datetime.strptime(
        sunrise_iso,
        '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc).astimezone()
    sunset_dtm = datetime.strptime(
        sunset_iso,
        '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc).astimezone()
    return (sunrise_dtm, sunset_dtm)
Example #17
0
def get_sunrise_sunset_noon(latitude=None, longitude=None, date=None, library='skyfield',
                            timezone=False):
    """
    Calculate sunrise, sunset and local solar noon times.

    Parameters
    ----------
    latitude : int, float
        Latitude in degrees north positive. Must be a scalar.
    longitude : int, float
        Longitude in degrees east positive. Must be a scalar.
    date : (datetime.datetime, numpy.datetime64, list of datetime.datetime,
            numpy.array of numpy.datetime64, string, list of string)
        Date(s) to return sunrise, sunset and noon times spaning the first date to last
        date if more than one provided. May be a scalar or vector. If entered as a string must follow
        YYYYMMDD format.
    library : str
        Library to use for making calculations. Options include ['skyfield']
    timezone : boolean
        Have timezone with datetime.

    Returns
    -------
    result : tuple of three numpy.array
        Tuple of three values sunrise, sunset, noon. Values will be a list.
        If no values can be calculated will return empty list. If the date is within
        polar night will return empty lists. If spans the transition to polar day
        will return previous sunrise or next sunset outside of date range provided.
    """

    sunrise, sunset, noon = np.array([]), np.array([]), np.array([])

    if library == 'skyfield':
        ts = load.timescale()
        eph = load_file(skyfield_bsp_file)
        sf_dates = []

        # Parse datetime object
        if isinstance(date, datetime):
            if date.tzinfo is None:
                sf_dates = [date.replace(tzinfo=pytz.UTC)]
            else:
                sf_dates = [date]

        if isinstance(date, (list, tuple)) and isinstance(date[0], datetime):
            if date[0].tzinfo is not None:
                sf_dates = date
            else:
                sf_dates = [ii.replace(tzinfo=pytz.UTC) for ii in date]

        # Parse string date
        if isinstance(date, str):
            sf_dates = [datetime.strptime(date, '%Y%m%d').replace(tzinfo=pytz.UTC)]

        # Parse list of string dates
        if isinstance(date, (list, tuple)) and isinstance(date[0], str):
            sf_dates = [datetime.strptime(dt, '%Y%m%d').replace(tzinfo=pytz.UTC) for dt in date]

        # Convert datetime64 to datetime
        if type(date).__module__ == np.__name__ and np.issubdtype(date.dtype, np.datetime64):
            sf_dates = datetime64_to_datetime(date)
            sf_dates = [ii.replace(tzinfo=pytz.UTC) for ii in sf_dates]

        # Function for calculating solar noon
        # Convert location into skyfield location object
        location = wgs84.latlon(latitude, longitude)
        # Set up function to indicate calculating locatin of Sun from Earth
        f = almanac.meridian_transits(eph, eph['Sun'], location)
        # Set up dates to be start of day and end of day so have a range
        t0 = sf_dates[0]
        t0 = t0.replace(hour=0, minute=0, second=0)
        t1 = sf_dates[-1]
        t1 = t1.replace(hour=23, minute=59, second=59)
        # Convert times from datetime to skyfild times
        t0 = ts.from_datetime(t0)
        t1 = ts.from_datetime(t1)
        # Calculate Meridian Transits. n contains times and x contains 1 and 0's
        # indicating when transit time is above or below location.
        n, x = almanac.find_discrete(t0, t1, f)

        # Determine if time is during daylight
        f = almanac.sunrise_sunset(eph, location)
        sun_up = f(n)

        # Filter out times when sun is below location or in polar night
        n = n[(x == 1) & sun_up]
        noon = n.utc_datetime()
        if noon.size == 0:
            return sunrise, sunset, noon

        # Calcuate sunrise and sunset times. Calcuate over range 12 less than minimum
        # noon time and 12 hours greater than maximum noon time.
        t0 = min(noon) - timedelta(hours=12)
        t1 = max(noon) + timedelta(hours=12)
        t0 = ts.from_datetime(t0)
        t1 = ts.from_datetime(t1)
        f = almanac.sunrise_sunset(eph, location)
        t, y = almanac.find_discrete(t0, t1, f)
        times = t.utc_datetime()
        sunrise = times[y == 1]
        sunset = times[y == 0]

        # Fill in sunrise and sunset if asked to during polar day
        if len(noon) > 0 and (y.size == 0 or len(sunrise) != len(sunset)):
            t0 = min(noon) - timedelta(days=90)
            t1 = max(noon) + timedelta(days=90)
            t0 = ts.from_datetime(t0)
            t1 = ts.from_datetime(t1)
            t, yy = almanac.find_discrete(t0, t1, f)
            times = t.utc_datetime()
            # If first time is sunset and/or last time is sunrise filter
            # from times
            if yy[0] == 0:
                yy = yy[1:]
                times = times[1:]
            if yy[-1] == 1:
                yy = yy[:-1]
                times = times[:-1]

            # Extract sunrise times
            temp_sunrise = times[yy == 1]
            # Extract sunset times
            temp_sunset = times[yy == 0]
            # Look for index closest to first noon time to get the time of last sunrise
            # since we are in polar day.
            diff = temp_sunrise - min(noon)
            sunrise_index = np.max(np.where(diff < timedelta(seconds=1)))
            # Look for index closest to last noon time to get the time of first sunset
            # since we are in polar day.
            diff = max(noon) - temp_sunset
            sunset_index = np.min(np.where(diff < timedelta(seconds=1))) + 1
            sunrise = temp_sunrise[sunrise_index: sunset_index]
            sunset = temp_sunset[sunrise_index: sunset_index]

        eph.close()

    if timezone is False:
        for ii in range(0, sunset.size):
            sunrise[ii] = sunrise[ii].replace(tzinfo=None)
            sunset[ii] = sunset[ii].replace(tzinfo=None)
        for ii in range(0, noon.size):
            noon[ii] = noon[ii].replace(tzinfo=None)

    return sunrise, sunset, noon
Example #18
0
def is_sun_visible(latitude=None, longitude=None, date_time=None, dawn_dusk=False):
    """
    Determine if sun is above horizon at for a list of times.

    Parameters
    ----------
    latitude : int, float
        Latitude in degrees north positive. Must be a scalar.
    longitude : int, float
        Longitude in degrees east positive. Must be a scalar.
    date_time : datetime.datetime, numpy.array.datetime64, list of datetime.datetime
        Datetime with timezone, datetime with no timezone in UTC, or numpy.datetime64
        format in UTC. Can be a single datetime object or list of datetime objects.
    dawn_dusk : boolean
        If set to True, will use skyfields dark_twilight_day function to calculate sun up
        Returns a list of int's instead of boolean.
        0 - Dark of Night
        1 - Astronomical Twilight
        2 - Nautical Twilight
        3 - Civil Twilight
        4 - Sun Is Up

    Returns
    -------
    result : list
        List matching size of date_time containing True/False if sun is above horizon.
    """

    sf_dates = None

    # Check if datetime object is scalar and if has no timezone.
    if isinstance(date_time, datetime):
        if date_time.tzinfo is None:
            sf_dates = [date_time.replace(tzinfo=pytz.UTC)]
        else:
            sf_dates = [date_time]

    # Check if datetime objects in list have timezone. If not add.
    if isinstance(date_time, (list, tuple)) and isinstance(date_time[0], datetime):
        if isinstance(date_time[0], datetime) and date_time[0].tzinfo is not None:
            sf_dates = date_time
        else:
            sf_dates = [ii.replace(tzinfo=pytz.UTC) for ii in date_time]

    # Convert datetime64 to datetime with timezone.
    if type(date_time).__module__ == np.__name__ and np.issubdtype(date_time.dtype, np.datetime64):
        sf_dates = datetime64_to_datetime(date_time)
        sf_dates = [ii.replace(tzinfo=pytz.UTC) for ii in sf_dates]

    if sf_dates is None:
        raise ValueError('The date_time values entered into is_sun_visible() '
                         'do not match input types.')

    ts = load.timescale()
    eph = load_file(skyfield_bsp_file)

    t0 = ts.from_datetimes(sf_dates)
    location = wgs84.latlon(latitude, longitude)
    if dawn_dusk:
        f = almanac.dark_twilight_day(eph, location)
    else:
        f = almanac.sunrise_sunset(eph, location)

    sun_up = f(t0)

    eph.close()

    return sun_up
Example #19
0
def get_solar_azimuth_elevation(latitude=None, longitude=None, time=None, library='skyfield',
                                temperature_C='standard', pressure_mbar='standard'):
    """
    Calculate solar azimuth, elevation and solar distance.


    Parameters
    ----------
    latitude : int, float
        Latitude in degrees north positive. Must be a scalar.
    longitude : int, float
        Longitude in degrees east positive. Must be a scalar.
    time : datetime.datetime, numpy.datetime64, list, numpy.array
        Time in UTC. May be a scalar or vector. datetime must be timezone aware.
    library : str
        Library to use for making calculations. Options include ['skyfield']
    temperature_C : string or list of float
        If library is 'skyfield' the temperature in degrees C at the surface for
        atmospheric compensation of the positon of the sun. Set to None for no
        compensation or 'standard' for standard model with a standard temperature.
    pressure_mbar : string or list of float
        If library is 'skyfield' the pressure in milibars at the surface for
        atmospheric compensation of the positon of the sun. Set to None for no
        compensation or 'standard' for standard model with a standard pressure.

    Returns
    -------
    result : tuple of float
        Values returned are a tuple of elevation, azimuth and distance. Elevation and
        azimuth are in degrees, with distance in Astronomical Units.

    """

    result = {'elevation': None, 'azimuth': None, 'distance': None}

    if library == 'skyfield':
        planets = load_file(skyfield_bsp_file)
        earth, sun = planets['earth'], planets['sun']

        if isinstance(time, datetime) and time.tzinfo is None:
            time = time.replace(tzinfo=pytz.UTC)

        if isinstance(time, (list, tuple)) and time[0].tzinfo is None:
            time = [ii.replace(tzinfo=pytz.UTC) for ii in time]

        if type(time).__module__ == np.__name__ and np.issubdtype(time.dtype, np.datetime64):
            time = time.astype('datetime64[s]').astype(int)
            if time.size > 1:
                time = [datetime.fromtimestamp(tm, timezone.utc) for tm in time]
            else:
                time = [datetime.fromtimestamp(time, timezone.utc)]

        if not isinstance(time, (list, tuple, np.ndarray)):
            time = [time]

        ts = load.timescale()
        t = ts.from_datetimes(time)
        location = earth + wgs84.latlon(latitude * N, longitude * W)
        astrometric = location.at(t).observe(sun)
        alt, az, distance = astrometric.apparent().altaz(temperature_C=temperature_C,
                                                         pressure_mbar=pressure_mbar)
        result = (alt.degrees, az.degrees, distance.au)
        planets.close()

    return result
Example #20
0
    arccos,
)
import os


def ts():
    yield load.timescale()


def _data_path(filename):
    return os.path.join(os.path.dirname(__file__), 'data', filename)


ECLIPTIC = inertial_frames['ECLIPJ2000']

ephem = load_file(_data_path('de430-2015-03-02.bsp'))
jup_ephem = load_file(_data_path('jup310-2015-03-02.bsp'))
io = jup_ephem['io']
moon = ephem['moon']
earth = ephem['earth']
sun = ephem['sun']

seterr(all='raise')


def compare(value, expected_value, epsilon, mod=False):
    """Compares value to expected value, and works if one or both are arrays.

    Also allows epsilon to be an array.

    If mod==True, then compare(0, tau, 0) is True.
Example #21
0
# −3000 to 3000

# https://iopscience.iop.org/article/10.3847/1538-3881/abd414

import pandas as pd
import numpy as np
from skyfield.api import load, load_file

ts = load.timescale()
t = ts.now()

planets = load_file("de422.bsp")

earth, moon = planets["earth"], planets["sun"]

astrometric = earth.at(t).observe(moon)

yearsall = ts.utc(range(-2999, 3000))

ra, dec, dist = earth.at(yearsall).observe(moon).radec()

year_data = []

for dt_i, dist_i in zip(yearsall, dist.au):
    yd = {}
    yd["date"] = dt_i.utc_strftime("%Y-%m-%d")
    yd["distance"] = dist_i
    year_data.append(yd)


yearall_df = pd.DataFrame.from_dict(year_data)
    normpi,
    osculating_elements_of,
)
from numpy import (array, sin, cos, pi, sqrt, ndarray, float64, repeat,
                   seterr, inf, linspace, arccos)
import os

def ts():
    yield load.timescale()

def _data_path(filename):
    return os.path.join(os.path.dirname(__file__), 'data', filename)

ECLIPTIC = inertial_frames['ECLIPJ2000']

ephem = load_file(_data_path('de430-2015-03-02.bsp'))
jup_ephem = load_file(_data_path('jup310-2015-03-02.bsp'))
io = jup_ephem['io']
moon = ephem['moon']
earth = ephem['earth']
sun = ephem['sun']

seterr(all='raise')


def compare(value, expected_value, epsilon, mod=False):
    """Compares value to expected value, and works if one or both are arrays.

    Also allows epsilon to be an array.

    If mod==True, then compare(0, tau, 0) is True.
Example #23
0
timeframe = tk.Frame(window, width=framewidth, height=frameheight * 3 / 4)
timeframe.grid_propagate(0)
timeframe.place(x=0, y=frameheight / 4)

# Get current time.  Default timezone set to EST.
tzonelist = ['UTC', 'EST', 'EDT', 'Others coming soon']
tvar = tk.StringVar(timeframe)
tvar.set(tzonelist[0])
tzone = 'EST'
utc_offset = TimezoneInfo(utc_offset=-5 * u.hour)  # EST by default
ttemp = dt.datetime.now(tz=utc_offset)
t = Time(ttemp)

# plot the moons
directory = './'
moons = load_file(directory + 'jup365.bsp')
io = moons['IO']
europa = moons['EUROPA']
ganymede = moons['GANYMEDE']
callisto = moons['CALLISTO']
jupiter = moons['JUPITER BARYCENTER']
#ts = load.timescale()
ts = load.timescale(builtin=True)
sky = tk.Canvas(moonframe, width=framewidth, height=frameheight / 4)
sky.config(bg="black")
sky.place(relx=0, rely=0)
sky.bind("<Button-1>", mooncoords)
updatemoons()

# display current moon and its position
row_pos = 0.1