Skip to content

Commit 1f25b2f

Browse files
Wrapper for clearsky filter combining csi and pvlib models (#412)
* add wrapper clearsky_filter * rename filter to model * update analysis_chains with clearsky filter wrapper * update clearsky tests * update default filter params * add pending changelog * update init.py * update api.rst * add test for clearsky_filter function * remove experimental warning for logic_clip_filter test * re-run notebook * update configparser deprecated arguments python 3.12 * Use csi clearsky filter in a number of tests * Adjust how attributes are removed for error testing * fix linting in analysis_chains_test * update numexpr to 2.10 * update h5py requirements to 3.11 * Revert "re-run notebook" This reverts commit 751cfaa. * update notebook requirements * save degradation notebook without logic filter warning * availability notebook avoid double plotting figures * re-run TrendAnalysis notebook * Revert "re-run TrendAnalysis notebook" This reverts commit 3e91ada. * restart kernel and re-run TrendAnalysis notebook * update change log * add line to change log * further changelog fixes --------- Co-authored-by: Michael Deceglie <[email protected]>
1 parent 26bb72d commit 1f25b2f

14 files changed

+4546
-4569
lines changed

docs/TrendAnalysis_example_pvdaq4.ipynb

+28-46
Large diffs are not rendered by default.

docs/degradation_and_soiling_example_pvdaq_4.ipynb

+4,075-4,240
Large diffs are not rendered by default.

docs/notebook_requirements.txt

+10-10
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ decorator==4.3.0
1010
defusedxml==0.7.1
1111
entrypoints==0.2.3
1212
html5lib==1.0.1
13-
ipykernel==4.8.2
14-
ipython==8.10.0
13+
ipykernel==6.29.4
14+
ipython==8.23.0
1515
ipython-genutils==0.2.0
1616
ipywidgets==7.3.0
1717
jedi==0.16.0
1818
Jinja2==3.0.0
1919
jsonschema==2.6.0
2020
jupyter==1.0.0
21-
jupyter-client==6.1.7
22-
jupyter-console==6.4.0
23-
jupyter-core==4.11.2
24-
jupyterlab-pygments==0.2.2
21+
jupyter-client==8.6.1
22+
jupyter-console==6.6.3
23+
jupyter-core==5.7.2
24+
jupyterlab-pygments==0.3.0
2525
lxml==4.9.1
2626
MarkupSafe==2.0.0
2727
mistune==2.0.3
@@ -30,17 +30,17 @@ nbconvert==7.0.0
3030
nbformat==5.1.0
3131
nest-asyncio==1.5.5
3232
notebook==6.4.12
33-
numexpr==2.8.0
33+
numexpr==2.10.0
3434
pandocfilters==1.4.2
3535
parso==0.5.2
3636
pexpect==4.6.0
3737
pickleshare==0.7.5
3838
prometheus-client==0.3.0
39-
prompt-toolkit==3.0.30
39+
prompt-toolkit==3.0.43
4040
ptyprocess==0.6.0
4141
pycparser==2.20
4242
Pygments==2.15.0
43-
pyzmq==22.2.1
43+
pyzmq==26.0.2
4444
qtconsole==4.3.1
4545
Send2Trash==1.8.0
4646
simplegeneric==0.8.1
@@ -49,7 +49,7 @@ terminado==0.8.3
4949
testpath==0.3.1
5050
tinycss2==1.1.1
5151
tornado==6.3.3
52-
traitlets==5.0.0
52+
traitlets==5.14.3
5353
wcwidth==0.1.7
5454
webencodings==0.5.1
5555
widgetsnbextension==3.3.0

docs/sphinx/source/api.rst

+8-6
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ Submodules
99
==========
1010

1111
RdTools is organized into submodules focused on different parts of the data
12-
analysis workflow.
12+
analysis workflow.
1313

1414
.. autosummary::
1515
:toctree: generated/
1616

1717
analysis_chains
1818
degradation
19-
soiling
19+
soiling
2020
availability
2121
filtering
2222
normalization
@@ -42,8 +42,8 @@ Object-oriented end-to-end analysis
4242
analysis_chains.TrendAnalysis.plot_soiling_monte_carlo
4343
analysis_chains.TrendAnalysis.plot_pv_vs_irradiance
4444
analysis_chains.TrendAnalysis.plot_degradation_timeseries
45-
46-
45+
46+
4747
Degradation
4848
===========
4949

@@ -86,7 +86,7 @@ System Availability
8686

8787
.. autosummary::
8888
:toctree: generated/
89-
89+
9090
AvailabilityAnalysis
9191
AvailabilityAnalysis.run
9292
AvailabilityAnalysis.plot
@@ -100,12 +100,14 @@ Filtering
100100

101101
.. autosummary::
102102
:toctree: generated/
103-
103+
104104
clip_filter
105105
quantile_clip_filter
106106
logic_clip_filter
107107
xgboost_clip_filter
108+
clearsky_filter
108109
csi_filter
110+
pvlib_clearsky_filter
109111
poa_filter
110112
tcell_filter
111113
normalized_filter

docs/sphinx/source/changelog.rst

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
RdTools Change Log
22
==================
3+
.. include:: changelog/pending.rst
34
.. include:: changelog/v2.2.0-beta.2.rst
45
.. include:: changelog/v2.2.0-beta.1.rst
56
.. include:: changelog/v2.1.8.rst
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
*******
2+
pending
3+
*******
4+
5+
Breaking changes
6+
------------
7+
These changes have the potential to change answers in existing scripts
8+
when compared with older versions of RdTools
9+
10+
* Use the pvlib method for clear sky detection by default in :py:func:`~rdtools.analysis_chains.TrendAnalysis` (:pull:`412`)
11+
12+
Enhancements
13+
------------
14+
* Added a new wrapper function for clearsky filters (:pull:`412`)
15+
16+
Bug fixes
17+
---------
18+
* tbd
19+
20+
Requirements
21+
------------
22+
* Specified versions in ``requirements.txt`` and ``docs/notebook_requirements.txt`` have been updated (:pull:`412`)
23+
24+
Contributors
25+
------------
26+
* Martin Springer (:ghuser:`martin-springer`)
27+
* Michael Deceglie (:ghuser:`mdeceglie`)

docs/system_availability_example.ipynb

+24-19
Large diffs are not rendered by default.

rdtools/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
from rdtools.degradation import degradation_year_on_year
1010
from rdtools.aggregation import aggregation_insol
1111
from rdtools.clearsky_temperature import get_clearsky_tamb
12+
from rdtools.filtering import clearsky_filter
1213
from rdtools.filtering import csi_filter
14+
from rdtools.filtering import pvlib_clearsky_filter
1315
from rdtools.filtering import poa_filter
1416
from rdtools.filtering import tcell_filter
1517
from rdtools.filtering import clip_filter

rdtools/analysis_chains.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def __init__(
153153
"poa_filter": {},
154154
"tcell_filter": {},
155155
"clip_filter": {},
156-
"pvlib_clearsky_filter": {},
156+
"clearsky_filter": {},
157157
"ad_hoc_filter": None, # use this to include an explict filter
158158
}
159159
self.filter_params_aggregated = {"ad_hoc_filter": None}
@@ -461,7 +461,7 @@ def _call_clearsky_filter(filter_string):
461461
"Both poa_global and poa_global_clearsky must be available to "
462462
f"do clearsky filtering with {filter_string}"
463463
)
464-
f = filtering.pvlib_clearsky_filter(
464+
f = filtering.clearsky_filter(
465465
self.poa_global,
466466
self.poa_global_clearsky,
467467
**self.filter_params[filter_string],
@@ -529,12 +529,12 @@ def _call_clearsky_filter(filter_string):
529529
filter_components["hour_angle_filter"] = f
530530

531531
if case == "clearsky":
532-
filter_components["pvlib_clearsky_filter"] = _call_clearsky_filter(
533-
"pvlib_clearsky_filter"
532+
filter_components["clearsky_filter"] = _call_clearsky_filter(
533+
"clearsky_filter"
534534
)
535-
if "sensor_pvlib_clearsky_filter" in self.filter_params:
536-
filter_components["sensor_pvlib_clearsky_filter"] = _call_clearsky_filter(
537-
"sensor_pvlib_clearsky_filter"
535+
if "sensor_clearsky_filter" in self.filter_params:
536+
filter_components["sensor_clearsky_filter"] = _call_clearsky_filter(
537+
"sensor_clearsky_filter"
538538
)
539539

540540
# note: the previous implementation using the & operator treated NaN
@@ -803,14 +803,14 @@ def _sensor_preprocess(self):
803803
"poa_global must be available to perform _sensor_preprocess"
804804
)
805805

806-
if "sensor_pvlib_clearsky_filter" in self.filter_params:
806+
if "sensor_clearsky_filter" in self.filter_params:
807807
try:
808808
if self.poa_global_clearsky is None:
809809
self._calc_clearsky_poa(model="isotropic")
810810
except AttributeError:
811811
raise AttributeError(
812812
"No poa_global_clearsky. 'set_clearsky' must be run "
813-
+ "to allow filter_params['sensor_pvlib_clearsky_filter']. "
813+
+ "to allow filter_params['sensor_clearsky_filter']. "
814814
)
815815
if self.power_expected is None:
816816
# Thermal details required if power_expected is not manually set.

rdtools/filtering.py

+37
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,43 @@ def tcell_filter(temperature_cell, temperature_cell_low=-50, temperature_cell_hi
103103
)
104104

105105

106+
def clearsky_filter(poa_global_measured, poa_global_clearsky, model='pvlib', **kwargs):
107+
"""
108+
Wrapper function for running either the CSI or pvlib clearsky filter.
109+
110+
Parameters
111+
----------
112+
poa_global_measured : pandas.Series
113+
Plane of array irradiance based on measurments
114+
poa_global_clearsky : pandas.Series
115+
Plane of array irradiance based on a clear sky model
116+
model : str, default 'pvlib'
117+
Clearsky filter model to be applied. Can be 'pvlib' or 'csi'.
118+
kwargs :
119+
Additional clearsky filter args, specific to the filter being
120+
used. Keyword must be passed with value.
121+
122+
Returns
123+
-------
124+
pandas.Series
125+
Boolean Series of whether or not the given time is clear
126+
based on the selected filter.
127+
128+
See Also
129+
--------
130+
csi_filter : Filtering based on clear-sky index (csi).
131+
pvlib_clearsky_filter : Filtering based on pvlib's clearsky model.
132+
"""
133+
134+
if model == "csi":
135+
clearsky_mask = csi_filter(poa_global_measured, poa_global_clearsky, **kwargs)
136+
elif model == "pvlib":
137+
clearsky_mask = pvlib_clearsky_filter(poa_global_measured, poa_global_clearsky, **kwargs)
138+
else:
139+
raise ValueError("Clearsky filter must be 'pvlib' or 'csi'.")
140+
return clearsky_mask
141+
142+
106143
def csi_filter(poa_global_measured, poa_global_clearsky, threshold=0.15):
107144
"""
108145
Filtering based on clear-sky index (csi)

0 commit comments

Comments
 (0)