Skip to content

Commit 227f07b

Browse files
committed
remove return_raw in favor of OrderedDict. improve nan handling
1 parent 9cc4a8f commit 227f07b

File tree

3 files changed

+150
-61
lines changed

3 files changed

+150
-61
lines changed

pvlib/clearsky.py

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
logger = logging.getLogger('pvlib')
1010

1111
import os
12+
from collections import OrderedDict
1213

1314
import numpy as np
1415
import pandas as pd
@@ -330,7 +331,7 @@ def _linearly_scale(inputmatrix, inputmin, inputmax, outputmin, outputmax):
330331

331332

332333
def simplified_solis(apparent_elevation, aod700=0.1, precipitable_water=1.,
333-
pressure=101325., dni_extra=1364., return_raw=False):
334+
pressure=101325., dni_extra=1364.):
334335
"""
335336
Calculate the clear sky GHI, DNI, and DHI according to the
336337
simplified Solis model [1]_.
@@ -361,17 +362,13 @@ def simplified_solis(apparent_elevation, aod700=0.1, precipitable_water=1.,
361362
dni_extra: numeric
362363
Extraterrestrial irradiance.
363364
364-
return_raw: bool
365-
Controls the return type. If False, function returns a DataFrame,
366-
if True, function returns an array.
367-
368365
Returns
369366
--------
370-
clearsky : pd.DataFrame or np.array (determined by ``return_raw``)
371-
DataFrame contains the columns ``'dhi', 'dni', 'ghi'`` with the
372-
units of the ``dni_extra`` input. If ``return_raw=True``,
373-
returns the array [dhi, dni, ghi] with shape determined by the
374-
input arrays.
367+
clearsky : DataFrame (if Series input) or OrderedDict of arrays
368+
DataFrame/OrderedDict contains the columns/keys
369+
``'dhi', 'dni', 'ghi'``.
370+
371+
The units of ``dni_extra`` determine the units of the output.
375372
376373
References
377374
----------
@@ -410,30 +407,21 @@ def simplified_solis(apparent_elevation, aod700=0.1, precipitable_water=1.,
410407
taud = _calc_taud(w, aod700, p)
411408
d = _calc_d(w, aod700, p)
412409

413-
sin_elev = np.sin(np.radians(apparent_elevation))
410+
# this prevents the creation of nans at night instead of 0s
411+
# it's also friendly to scalar and series inputs
412+
sin_elev = np.maximum(1.e-30, np.sin(np.radians(apparent_elevation)))
414413

415414
dni = i0p * np.exp(-taub/sin_elev**b)
416415
ghi = i0p * np.exp(-taug/sin_elev**g) * sin_elev
417416
dhi = i0p * np.exp(-taud/sin_elev**d)
418417

419-
irrads = np.array([dhi, dni, ghi])
418+
irrads = OrderedDict()
419+
irrads['ghi'] = ghi
420+
irrads['dni'] = dni
421+
irrads['dhi'] = dhi
420422

421-
if not return_raw:
422-
if isinstance(dni, pd.Series):
423-
index = dni.index
424-
else:
425-
index = None
426-
427-
try:
428-
irrads = pd.DataFrame(irrads.T, columns=['dhi', 'dni', 'ghi'],
429-
index=index)
430-
except ValueError:
431-
# probably all scalar input, so we
432-
# need to increase the dimensionality
433-
irrads = pd.DataFrame(np.array([irrads]),
434-
columns=['dhi', 'dni', 'ghi'])
435-
finally:
436-
irrads = irrads.fillna(0)
423+
if isinstance(dni, pd.Series):
424+
irrads = pd.DataFrame.from_dict(irrads)
437425

438426
return irrads
439427

pvlib/test/test_clearsky.py

Lines changed: 126 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import logging
22
pvl_logger = logging.getLogger('pvlib')
33

4+
from collections import OrderedDict
5+
46
import numpy as np
57
import pandas as pd
68

79
from nose.tools import raises
8-
from numpy.testing import assert_almost_equal
10+
from numpy.testing import assert_almost_equal, assert_allclose
911
from pandas.util.testing import assert_frame_equal, assert_series_equal
1012

1113
from pvlib.location import Location
@@ -170,29 +172,42 @@ def test_simplified_solis_series_elevation():
170172

171173

172174
def test_simplified_solis_scalar_elevation():
173-
expected = pd.DataFrame(np.array([[959.335463, 1064.653145, 129.125602]]),
174-
columns=['dni', 'ghi', 'dhi'])
175-
expected = expected[['dhi', 'dni', 'ghi']]
175+
expected = OrderedDict()
176+
expected['ghi'] = 1064.653145
177+
expected['dni'] = 959.335463
178+
expected['dhi'] = 129.125602
176179

177180
out = clearsky.simplified_solis(80)
178-
assert_frame_equal(expected, out)
181+
for k, v in expected.items():
182+
yield assert_allclose, expected[k], out[k]
183+
179184

185+
def test_simplified_solis_scalar_neg_elevation():
186+
expected = OrderedDict()
187+
expected['ghi'] = 0
188+
expected['dni'] = 0
189+
expected['dhi'] = 0
180190

181-
def test_simplified_solis_array_elevation():
191+
out = clearsky.simplified_solis(-10)
192+
for k, v in expected.items():
193+
yield assert_allclose, expected[k], out[k]
194+
195+
196+
def test_simplified_solis_series_elevation():
182197
expected = pd.DataFrame(np.array([[959.335463, 1064.653145, 129.125602]]),
183198
columns=['dni', 'ghi', 'dhi'])
184-
expected = expected[['dhi', 'dni', 'ghi']]
199+
expected = expected[['ghi', 'dni', 'dhi']]
185200

186-
out = clearsky.simplified_solis(np.array([80]))
201+
out = clearsky.simplified_solis(pd.Series(80))
187202
assert_frame_equal(expected, out)
188203

189204

190205
def test_simplified_solis_dni_extra():
191206
expected = pd.DataFrame(np.array([[963.555414, 1069.33637, 129.693603]]),
192207
columns=['dni', 'ghi', 'dhi'])
193-
expected = expected[['dhi', 'dni', 'ghi']]
208+
expected = expected[['ghi', 'dni', 'dhi']]
194209

195-
out = clearsky.simplified_solis(80, dni_extra=1370)
210+
out = clearsky.simplified_solis(80, dni_extra=pd.Series(1370))
196211
assert_frame_equal(expected, out)
197212

198213

@@ -202,10 +217,10 @@ def test_simplified_solis_pressure():
202217
[ 961.88811874, 1066.36847963, 128.1402539 ],
203218
[ 959.58112234, 1064.81837558, 129.0304193 ]]),
204219
columns=['dni', 'ghi', 'dhi'])
205-
expected = expected[['dhi', 'dni', 'ghi']]
220+
expected = expected[['ghi', 'dni', 'dhi']]
206221

207222
out = clearsky.simplified_solis(
208-
80, pressure=np.array([95000, 98000, 101000]))
223+
80, pressure=pd.Series([95000, 98000, 101000]))
209224
assert_frame_equal(expected, out)
210225

211226

@@ -217,9 +232,9 @@ def test_simplified_solis_aod700():
217232
[ 342.45810926, 638.63409683, 77.71786575],
218233
[ 55.24140911, 7.5413313 , 0. ]]),
219234
columns=['dni', 'ghi', 'dhi'])
220-
expected = expected[['dhi', 'dni', 'ghi']]
235+
expected = expected[['ghi', 'dni', 'dhi']]
221236

222-
aod700 = np.array([0.0, 0.05, 0.1, 1, 10])
237+
aod700 = pd.Series([0.0, 0.05, 0.1, 1, 10])
223238
out = clearsky.simplified_solis(80, aod700=aod700)
224239
assert_frame_equal(expected, out)
225240

@@ -232,39 +247,120 @@ def test_simplified_solis_precipitable_water():
232247
[ 959.3354628 , 1064.65314509, 129.12560167],
233248
[ 872.02335029, 974.18046717, 125.63581346]]),
234249
columns=['dni', 'ghi', 'dhi'])
235-
expected = expected[['dhi', 'dni', 'ghi']]
250+
expected = expected[['ghi', 'dni', 'dhi']]
236251

237252
out = clearsky.simplified_solis(
238253
80, precipitable_water=pd.Series([0.0, 0.2, 0.5, 1.0, 5.0]))
239254
assert_frame_equal(expected, out)
240255

241256

242257
def test_simplified_solis_small_scalar_pw():
243-
expected = pd.DataFrame(np.
244-
array([[ 1001.15353307, 1107.84678941, 128.58887606]]),
245-
columns=['dni', 'ghi', 'dhi'])
246-
expected = expected[['dhi', 'dni', 'ghi']]
258+
259+
expected = OrderedDict()
260+
expected['ghi'] = 1107.84678941
261+
expected['dni'] = 1001.15353307
262+
expected['dhi'] = 128.58887606
247263

248264
out = clearsky.simplified_solis(80, precipitable_water=0.1)
249-
assert_frame_equal(expected, out)
265+
for k, v in expected.items():
266+
yield assert_allclose, expected[k], out[k]
267+
250268

269+
def test_simplified_solis_return_arrays():
270+
expected = OrderedDict()
251271

252-
def test_simplified_solis_return_raw():
253-
expected = np.array([[[ 1099.25706525, 656.24601381],
254-
[ 915.31689149, 530.31697378]],
272+
expected['ghi'] = np.array([[ 1148.40081325, 913.42330823],
273+
[ 965.48550828, 760.04527609]])
255274

256-
[[ 1148.40081325, 913.42330823],
257-
[ 965.48550828, 760.04527609]],
275+
expected['dni'] = np.array([[ 1099.25706525, 656.24601381],
276+
[ 915.31689149, 530.31697378]])
258277

259-
[[ 64.1063074 , 254.6186615 ],
260-
[ 62.75642216, 232.21931597]]])
278+
expected['dhi'] = np.array([[ 64.1063074 , 254.6186615 ],
279+
[ 62.75642216, 232.21931597]])
261280

262281
aod700 = np.linspace(0, 0.5, 2)
263282
precipitable_water = np.linspace(0, 10, 2)
264283

265284
aod700, precipitable_water = np.meshgrid(aod700, precipitable_water)
266285

267-
out = clearsky.simplified_solis(80, aod700, precipitable_water,
268-
return_raw=True)
286+
out = clearsky.simplified_solis(80, aod700, precipitable_water)
287+
288+
for k, v in expected.items():
289+
yield assert_allclose, expected[k], out[k]
290+
291+
292+
def test_simplified_solis_nans_arrays():
293+
294+
# construct input arrays that each have 1 nan offset from each other,
295+
# the last point is valid for all arrays
269296

270-
np.allclose(expected, out)
297+
length = 6
298+
299+
apparent_elevation = np.full(length, 80.)
300+
apparent_elevation[0] = np.nan
301+
302+
aod700 = np.full(length, 0.1)
303+
aod700[1] = np.nan
304+
305+
precipitable_water = np.full(length, 0.5)
306+
precipitable_water[2] = np.nan
307+
308+
pressure = np.full(length, 98000.)
309+
pressure[3] = np.nan
310+
311+
dni_extra = np.full(length, 1370.)
312+
dni_extra[4] = np.nan
313+
314+
expected = OrderedDict()
315+
expected['ghi'] = np.full(length, np.nan)
316+
expected['dni'] = np.full(length, np.nan)
317+
expected['dhi'] = np.full(length, np.nan)
318+
319+
expected['ghi'][length-1] = 1096.022736
320+
expected['dni'][length-1] = 990.306854
321+
expected['dhi'][length-1] = 128.664594
322+
323+
out = clearsky.simplified_solis(apparent_elevation, aod700,
324+
precipitable_water, pressure, dni_extra)
325+
326+
for k, v in expected.items():
327+
yield assert_allclose, expected[k], out[k]
328+
329+
330+
def test_simplified_solis_nans_series():
331+
332+
# construct input arrays that each have 1 nan offset from each other,
333+
# the last point is valid for all arrays
334+
335+
length = 6
336+
337+
apparent_elevation = pd.Series(np.full(length, 80.))
338+
apparent_elevation[0] = np.nan
339+
340+
aod700 = np.full(length, 0.1)
341+
aod700[1] = np.nan
342+
343+
precipitable_water = np.full(length, 0.5)
344+
precipitable_water[2] = np.nan
345+
346+
pressure = np.full(length, 98000.)
347+
pressure[3] = np.nan
348+
349+
dni_extra = np.full(length, 1370.)
350+
dni_extra[4] = np.nan
351+
352+
expected = OrderedDict()
353+
expected['ghi'] = np.full(length, np.nan)
354+
expected['dni'] = np.full(length, np.nan)
355+
expected['dhi'] = np.full(length, np.nan)
356+
357+
expected['ghi'][length-1] = 1096.022736
358+
expected['dni'][length-1] = 990.306854
359+
expected['dhi'][length-1] = 128.664594
360+
361+
expected = pd.DataFrame.from_dict(expected)
362+
363+
out = clearsky.simplified_solis(apparent_elevation, aod700,
364+
precipitable_water, pressure, dni_extra)
365+
366+
assert_frame_equal(expected, out)

pvlib/test/test_location.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ def test_get_clearsky_simplified_solis():
9393
[ 0. , 0. , 0. ]]),
9494
columns=['dhi', 'dni', 'ghi'],
9595
index=times)
96+
expected = expected[['ghi', 'dni', 'dhi']]
9697
assert_frame_equal(expected, clearsky)
9798

9899

@@ -112,6 +113,7 @@ def test_get_clearsky_simplified_solis_apparent_elevation():
112113
[ 131.3124497 , 1001.14754036, 1108.14147919]]),
113114
columns=['dhi', 'dni', 'ghi'],
114115
index=times)
116+
expected = expected[['ghi', 'dni', 'dhi']]
115117
assert_frame_equal(expected, clearsky)
116118

117119

@@ -130,6 +132,7 @@ def test_get_clearsky_simplified_solis_dni_extra():
130132
[ 0. , 0. , 0. ]]),
131133
columns=['dhi', 'dni', 'ghi'],
132134
index=times)
135+
expected = expected[['ghi', 'dni', 'dhi']]
133136
assert_frame_equal(expected, clearsky)
134137

135138

@@ -148,6 +151,7 @@ def test_get_clearsky_simplified_solis_pressure():
148151
[ 0. , 0. , 0. ]]),
149152
columns=['dhi', 'dni', 'ghi'],
150153
index=times)
154+
expected = expected[['ghi', 'dni', 'dhi']]
151155
assert_frame_equal(expected, clearsky)
152156

153157

@@ -166,6 +170,7 @@ def test_get_clearsky_simplified_solis_aod_pw():
166170
[ 0. , 0. , 0. ]]),
167171
columns=['dhi', 'dni', 'ghi'],
168172
index=times)
173+
expected = expected[['ghi', 'dni', 'dhi']]
169174
assert_frame_equal(expected, clearsky)
170175

171176

@@ -250,10 +255,10 @@ def test_get_airmass_valueerror():
250255
end='20160101T1800-0700',
251256
freq='3H')
252257
clearsky = tus.get_airmass(times, model='invalid_model')
253-
258+
254259
def test_Location___repr__():
255260
tus = Location(32.2, -111, 'US/Arizona', 700, 'Tucson')
256261
assert tus.__repr__()==('Tucson: latitude=32.2, longitude=-111, '+
257262
'tz=US/Arizona, altitude=700')
258-
259-
263+
264+

0 commit comments

Comments
 (0)