Skip to content
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

Fix/issue 205 #207

Merged
merged 16 commits into from
Oct 8, 2020
59 changes: 33 additions & 26 deletions docs/degradation_and_soiling_example.ipynb

Large diffs are not rendered by default.

116 changes: 43 additions & 73 deletions docs/degradation_and_soiling_example_pvdaq_4.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -616,37 +616,6 @@
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0 2010-02-25 00:00:00-07:00\n",
"1 2010-03-08 00:00:00-07:00\n",
"2 2010-03-12 00:00:00-07:00\n",
"3 2010-04-09 00:00:00-07:00\n",
"4 2010-04-12 00:00:00-07:00\n",
" ... \n",
"59 2016-04-10 00:00:00-07:00\n",
"60 2016-04-16 00:00:00-07:00\n",
"61 2016-05-04 00:00:00-07:00\n",
"62 2016-07-13 00:00:00-07:00\n",
"63 2016-12-06 00:00:00-07:00\n",
"Name: start, Length: 64, dtype: datetime64[ns, Etc/GMT+7]"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"soiling_summary['start']"
mdeceglie marked this conversation as resolved.
Show resolved Hide resolved
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
Expand All @@ -673,7 +642,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 18,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -835,7 +804,7 @@
"11 6 "
]
},
"execution_count": 19,
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
Expand All @@ -848,7 +817,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 19,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -882,81 +851,82 @@
" <tr>\n",
" <th>0</th>\n",
" <td>2010</td>\n",
" <td>0.975022</td>\n",
" <td>0.934111</td>\n",
" <td>0.992382</td>\n",
" <td>0.963661</td>\n",
" <td>0.951828</td>\n",
" <td>0.971463</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>2011</td>\n",
" <td>0.958594</td>\n",
" <td>0.872132</td>\n",
" <td>0.984363</td>\n",
" <td>0.944819</td>\n",
" <td>0.936342</td>\n",
" <td>0.950665</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>2012</td>\n",
" <td>0.945495</td>\n",
" <td>0.867414</td>\n",
" <td>0.989819</td>\n",
" <td>0.939456</td>\n",
" <td>0.931768</td>\n",
" <td>0.945988</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>2013</td>\n",
" <td>0.957287</td>\n",
" <td>0.906841</td>\n",
" <td>0.987823</td>\n",
" <td>0.954258</td>\n",
" <td>0.944068</td>\n",
" <td>0.961534</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>2014</td>\n",
" <td>0.959787</td>\n",
" <td>0.902334</td>\n",
" <td>0.991943</td>\n",
" <td>0.950645</td>\n",
" <td>0.929716</td>\n",
" <td>0.966537</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>2015</td>\n",
" <td>0.959014</td>\n",
" <td>0.899179</td>\n",
" <td>0.985713</td>\n",
" <td>0.951059</td>\n",
" <td>0.921407</td>\n",
" <td>0.966395</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>2016</td>\n",
" <td>0.964605</td>\n",
" <td>0.842394</td>\n",
" <td>0.987011</td>\n",
" <td>0.937259</td>\n",
" <td>0.925394</td>\n",
" <td>0.944943</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" year soiling_ratio_median soiling_ratio_low soiling_ratio_high\n",
"0 2010 0.975022 0.934111 0.992382\n",
"1 2011 0.958594 0.872132 0.984363\n",
"2 2012 0.945495 0.867414 0.989819\n",
"3 2013 0.957287 0.906841 0.987823\n",
"4 2014 0.959787 0.902334 0.991943\n",
"5 2015 0.959014 0.899179 0.985713\n",
"6 2016 0.964605 0.842394 0.987011"
"0 2010 0.963661 0.951828 0.971463\n",
"1 2011 0.944819 0.936342 0.950665\n",
"2 2012 0.939456 0.931768 0.945988\n",
"3 2013 0.954258 0.944068 0.961534\n",
"4 2014 0.950645 0.929716 0.966537\n",
"5 2015 0.951059 0.921407 0.966395\n",
"6 2016 0.937259 0.925394 0.944943"
]
},
"execution_count": 20,
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Calculate and view annual soiling ratios and their confidence intervals\n",
"# based on the Monte Carlo simulation. Note that these losses include the\n",
"# Calculate and view annual insolation-weighted soiling ratios and their confidence\n",
"# intervals based on the Monte Carlo simulation. Note that these losses include the\n",
"# assumptions of the cleaning assumptions associated with the method parameter\n",
"# of rdtools.soiling_srr(). For anything but 'perfect_clean', each year's soiling\n",
"# ratio may be impacted by prior years' soiling profiles. The default behavior of\n",
"# rdtools.soiling_srr uses method='half_norm_clean'\n",
"\n",
"rdtools.annual_soiling_ratios(soiling_info['stochastic_soiling_profiles'],\n",
" daily_insolation,\n",
" confidence_level=cl)"
]
},
Expand Down Expand Up @@ -985,7 +955,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -1018,7 +988,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -1049,7 +1019,7 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -1075,7 +1045,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -1093,7 +1063,7 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": 24,
"metadata": {},
"outputs": [
{
Expand Down Expand Up @@ -1140,7 +1110,7 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 25,
"metadata": {},
"outputs": [
{
Expand All @@ -1150,7 +1120,7 @@
"<Figure size 720x216 with 2 Axes>"
]
},
"execution_count": 26,
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
Expand Down Expand Up @@ -1178,7 +1148,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
"version": "3.7.9"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion docs/sphinx/source/changelog/pending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Enhancements
------------

* Add new function :py:func:`~rdtools.soiling.monthly_soiling_rates` (:pull:`193`).
* Add new function :py:func:`~rdtools.annual_soiling_ratios` (:pull:`193`).
* Add new function :py:func:`~rdtools.annual_soiling_ratios` (:pull:`193`, :pull:`207`).
* Create new module :py:mod:`~rdtools.availability` and class
:py:class:`~rdtools.availability.AvailabilityAanlysis` for estimating
timeseries system availability (:pull:`131`)
Expand Down
37 changes: 28 additions & 9 deletions rdtools/soiling.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'''Functions for calculating soiling metrics from photovoltaic system data.'''

import warnings
import pandas as pd
import numpy as np
from scipy.stats.mstats import theilslopes
Expand Down Expand Up @@ -273,7 +274,7 @@ def _calc_result_df(self, trim=False, max_relative_slope_error=500.0,
results.next_inferred_start_loss - results.inferred_end_loss,
0, 1)

# Don't consider data outside of first and last valid interverals
# Don't consider data outside of first and last valid intervals
if len(results[results.valid]) == 0:
raise NoValidIntervalError('No valid soiling intervals were found')
new_start = results[results.valid].start.iloc[0]
Expand Down Expand Up @@ -443,7 +444,7 @@ def _calc_monte(self, monte, method='half_norm_clean'):

df_rand['soil_insol'] = df_rand.loss * df_rand.insol

monte_losses.append(df_rand.soil_insol.sum() / df_rand.insol.sum())
monte_losses.append(df_rand.soil_insol.sum() / df_rand.insol[~df_rand.soil_insol.isnull()].sum())
random_profile = df_rand['loss'].copy()
random_profile.name = 'stochastic_soiling_profile'
random_profiles.append(random_profile)
Expand Down Expand Up @@ -778,7 +779,7 @@ def _count_month_days(start, end):
return out_dict


def annual_soiling_ratios(stochastic_soiling_profiles, confidence_level=68.2):
def annual_soiling_ratios(stochastic_soiling_profiles, insolation_daily, confidence_level=68.2):
'''
Return annualized soiling ratios and associated confidence intervals based
on stochastic soiling profiles from SRR. Note that each year may be affected
Expand All @@ -791,7 +792,8 @@ def annual_soiling_ratios(stochastic_soiling_profiles, confidence_level=68.2):
List of pd.Series representing profile realizations from the SRR monte carlo.
Typically ``soiling_interval_summary['stochastic_soiling_profiles']`` obtained with
:py:func:`rdtools.soiling.soiling_srr` or :py:meth:`rdtools.soiling.SRRAnalysis.run`

insolation_daily : pd.Series
Daily plane-of-array insolation with DatetimeIndex. Arbitrary units.
confidence_level : float, default 68.2
The size of the confidence interval to use in determining the upper and lower
quantiles reported in the returned DataFrame. (The median is always included in
Expand Down Expand Up @@ -820,12 +822,29 @@ def annual_soiling_ratios(stochastic_soiling_profiles, confidence_level=68.2):
+------------------------+-------------------------------------------+
'''

all_profiles = pd.concat(stochastic_soiling_profiles)
annual_groups = all_profiles.groupby(all_profiles.index.year)
# Create a df with each realization as a column
all_profiles = pd.concat(stochastic_soiling_profiles, axis=1)
all_profiles = all_profiles.dropna()

if not all_profiles.index.isin(insolation_daily.index).all():
warnings.warn('The indexes of stochastic_soiling_profiles are not entirely contained '
'within the index of insolation_daily. Every day in stochastic_soiling_profiles '
'should be represented in insolation_daily. This may cause erroneous results.')

insolation_daily = insolation_daily.reindex(all_profiles.index)

# Weight each day by insolation
all_profiles_weighted = all_profiles.multiply(insolation_daily, axis=0)

# Compute the insolation-weighted soiling ratio (IWSR) for each realization
annual_insolation = insolation_daily.groupby(insolation_daily.index.year).sum()
mdeceglie marked this conversation as resolved.
Show resolved Hide resolved
all_annual_weighted_sums = all_profiles_weighted.groupby(all_profiles_weighted.index.year).sum()
all_annual_iwsr = all_annual_weighted_sums.multiply(1/annual_insolation, axis=0)

annual_soiling = pd.DataFrame({
'soiling_ratio_median': annual_groups.quantile(0.5),
'soiling_ratio_low': annual_groups.quantile(0.5 - confidence_level/2/100),
'soiling_ratio_high': annual_groups.quantile(0.5 + confidence_level/2/100),
'soiling_ratio_median': all_annual_iwsr.quantile(0.5, axis=1),
'soiling_ratio_low': all_annual_iwsr.quantile(0.5 - confidence_level/2/100, axis=1),
'soiling_ratio_high': all_annual_iwsr.quantile(0.5 + confidence_level/2/100, axis=1),
})
annual_soiling.index.name = 'year'
annual_soiling = annual_soiling.reset_index()
Expand Down
Loading