Skip to content
8 changes: 4 additions & 4 deletions docs/degradation_and_soiling_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,14 @@
"source": [
"# Calculate a collection of boolean masks that can be used\n",
"# to filter the time series\n",
"nz_mask = (df['normalized'] > 0.01)\n",
"normalized_mask = rdtools.normalized_filter(df['normalized'])\n",
"poa_mask = rdtools.poa_filter(df['poa'])\n",
"tcell_mask = rdtools.tcell_filter(df['Tcell'])\n",
"clip_mask = rdtools.clip_filter(df['power'])\n",
"\n",
"# filter the time series and keep only the columns needed for the\n",
"# remaining steps\n",
"filtered = df[nz_mask & poa_mask & tcell_mask & clip_mask]\n",
"filtered = df[normalized_mask & poa_mask & tcell_mask & clip_mask]\n",
"filtered = filtered[['insolation', 'normalized']]\n",
"\n",
"fig, ax = plt.subplots()\n",
Expand Down Expand Up @@ -709,14 +709,14 @@
"outputs": [],
"source": [
"# Perform clearsky filter\n",
"cs_nz_mask = (df['clearsky_normalized'] > 0.01)\n",
"cs_normalized_mask = rdtools.normalized_filter(df['clearsky_normalized'])\n",
"cs_poa_mask = rdtools.poa_filter(df['clearsky_poa'])\n",
"cs_tcell_mask = rdtools.tcell_filter(df['clearsky_Tcell'])\n",
"\n",
"csi_mask = rdtools.csi_filter(df.insolation, df.clearsky_insolation)\n",
"\n",
"\n",
"clearsky_filtered = df[cs_nz_mask & cs_poa_mask & cs_tcell_mask & clip_mask & csi_mask]\n",
"clearsky_filtered = df[cs_normalized_mask & cs_poa_mask & cs_tcell_mask & clip_mask & csi_mask]\n",
"clearsky_filtered = clearsky_filtered[['clearsky_insolation', 'clearsky_normalized']]"
]
},
Expand Down
1 change: 1 addition & 0 deletions docs/sphinx/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Functions to perform filtering on PV system data.
filtering.csi_filter
filtering.poa_filter
filtering.tcell_filter
filtering.normalized_filter


Normalization
Expand Down
4 changes: 4 additions & 0 deletions docs/sphinx/source/changelog/v2.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Enhancements
recovery method (:pull:`112`).
* Add new functions :py:func:`~rdtools.normalization.energy_from_power` and
:py:func:`~rdtools.normalization.interpolate`.
* Add new function :py:func:`~rdtools.filtering.normalized_filter`.
* Add new :py:mod:`~rdtools.plotting` module for generating standard plots.
* Add parameter ``convergence_threshold`` to
:py:func:`~rdtools.normalization.irradiance_rescale` (:pull:`152`).
Expand Down Expand Up @@ -41,6 +42,9 @@ Requirements
Example Updates
---------------
* Seed ``numpy.random`` to ensure repeatable results (:pull:`164`).
* Use :py:func:`~rdtools.filtering.normalized_filter` instead of manually
filtering the normalized energy timeseries. Also updated the associated mask
variable names (:pull:`139`).

Contributors
------------
1 change: 1 addition & 0 deletions rdtools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from rdtools.filtering import poa_filter
from rdtools.filtering import tcell_filter
from rdtools.filtering import clip_filter
from rdtools.filtering import normalized_filter
from rdtools.soiling import soiling_srr
from rdtools.plotting import degradation_summary_plots
from rdtools.plotting import soiling_monte_carlo_plot
Expand Down
30 changes: 30 additions & 0 deletions rdtools/filtering.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
'''Functions for filtering and subsetting PV system data.'''

import numpy as np


def normalized_filter(normalized, low_cutoff=0.01, high_cutoff=None):
'''
Select normalized yield between ``low_cutoff`` and ``high_cutoff``

Parameters
----------
normalized : pd.Series
Normalized power measurements.
low_cutoff : float, default 0.01
The lower bound of acceptable values.
high_cutoff : float, optional
The upper bound of acceptable values.

Returns
-------
pd.Series
Boolean Series of whether the given measurement is within acceptable
bounds.
'''

if low_cutoff is None:
low_cutoff = -np.inf
if high_cutoff is None:
high_cutoff = np.inf

return (normalized > low_cutoff) & (normalized < high_cutoff)


def poa_filter(poa, low_irradiance_cutoff=200, high_irradiance_cutoff=1200):
'''
Expand Down
15 changes: 14 additions & 1 deletion rdtools/test/filtering_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pandas as pd
import numpy as np

from rdtools import csi_filter, poa_filter, tcell_filter, clip_filter
from rdtools import csi_filter, poa_filter, tcell_filter, clip_filter, normalized_filter


class CSIFilterTestCase(unittest.TestCase):
Expand Down Expand Up @@ -73,5 +73,18 @@ def test_clip_filter_upper(self):
self.assertTrue((expected_result == filtered).all())


def test_normalized_filter_default():
pd.testing.assert_series_equal(normalized_filter(pd.Series([-5, 5])),
pd.Series([False, True]))

pd.testing.assert_series_equal(normalized_filter(pd.Series([-1e6, 1e6]), low_cutoff=None, high_cutoff=None),
pd.Series([True, True]))

pd.testing.assert_series_equal(normalized_filter(pd.Series([-2, 2]), low_cutoff=-1, high_cutoff=1),
pd.Series([False, False]))

pd.testing.assert_series_equal(normalized_filter(pd.Series([0.01 - 1e-16, 0.01 + 1e-16, 1e308])),
pd.Series([False, True, True]))

if __name__ == '__main__':
unittest.main()