Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 37fba6b

Browse filesBrowse files
jssteinkandersolar
andauthored
Adds ability for soiling.Hsu to accept arbitrary time intervals (other than 1 hour) (#980)
* bug fixes to hsu soiling function. Addresses (#970) * Made changes to the soiling tests Addresses (#970) * update what's new documentation * Fixed stickler-ci issues in test_soiling.py * Fixed errant character in test * allowed function to accept aribtrary time intervals * updated v0.8.0.rst file * Add variable time interval functionality and testing to soiling.hsu(), also corrected horiz_mass_rate equation * fixed typo in test_soiling.py * fixed stickler-ci errors * fixed more formatting errors * more stickler-ci issues fixed * fixed more stickler-ci issues * formatting issues * formatting issues * formatting... * formatting..... * changed variable time interval calculation in hsu model and test * formatting changes * formatting * formatting * formatting * whatsnew PR links * remove needs_pandas_22 from test_soiling * move time interval note from bug fixes to enhancements * stickler * review improvements Co-authored-by: Kevin Anderson <kevin.anderson@nrel.gov>
1 parent 8ca32c9 commit 37fba6b
Copy full SHA for 37fba6b

File tree

Expand file treeCollapse file tree

3 files changed

+69
-25
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+69
-25
lines changed

‎docs/sphinx/source/whatsnew/v0.8.0.rst

Copy file name to clipboardExpand all lines: docs/sphinx/source/whatsnew/v0.8.0.rst
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@ Enhancements
7878
* Added *racking_model*, *module_type*, and *temperature_model_parameters* to
7979
PVSystem, LocalizedPVSystem, SingleAxisTracker, and
8080
LocalizedSingleAxisTracker repr methods. (:issue:`1027`)
81+
* Added ability for :py:func:`pvlib.soiling.hsu` to accept arbitrary time intervals. (:pull:`980`)
8182

8283
Bug fixes
8384
~~~~~~~~~
84-
* Fixed unit and default value errors in :py:func:`pvlib.soiling.hsu`. (:pull:`XXX`)
85+
* Fixed unit and default value errors in :py:func:`pvlib.soiling.hsu`. (:pull:`977`, :pull:`980`)
8586
* Handle NUL characters and fix version column dtype in
8687
:py:func:`~pvlib.iotools.crn.read_crn`. (:issue:`1025`)
8788

‎pvlib/soiling.py

Copy file name to clipboardExpand all lines: pvlib/soiling.py
+13-4Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
def hsu(rainfall, cleaning_threshold, tilt, pm2_5, pm10,
1313
depo_veloc=None, rain_accum_period=pd.Timedelta('1h')):
1414
"""
15-
Calculates soiling ratio given particulate and rain data using the model
16-
from Humboldt State University (HSU).
15+
Calculates soiling ratio given particulate and rain data using the
16+
Fixed Velocity model from Humboldt State University (HSU).
1717
1818
The HSU soiling model [1]_ returns the soiling ratio, a value between zero
1919
and one which is equivalent to (1 - transmission loss). Therefore a soiling
@@ -76,8 +76,17 @@ def hsu(rainfall, cleaning_threshold, tilt, pm2_5, pm10,
7676
# cleaning is True for intervals with rainfall greater than threshold
7777
cleaning_times = accum_rain.index[accum_rain >= cleaning_threshold]
7878

79-
horiz_mass_rate = pm2_5 * depo_veloc['2_5']\
80-
+ np.maximum(pm10 - pm2_5, 0.) * depo_veloc['10'] * 3600
79+
# determine the time intervals in seconds (dt_sec)
80+
dt = rainfall.index
81+
# subtract shifted values from original and convert to seconds
82+
dt_diff = (dt[1:] - dt[:-1]).total_seconds()
83+
# ensure same number of elements in the array, assuming that the interval
84+
# prior to the first value is equal in length to the first interval
85+
dt_sec = np.append(dt_diff[0], dt_diff).astype('float64')
86+
87+
horiz_mass_rate = (
88+
pm2_5 * depo_veloc['2_5'] + np.maximum(pm10 - pm2_5, 0.)
89+
* depo_veloc['10']) * dt_sec
8190
tilted_mass_rate = horiz_mass_rate * cosd(tilt) # assuming no rain
8291

8392
# tms -> tilt_mass_rate

‎pvlib/tests/test_soiling.py

Copy file name to clipboardExpand all lines: pvlib/tests/test_soiling.py
+54-20Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,24 @@ def expected_output():
1818
end=pd.Timestamp(2019, 1, 1, 23, 59, 0), freq='1h')
1919

2020
expected_no_cleaning = pd.Series(
21-
data=[0.97230454, 0.95036146, 0.93039061, 0.91177978, 0.89427556,
22-
0.8777455 , 0.86211038, 0.84731759, 0.83332881, 0.82011354,
23-
0.80764549, 0.79590056, 0.78485556, 0.77448749, 0.76477312,
24-
0.75568883, 0.74721046, 0.73931338, 0.73197253, 0.72516253,
25-
0.7188578 , 0.71303268, 0.7076616 , 0.70271919],
21+
data=[0.96998483, 0.94623958, 0.92468139, 0.90465654, 0.88589707,
22+
0.86826366, 0.85167258, 0.83606715, 0.82140458, 0.80764919,
23+
0.79476875, 0.78273241, 0.77150951, 0.76106905, 0.75137932,
24+
0.74240789, 0.73412165, 0.72648695, 0.71946981, 0.7130361,
25+
0.70715176, 0.70178307, 0.69689677, 0.69246034],
2626
index=dt)
2727
return expected_no_cleaning
2828

2929
@pytest.fixture
3030
def expected_output_1():
3131
dt = pd.date_range(start=pd.Timestamp(2019, 1, 1, 0, 0, 0),
32-
end=pd.Timestamp(2019, 1, 1, 23, 59, 0), freq='1h')
32+
end=pd.Timestamp(2019, 1, 1, 23, 59, 0), freq='1h')
3333
expected_output_1 = pd.Series(
34-
data=[0.9872406 , 0.97706269, 0.96769693, 0.95884032, 1.,
35-
0.9872406 , 0.97706269, 0.96769693, 1. , 1. ,
36-
0.9872406 , 0.97706269, 0.96769693, 0.95884032, 0.95036001,
37-
0.94218263, 0.93426236, 0.92656836, 0.91907873, 0.91177728,
38-
0.9046517 , 0.89769238, 0.89089165, 0.88424329],
34+
data=[0.98484972, 0.97277367, 0.96167471, 0.95119603, 1.,
35+
0.98484972, 0.97277367, 0.96167471, 1., 1.,
36+
0.98484972, 0.97277367, 0.96167471, 0.95119603, 0.94118234,
37+
0.93154854, 0.922242, 0.91322759, 0.90448058, 0.89598283,
38+
0.88772062, 0.87968325, 0.8718622, 0.86425049],
3939
index=dt)
4040
return expected_output_1
4141

@@ -44,15 +44,31 @@ def expected_output_2():
4444
dt = pd.date_range(start=pd.Timestamp(2019, 1, 1, 0, 0, 0),
4545
end=pd.Timestamp(2019, 1, 1, 23, 59, 0), freq='1h')
4646
expected_output_2 = pd.Series(
47-
data=[0.97229869, 0.95035106, 0.93037619, 0.91176175, 1.,
48-
1. , 1. , 0.97229869, 1. , 1. ,
49-
1. , 1. , 0.97229869, 0.95035106, 0.93037619,
50-
0.91176175, 0.89425431, 1. , 1. , 1. ,
51-
1. , 0.97229869, 0.95035106, 0.93037619],
47+
data=[0.95036261, 0.91178179, 0.87774818, 0.84732079, 1.,
48+
1., 1., 0.95036261, 1., 1.,
49+
1., 1., 0.95036261, 0.91178179, 0.87774818,
50+
0.84732079, 0.8201171, 1., 1., 1.,
51+
1., 0.95036261, 0.91178179, 0.87774818],
5252
index=dt)
53-
5453
return expected_output_2
5554

55+
56+
@pytest.fixture
57+
def expected_output_3():
58+
dt = pd.date_range(start=pd.Timestamp(2019, 1, 1, 0, 0, 0),
59+
end=pd.Timestamp(2019, 1, 1, 23, 59, 0), freq='1h')
60+
timedelta = [0, 0, 0, 0, 0, 30, 0, 30, 0, 30, 0, -30,
61+
-30, -30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
62+
dt_new = dt + pd.to_timedelta(timedelta, 'm')
63+
expected_output_3 = pd.Series(
64+
data=[0.96576705, 0.9387675, 0.91437615, 0.89186852, 1.,
65+
1., 0.98093819, 0.9387675, 1., 1.,
66+
1., 1., 0.96576705, 0.9387675, 0.90291005,
67+
0.88122293, 0.86104089, 1., 1., 1.,
68+
0.96576705, 0.9387675, 0.91437615, 0.89186852],
69+
index=dt_new)
70+
return expected_output_3
71+
5672
@pytest.fixture
5773
def rainfall_input():
5874

@@ -105,12 +121,30 @@ def test_hsu_defaults(rainfall_input, expected_output_1):
105121
Test Soiling HSU function with default deposition velocity and default rain
106122
accumulation period.
107123
"""
108-
result = hsu(
109-
rainfall=rainfall_input, cleaning_threshold=0.5, tilt=0.0,
110-
pm2_5=1.0e-2,pm10=2.0e-2)
124+
result = hsu(rainfall=rainfall_input, cleaning_threshold=0.5, tilt=0.0,
125+
pm2_5=1.0e-2, pm10=2.0e-2)
111126
assert np.allclose(result.values, expected_output_1)
112127

113128

129+
@requires_scipy
130+
def test_hsu_variable_time_intervals(rainfall_input, expected_output_3):
131+
"""
132+
Test Soiling HSU function with variable time intervals.
133+
"""
134+
depo_veloc = {'2_5': 1.0e-4, '10': 1.0e-4}
135+
rain = pd.DataFrame(data=rainfall_input)
136+
# define time deltas in minutes
137+
timedelta = [0, 0, 0, 0, 0, 30, 0, 30, 0, 30, 0, -30,
138+
-30, -30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
139+
rain['mins_added'] = pd.to_timedelta(timedelta, 'm')
140+
rain['new_time'] = rain.index + rain['mins_added']
141+
rain_var_times = rain.set_index('new_time').iloc[:, 0]
142+
result = hsu(
143+
rainfall=rain_var_times, cleaning_threshold=0.5, tilt=50.0,
144+
pm2_5=1, pm10=2, depo_veloc=depo_veloc,
145+
rain_accum_period=pd.Timedelta('2h'))
146+
assert np.allclose(result, expected_output_3)
147+
114148
@pytest.fixture
115149
def greensboro_rain():
116150
# get TMY3 data with rain

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.