-
Notifications
You must be signed in to change notification settings - Fork 1.1k
sunrise and sunset from pyephem #588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
90ea2e0
0b9df18
86cdfa7
06aef3f
a22d846
719009d
aa4f1d6
c08d213
f192547
377658b
f338781
a3bedc0
17564dd
c29ed06
a3d143d
99a75a0
95187d5
e318bad
a88a5b6
2121aa0
c75b10e
f85a46a
6238321
3618022
36bf3cc
39956cc
c0ae1c5
f615f12
47c95c5
bef44f6
c9b5348
92e0677
db08f8d
c05bae7
da2a0e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -438,6 +438,24 @@ def get_sun_rise_set_transit(time, latitude, longitude, how='numpy', | |
return result | ||
|
||
|
||
def _ephem_convert_to_seconds_and_microseconds(date): | ||
# utility from unreleased PyEphem 3.6.7.1 | ||
"""Converts a PyEphem date into seconds""" | ||
microseconds = int(round(24 * 60 * 60 * 1000000 * date)) | ||
seconds, microseconds = divmod(microseconds, 1000000) | ||
seconds -= 2209032000 # difference between epoch 1900 and epoch 1970 | ||
return seconds, microseconds | ||
|
||
|
||
def _ephem_to_timezone(date, tzinfo): | ||
# utility from unreleased PyEphem 3.6.7.1 | ||
""""Convert a PyEphem date into a timezone aware Python datetime representation.""" | ||
seconds, microseconds = _ephem_convert_to_seconds_and_microseconds(date) | ||
date = dt.datetime.fromtimestamp(seconds, tzinfo) | ||
date = date.replace(microsecond=microseconds) | ||
return date | ||
|
||
|
||
def _ephem_setup(latitude, longitude, altitude, pressure, temperature): | ||
import ephem | ||
# initialize a PyEphem observer | ||
|
@@ -453,6 +471,63 @@ def _ephem_setup(latitude, longitude, altitude, pressure, temperature): | |
return obs, sun | ||
|
||
|
||
def ephem_next_rise_set(time, latitude, longitude, altitude=0, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I'll change. I have in mind |
||
pressure=101325, temperature=12): | ||
""" | ||
Calculate the next sunrise and sunset times using the PyEphem package. | ||
|
||
Parameters | ||
---------- | ||
time : pandas.DatetimeIndex | ||
Localized or UTC. | ||
latitude : float | ||
positive is north of 0 | ||
longitude : float | ||
positive is east of 0 | ||
altitude : float, default 0 | ||
distance above sea level in meters. | ||
pressure : int or float, optional, default 101325 | ||
air pressure in Pascals. | ||
temperature : int or float, optional, default 12 | ||
air temperature in degrees C. | ||
|
||
Returns | ||
------- | ||
pandas.DataFrame | ||
index is the same as input time.index | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
columns are 'sunrise' and 'sunset', times are localized to the | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
timezone time.tz | ||
|
||
See also | ||
-------- | ||
pyephem | ||
""" | ||
|
||
try: | ||
import ephem | ||
except ImportError: | ||
raise ImportError('PyEphem must be installed') | ||
|
||
# if localized, convert to UTC. otherwise, assume UTC. | ||
try: | ||
time_utc = time.tz_convert('UTC') | ||
except TypeError: | ||
time_utc = time | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
obs, sun = _ephem_setup(latitude, longitude, altitude, | ||
pressure, temperature) | ||
# create lists of the next sunrise and sunset time localized to time.tz | ||
next_sunrise = [] | ||
next_sunset = [] | ||
for thetime in time_utc: | ||
obs.date = ephem.Date(thetime) | ||
next_sunrise.append(_ephem_to_timezone(obs.next_rising(sun), time.tz)) | ||
next_sunset.append(_ephem_to_timezone(obs.next_setting(sun), time.tz)) | ||
|
||
return pd.DataFrame(index=time, data={'sunrise' : next_sunrise, | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
'sunset' : next_sunset}) | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
def pyephem(time, latitude, longitude, altitude=0, pressure=101325, | ||
temperature=12): | ||
""" | ||
|
@@ -463,9 +538,11 @@ def pyephem(time, latitude, longitude, altitude=0, pressure=101325, | |
time : pandas.DatetimeIndex | ||
Localized or UTC. | ||
latitude : float | ||
positive is north of 0 | ||
longitude : float | ||
positive is east of 0 | ||
altitude : float, default 0 | ||
distance above sea level. | ||
distance above sea level in meters. | ||
pressure : int or float, optional, default 101325 | ||
air pressure in Pascals. | ||
temperature : int or float, optional, default 12 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,21 @@ def expected_solpos_multi(): | |
'apparent_elevation': [39.888378, 39.521740]}, | ||
index=[['2003-10-17T12:30:30Z', '2003-10-18T12:30:30Z']]) | ||
|
||
@pytest.fixture() | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def expected_rise_set(): | ||
# for Golden, CO, from USNO website | ||
times = pd.DatetimeIndex([datetime.datetime(2015, 1, 2), | ||
datetime.datetime(2015, 8, 2),] | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
).tz_localize('MST') | ||
sunrise = pd.DatetimeIndex([datetime.datetime(2015, 1, 2, 7, 19, 2), | ||
datetime.datetime(2015, 8, 2, 5, 1, 26) | ||
]).tz_localize('MST').tolist() | ||
sunset = pd.DatetimeIndex([datetime.datetime(2015, 1, 2, 16, 49, 10), | ||
datetime.datetime(2015, 8, 2, 19, 11, 31) | ||
]).tz_localize('MST').tolist() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. E124 closing bracket does not match visual indentation
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return pd.DataFrame({'sunrise':sunrise, 'sunset':sunset}, index=times) | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
# the physical tests are run at the same time as the NREL SPA test. | ||
# pyephem reproduces the NREL result to 2 decimal places. | ||
# this doesn't mean that one code is better than the other. | ||
|
@@ -125,7 +140,7 @@ def test_spa_python_numba_physical_dst(expected_solpos): | |
|
||
|
||
@needs_pandas_0_17 | ||
def test_get_sun_rise_set_transit(): | ||
def test_get_sun_rise_set_transit(expected_rise_set): | ||
south = Location(-35.0, 0.0, tz='UTC') | ||
times = pd.DatetimeIndex([datetime.datetime(1996, 7, 5, 0), | ||
datetime.datetime(2004, 12, 4, 0)] | ||
|
@@ -136,10 +151,11 @@ def test_get_sun_rise_set_transit(): | |
sunset = pd.DatetimeIndex([datetime.datetime(1996, 7, 5, 17, 1, 4), | ||
datetime.datetime(2004, 12, 4, 19, 2, 2)] | ||
).tz_localize('UTC').tolist() | ||
frame = pd.DataFrame({'sunrise':sunrise, 'sunset':sunset}, index=times) | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
result = solarposition.get_sun_rise_set_transit(times, south.latitude, | ||
south.longitude, | ||
delta_t=64.0) | ||
frame = pd.DataFrame({'sunrise':sunrise, 'sunset':sunset}, index=times) | ||
result_rounded = pd.DataFrame(index=result.index) | ||
# need to iterate because to_datetime does not accept 2D data | ||
# the rounding fails on pandas < 0.17 | ||
|
@@ -150,23 +166,11 @@ def test_get_sun_rise_set_transit(): | |
del result_rounded['transit'] | ||
assert_frame_equal(frame, result_rounded) | ||
|
||
|
||
# tests from USNO | ||
# Golden | ||
golden = Location(39.0, -105.0, tz='MST') | ||
times = pd.DatetimeIndex([datetime.datetime(2015, 1, 2), | ||
datetime.datetime(2015, 8, 2),] | ||
).tz_localize('MST') | ||
sunrise = pd.DatetimeIndex([datetime.datetime(2015, 1, 2, 7, 19, 2), | ||
datetime.datetime(2015, 8, 2, 5, 1, 26) | ||
]).tz_localize('MST').tolist() | ||
sunset = pd.DatetimeIndex([datetime.datetime(2015, 1, 2, 16, 49, 10), | ||
datetime.datetime(2015, 8, 2, 19, 11, 31) | ||
]).tz_localize('MST').tolist() | ||
result = solarposition.get_sun_rise_set_transit(times, golden.latitude, | ||
# test for Golden, CO compare to USNO | ||
result = solarposition.get_sun_rise_set_transit(expected_rise_set.index, | ||
golden.latitude, | ||
golden.longitude, | ||
delta_t=64.0) | ||
frame = pd.DataFrame({'sunrise':sunrise, 'sunset':sunset}, index=times) | ||
result_rounded = pd.DataFrame(index=result.index) | ||
# need to iterate because to_datetime does not accept 2D data | ||
# the rounding fails on pandas < 0.17 | ||
|
@@ -176,7 +180,25 @@ def test_get_sun_rise_set_transit(): | |
.tz_convert('MST')) | ||
|
||
del result_rounded['transit'] | ||
assert_frame_equal(frame, result_rounded) | ||
assert_frame_equal(expected_rise_set, result_rounded) | ||
|
||
|
||
@requires_ephem | ||
def test_ephem_next_rise_set(expected_rise_set): | ||
# test for Golden, CO compare to USNO | ||
result = solarposition.ephem_next_rise_set(expected_rise_set.index, | ||
golden.latitude, | ||
golden.longitude, | ||
golden.altitude, | ||
pressure=101325, | ||
temperature=12) | ||
result_rounded = pd.DataFrame(index=result.index) | ||
for col, data in result.iteritems(): | ||
result_rounded[col] = (pd.to_datetime( | ||
np.floor(data.values.astype(np.int64) / 1e9)*1e9, utc=True) | ||
cwhanse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.tz_convert('MST')) | ||
|
||
assert_frame_equal(expected_rise_set, result_rounded) | ||
|
||
|
||
@requires_ephem | ||
|
@@ -190,6 +212,7 @@ def test_pyephem_physical(expected_solpos): | |
assert_frame_equal(expected_solpos.round(2), | ||
ephem_data[expected_solpos.columns].round(2)) | ||
|
||
|
||
@requires_ephem | ||
def test_pyephem_physical_dst(expected_solpos): | ||
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30), periods=1, | ||
|
@@ -201,6 +224,7 @@ def test_pyephem_physical_dst(expected_solpos): | |
assert_frame_equal(expected_solpos.round(2), | ||
ephem_data[expected_solpos.columns].round(2)) | ||
|
||
|
||
@requires_ephem | ||
def test_calc_time(): | ||
import pytz | ||
|
@@ -227,6 +251,7 @@ def test_calc_time(): | |
assert_allclose((az.replace(second=0, microsecond=0) - | ||
epoch_dt).total_seconds(), actual_timestamp) | ||
|
||
|
||
@requires_ephem | ||
def test_earthsun_distance(): | ||
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30), | ||
|
Uh oh!
There was an error while loading. Please reload this page.