Skip to content

Commit ab6063f

Browse files
committed
solarposition.get_solarposition is smart about alt pressure kwargs
1 parent 4c3ad9b commit ab6063f

File tree

4 files changed

+139
-51
lines changed

4 files changed

+139
-51
lines changed

pvlib/solarposition.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@
2525
import numpy as np
2626
import pandas as pd
2727

28-
28+
from pvlib import atmosphere
2929
from pvlib.tools import localize_to_utc, datetime_to_djd, djd_to_datetime
3030

3131

3232
def get_solarposition(time, latitude, longitude,
33-
altitude=0,
34-
method='nrel_numpy', pressure=101325,
33+
altitude=None, pressure=None,
34+
method='nrel_numpy',
3535
temperature=12, **kwargs):
3636
"""
3737
A convenience wrapper for the solar position calculators.
@@ -42,6 +42,11 @@ def get_solarposition(time, latitude, longitude,
4242
latitude : float
4343
longitude : float
4444
altitude : None or float
45+
If None, computed from pressure. Assumed to be 0 m
46+
if pressure is also None.
47+
pressure : None or float
48+
If None, computed from altitude. Assumed to be 101325 Pa
49+
if altitude is also None.
4550
method : string
4651
'pyephem' uses the PyEphem package: :func:`pyephem`
4752
@@ -54,8 +59,6 @@ def get_solarposition(time, latitude, longitude,
5459
described in [1], but also compiles the code first: :func:`spa_python`
5560
5661
'ephemeris' uses the pvlib ephemeris code: :func:`ephemeris`
57-
pressure : float
58-
Pascals.
5962
temperature : float
6063
Degrees C.
6164
@@ -71,7 +74,15 @@ def get_solarposition(time, latitude, longitude,
7174
7275
[3] NREL SPA code: http://rredc.nrel.gov/solar/codesandalgorithms/spa/
7376
"""
74-
77+
78+
if altitude is None and pressure is None:
79+
altitude = 0.
80+
pressure = 101325.
81+
elif altitude is None:
82+
altitude = atmosphere.pres2alt(pressure)
83+
elif pressure is None:
84+
pressure = atmosphere.alt2pres(altitude)
85+
7586
method = method.lower()
7687
if isinstance(time, dt.datetime):
7788
time = pd.DatetimeIndex([time, ])
@@ -163,7 +174,7 @@ def spa_c(time, latitude, longitude, pressure=101325, altitude=0,
163174
pvl_logger.debug('using built-in spa code to calculate solar position')
164175

165176
time_utc = time
166-
177+
167178
spa_out = []
168179

169180
for date in time_utc:

pvlib/test/test_clearsky.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,19 @@ def test_ineichen_required():
3939
index=times_localized)
4040
out = clearsky.ineichen(times_localized, tus.latitude, tus.longitude)
4141
assert_frame_equal(expected, out)
42-
42+
4343

4444
def test_ineichen_supply_linke():
45-
expected = pd.DataFrame(
46-
np.array([[ 0. , 0. , 0. ],
47-
[ 0. , 0. , 0. ],
48-
[ 40.19492186, 322.1949484 , 80.27218726],
49-
[ 95.14479487, 876.49778895, 703.49655602],
50-
[ 118.45876694, 939.816594 , 1042.34575261],
51-
[ 105.36721216, 909.11474576, 851.33560265],
52-
[ 61.91851386, 647.43752674, 257.50239737],
53-
[ 0. , 0. , 0. ],
54-
[ 0. , 0. , 0. ]]),
45+
expected = pd.DataFrame(np.array(
46+
[[ 0. , 0. , 0. ],
47+
[ 0. , 0. , 0. ],
48+
[ 40.16490879, 321.71856556, 80.12815294],
49+
[ 95.14336873, 876.49252839, 703.47605855],
50+
[ 118.4587024 , 939.81646535, 1042.34480815],
51+
[ 105.36645492, 909.11265773, 851.32459694],
52+
[ 61.91187639, 647.35889938, 257.42691896],
53+
[ 0. , 0. , 0. ],
54+
[ 0. , 0. , 0. ]]),
5555
columns=['dhi', 'dni', 'ghi'],
5656
index=times_localized)
5757
out = clearsky.ineichen(times_localized, tus.latitude, tus.longitude,

pvlib/test/test_location.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,18 @@
1515

1616
def test_location_required():
1717
Location(32.2, -111)
18-
18+
1919
def test_location_all():
2020
Location(32.2, -111, 'US/Arizona', 700, 'Tucson')
2121

22-
@raises(UnknownTimeZoneError)
22+
@raises(UnknownTimeZoneError)
2323
def test_location_invalid_tz():
2424
Location(32.2, -111, 'invalid')
25-
25+
2626
@raises(TypeError)
2727
def test_location_invalid_tz_type():
2828
Location(32.2, -111, [5])
29-
29+
3030
def test_location_pytz_tz():
3131
Location(32.2, -111, aztz)
3232

@@ -38,7 +38,7 @@ def test_location_print_all():
3838
tus = Location(32.2, -111, 'US/Arizona', 700, 'Tucson')
3939
expected_str = 'Tucson: latitude=32.2, longitude=-111, tz=US/Arizona, altitude=700'
4040
assert tus.__str__() == expected_str
41-
41+
4242
def test_location_print_pytz():
4343
tus = Location(32.2, -111, aztz, 700, 'Tucson')
4444
expected_str = 'Tucson: latitude=32.2, longitude=-111, tz=US/Arizona, altitude=700'
@@ -52,11 +52,11 @@ def test_get_clearsky():
5252
freq='3H')
5353
clearsky = tus.get_clearsky(times)
5454
expected = pd.DataFrame(data=np.array(
55-
[[ 0. , 0. , 0. ],
56-
[ 49.99776128, 763.02009659, 258.93387913],
57-
[ 70.79971557, 957.15432484, 612.08052529],
58-
[ 59.01912609, 879.09965133, 415.32459426],
59-
[ 0. , 0. , 0. ]]),
55+
[[ 0. , 0. , 0. ],
56+
[ 49.99257714, 762.92663984, 258.84368467],
57+
[ 70.79757257, 957.14396999, 612.04545874],
58+
[ 59.01570645, 879.06844381, 415.26616693],
59+
[ 0. , 0. , 0. ]]),
6060
columns=['dhi', 'dni', 'ghi'],
6161
index=times)
6262
assert_frame_equal(expected, clearsky)
@@ -123,7 +123,7 @@ def test_get_solarposition():
123123
this_expected = np.round(this_expected, 3)
124124
print(this_expected, ephem_data[expected.columns])
125125
assert_frame_equal(this_expected, ephem_data[expected.columns])
126-
126+
127127

128128
def test_get_airmass():
129129
tus = Location(32.2, -111, 'US/Arizona', 700, 'Tucson')
@@ -159,4 +159,4 @@ def test_get_airmass_valueerror():
159159
times = pd.DatetimeIndex(start='20160101T0600-0700',
160160
end='20160101T1800-0700',
161161
freq='3H')
162-
clearsky = tus.get_airmass(times, model='invalid_model')
162+
clearsky = tus.get_airmass(times, model='invalid_model')

pvlib/test/test_solarposition.py

Lines changed: 98 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from . import requires_ephem
1818

1919
# setup times and locations to be tested.
20-
times = pd.date_range(start=datetime.datetime(2014,6,24),
20+
times = pd.date_range(start=datetime.datetime(2014,6,24),
2121
end=datetime.datetime(2014,6,26), freq='15Min')
2222

2323
tus = Location(32.2, -111, 'US/Arizona', 700) # no DST issues possible
@@ -37,7 +37,7 @@
3737

3838
# the physical tests are run at the same time as the NREL SPA test.
3939
# pyephem reproduces the NREL result to 2 decimal places.
40-
# this doesn't mean that one code is better than the other.
40+
# this doesn't mean that one code is better than the other.
4141

4242

4343
def test_spa_c_physical():
@@ -46,15 +46,15 @@ def test_spa_c_physical():
4646
try:
4747
ephem_data = solarposition.spa_c(times, golden_mst.latitude,
4848
golden_mst.longitude,
49-
pressure=82000,
49+
pressure=82000,
5050
temperature=11)
5151
except ImportError:
5252
raise SkipTest
5353
this_expected = expected.copy()
5454
this_expected.index = times
5555
assert_frame_equal(this_expected, ephem_data[expected.columns])
56-
57-
56+
57+
5858
def test_spa_c_physical_dst():
5959
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
6060
periods=1, freq='D', tz=golden.tz)
@@ -64,7 +64,7 @@ def test_spa_c_physical_dst():
6464
pressure=82000,
6565
temperature=11)
6666
except ImportError:
67-
raise SkipTest
67+
raise SkipTest
6868
this_expected = expected.copy()
6969
this_expected.index = times
7070
assert_frame_equal(this_expected, ephem_data[expected.columns])
@@ -75,8 +75,8 @@ def test_spa_python_numpy_physical():
7575
periods=1, freq='D', tz=golden_mst.tz)
7676
ephem_data = solarposition.spa_python(times, golden_mst.latitude,
7777
golden_mst.longitude,
78-
pressure=82000,
79-
temperature=11, delta_t=67,
78+
pressure=82000,
79+
temperature=11, delta_t=67,
8080
atmos_refract=0.5667,
8181
how='numpy')
8282
this_expected = expected.copy()
@@ -89,8 +89,8 @@ def test_spa_python_numpy_physical_dst():
8989
periods=1, freq='D', tz=golden.tz)
9090
ephem_data = solarposition.spa_python(times, golden.latitude,
9191
golden.longitude,
92-
pressure=82000,
93-
temperature=11, delta_t=67,
92+
pressure=82000,
93+
temperature=11, delta_t=67,
9494
atmos_refract=0.5667,
9595
how='numpy')
9696
this_expected = expected.copy()
@@ -106,13 +106,13 @@ def test_spa_python_numba_physical():
106106
vers = numba.__version__.split('.')
107107
if int(vers[0] + vers[1]) < 17:
108108
raise SkipTest
109-
109+
110110
times = pd.date_range(datetime.datetime(2003,10,17,12,30,30),
111111
periods=1, freq='D', tz=golden_mst.tz)
112112
ephem_data = solarposition.spa_python(times, golden_mst.latitude,
113113
golden_mst.longitude,
114-
pressure=82000,
115-
temperature=11, delta_t=67,
114+
pressure=82000,
115+
temperature=11, delta_t=67,
116116
atmos_refract=0.5667,
117117
how='numba', numthreads=1)
118118
this_expected = expected.copy()
@@ -132,8 +132,8 @@ def test_spa_python_numba_physical_dst():
132132
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
133133
periods=1, freq='D', tz=golden.tz)
134134
ephem_data = solarposition.spa_python(times, golden.latitude,
135-
golden.longitude, pressure=82000,
136-
temperature=11, delta_t=67,
135+
golden.longitude, pressure=82000,
136+
temperature=11, delta_t=67,
137137
atmos_refract=0.5667,
138138
how='numba', numthreads=1)
139139
this_expected = expected.copy()
@@ -153,7 +153,7 @@ def test_get_sun_rise_set_transit():
153153
datetime.datetime(2004, 12, 4, 19, 2, 2, 499704)]
154154
).tz_localize('UTC').tolist()
155155
result = solarposition.get_sun_rise_set_transit(times, south.latitude,
156-
south.longitude,
156+
south.longitude,
157157
delta_t=64.0)
158158
frame = pd.DataFrame({'sunrise':sunrise, 'sunset':sunset}, index=times)
159159
del result['transit']
@@ -211,7 +211,7 @@ def test_calc_time():
211211

212212
epoch = datetime.datetime(1970,1,1)
213213
epoch_dt = pytz.utc.localize(epoch)
214-
214+
215215
loc = tus
216216
loc.pressure = 0
217217
actual_time = pytz.timezone(loc.tz).localize(datetime.datetime(2014, 10, 10, 8, 30))
@@ -222,12 +222,12 @@ def test_calc_time():
222222
az = solarposition.calc_time(lb, ub, loc.latitude, loc.longitude,
223223
'az', math.radians(116.3))
224224
actual_timestamp = (actual_time - epoch_dt).total_seconds()
225-
226-
assert_almost_equals((alt.replace(second=0, microsecond=0) -
225+
226+
assert_almost_equals((alt.replace(second=0, microsecond=0) -
227227
epoch_dt).total_seconds(), actual_timestamp)
228-
assert_almost_equals((az.replace(second=0, microsecond=0) -
228+
assert_almost_equals((az.replace(second=0, microsecond=0) -
229229
epoch_dt).total_seconds(), actual_timestamp)
230-
230+
231231
@requires_ephem
232232
def test_earthsun_distance():
233233
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
@@ -261,3 +261,80 @@ def test_ephemeris_physical_dst():
261261
this_expected = np.round(this_expected, 2)
262262
ephem_data = np.round(ephem_data, 2)
263263
assert_frame_equal(this_expected, ephem_data[this_expected.columns])
264+
265+
@raises(ValueError)
266+
def test_get_solarposition_error():
267+
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
268+
periods=1, freq='D', tz=golden.tz)
269+
ephem_data = solarposition.get_solarposition(times, golden.latitude,
270+
golden.longitude,
271+
pressure=82000,
272+
temperature=11,
273+
method='error this')
274+
275+
def test_get_solarposition_pressure():
276+
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
277+
periods=1, freq='D', tz=golden.tz)
278+
ephem_data = solarposition.get_solarposition(times, golden.latitude,
279+
golden.longitude,
280+
pressure=82000,
281+
temperature=11)
282+
this_expected = expected.copy()
283+
this_expected.index = times
284+
this_expected = np.round(this_expected, 5)
285+
ephem_data = np.round(ephem_data, 5)
286+
assert_frame_equal(this_expected, ephem_data[this_expected.columns])
287+
288+
ephem_data = solarposition.get_solarposition(times, golden.latitude,
289+
golden.longitude,
290+
pressure=0.0,
291+
temperature=11)
292+
this_expected = expected.copy()
293+
this_expected.index = times
294+
this_expected = np.round(this_expected, 5)
295+
ephem_data = np.round(ephem_data, 5)
296+
try:
297+
assert_frame_equal(this_expected, ephem_data[this_expected.columns])
298+
except AssertionError:
299+
pass
300+
else:
301+
raise AssertionError
302+
303+
def test_get_solarposition_altitude():
304+
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
305+
periods=1, freq='D', tz=golden.tz)
306+
ephem_data = solarposition.get_solarposition(times, golden.latitude,
307+
golden.longitude,
308+
altitude=golden.altitude,
309+
temperature=11)
310+
this_expected = expected.copy()
311+
this_expected.index = times
312+
this_expected = np.round(this_expected, 5)
313+
ephem_data = np.round(ephem_data, 5)
314+
assert_frame_equal(this_expected, ephem_data[this_expected.columns])
315+
316+
ephem_data = solarposition.get_solarposition(times, golden.latitude,
317+
golden.longitude,
318+
altitude=0.0,
319+
temperature=11)
320+
this_expected = expected.copy()
321+
this_expected.index = times
322+
this_expected = np.round(this_expected, 5)
323+
ephem_data = np.round(ephem_data, 5)
324+
try:
325+
assert_frame_equal(this_expected, ephem_data[this_expected.columns])
326+
except AssertionError:
327+
pass
328+
else:
329+
raise AssertionError
330+
331+
def test_get_solarposition_no_kwargs():
332+
times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
333+
periods=1, freq='D', tz=golden.tz)
334+
ephem_data = solarposition.get_solarposition(times, golden.latitude,
335+
golden.longitude)
336+
this_expected = expected.copy()
337+
this_expected.index = times
338+
this_expected = np.round(this_expected, 2)
339+
ephem_data = np.round(ephem_data, 2)
340+
assert_frame_equal(this_expected, ephem_data[this_expected.columns])

0 commit comments

Comments
 (0)