Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
569177f
Merge pull request #448 from NREL/development
mdeceglie Jan 23, 2025
916fedd
Bump notebook from 7.2.1 to 7.2.2 in /docs
dependabot[bot] Jan 23, 2025
0c6cae8
Merge pull request #451 from NREL/dependabot/pip/docs/notebook-7.2.2
mdeceglie Jan 23, 2025
3e4be19
Bump tornado from 6.4.2 to 6.5.1 in /docs
dependabot[bot] May 23, 2025
7c312ad
add keyword 'label' to degradation_timeseries_plot, enabling 'left' a…
cdeline May 28, 2025
d6a898e
Update changelog, add pytests, update sphinx documentation
cdeline May 28, 2025
df2effc
fix flake8 grumbles
cdeline May 28, 2025
3099497
update pytests to include axes limits
cdeline Jun 18, 2025
1d140e6
fix flake8 grumbles
cdeline Jun 18, 2025
424fc7d
statsmodels 0.14.4 is not able to handle the latest scipy.
cdeline Jun 23, 2025
650c4ce
Merge pull request #461 from cdeline/scipy1.16
mdeceglie Jun 24, 2025
ea8854e
Bump jinja2 from 3.1.5 to 3.1.6 in /docs
dependabot[bot] Jun 24, 2025
f4b77bb
Bump requests from 2.32.3 to 2.32.4
dependabot[bot] Jun 24, 2025
e2c387a
Bump urllib3 from 2.2.2 to 2.5.0
dependabot[bot] Jun 24, 2025
125a5ff
Merge remote-tracking branch 'remotes/origin/master' into 455_degrada…
cdeline Jun 25, 2025
03e094e
try setup.py now that statsmodels has a new release.
cdeline Jul 7, 2025
a6c7355
Merge pull request #462 from NREL/dependabot/pip/docs/jinja2-3.1.6
mdeceglie Aug 21, 2025
92270aa
Merge pull request #463 from cdeline/statsmodels_test
mdeceglie Aug 21, 2025
d665d38
Merge pull request #458 from NREL/dependabot/pip/urllib3-2.5.0
mdeceglie Aug 21, 2025
a0783bb
Merge pull request #457 from NREL/dependabot/pip/requests-2.32.4
mdeceglie Aug 21, 2025
ac25a59
Merge pull request #454 from NREL/dependabot/pip/docs/tornado-6.5.1
mdeceglie Aug 21, 2025
3c43bdb
Update changelog
mdeceglie Aug 21, 2025
e38e7b9
Merge branch '3.0.1_candidate' of https://github.com/NREL/rdtools int…
mdeceglie Aug 21, 2025
8060f31
Update release date
mdeceglie Aug 21, 2025
076ebff
Merge pull request #465 from NREL/3.0.1_candidate
mdeceglie Aug 21, 2025
0f53385
Merge branch 'master' into 455_degradation_timeseries
cdeline Aug 26, 2025
8451499
update plotting tests to be relative value, update ordering of module…
cdeline Sep 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/notebook_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ ipython==8.26.0
ipython-genutils==0.2.0
ipywidgets==8.1.3
jedi==0.19.1
Jinja2==3.1.5
Jinja2==3.1.6
jsonschema==4.23.0
jupyter==1.0.0
jupyter-client==8.6.2
Expand All @@ -29,7 +29,7 @@ nbclient==0.10.0
nbconvert==7.16.4
nbformat==5.10.4
nest-asyncio==1.6.0
notebook==7.2.1
notebook==7.2.2
numexpr==2.10.1
pandocfilters==1.5.1
parso==0.8.4
Expand All @@ -48,7 +48,7 @@ soupsieve==2.6
terminado==0.18.1
testpath==0.6.0
tinycss2==1.3.0
tornado==6.4.2
tornado==6.5.1
traitlets==5.14.3
wcwidth==0.2.13
webencodings==0.5.1
Expand Down
2 changes: 2 additions & 0 deletions docs/sphinx/source/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
RdTools Change Log
==================
.. include:: changelog/pending.rst
.. include:: changelog/v3.0.1.rst
.. include:: changelog/v3.0.0.rst
.. include:: changelog/v2.1.8.rst
.. include:: changelog/v2.1.7.rst
Expand Down
16 changes: 16 additions & 0 deletions docs/sphinx/source/changelog/pending.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
*************************
v3.0.x (X, X, 2025)
*************************

Enhancements
------------
* :py:func:`~rdtools.plotting.degradation_timeseries_plot` has new parameter ``label=``
to allow the timeseries plot to have right labeling (default), center or left labeling.
(:issue:`455`)



Contributors
------------
* Chris Deline (:ghuser:`cdeline`)

11 changes: 11 additions & 0 deletions docs/sphinx/source/changelog/v3.0.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*************************
v3.0.1 (August 21, 2025)
*************************

Requirements
------------
* Updated Jinja2==3.1.6 in ``notebook_requirements.txt`` (:pull:`465`)
* Updated tornado==6.5.1 in ``notebook_requirements.txt`` (:pull:`465`)
* Updated requests==2.32.4 in ``requirements.txt`` (:pull:`465`)
* Updated urllib3==2.5.0 in ``requirements.txt`` (:pull:`465`)
* Removed constraint that scipy<1.16.0 (:pull:`465`)
34 changes: 29 additions & 5 deletions rdtools/plotting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import plotly.express as px
import numpy as np
import warnings
import datetime


def degradation_summary_plots(yoy_rd, yoy_ci, yoy_info, normalized_yield,
Expand Down Expand Up @@ -431,7 +432,7 @@ def availability_summary_plots(power_system, power_subsystem, loss_total,
return fig


def degradation_timeseries_plot(yoy_info, rolling_days=365, include_ci=True,
def degradation_timeseries_plot(yoy_info, rolling_days=365, include_ci=True, label='right',
fig=None, plot_color=None, ci_color=None, **kwargs):
'''
Plot resampled time series of degradation trend with time
Expand All @@ -447,6 +448,13 @@ def degradation_timeseries_plot(yoy_info, rolling_days=365, include_ci=True,
at least 50% of datapoints to be included in rolling plot.
include_ci : bool, default True
calculate and plot 2-sigma confidence intervals along with rolling median
label : {'right', 'left', 'center'}, default 'right'
A combination of 1) which Year-on-Year slope edge to label,
and 2) which rolling median edge to label.

* ``right`` : label right edge of YoY slope and right edge of rolling median interval.
* ``center``: label center of YoY slope interval and center of rolling median interval.
* ``left`` : label left edge of YoY slope and center of rolling median interval.
fig : matplotlib, optional
fig object to add new plot to (first set of axes only)
plot_color : str, optional
Expand Down Expand Up @@ -475,7 +483,6 @@ def _bootstrap(x, percentile, reps):

try:
results_values = yoy_info['YoY_values']

except KeyError:
raise KeyError("yoy_info input dictionary does not contain key `YoY_values`.")

Expand All @@ -484,7 +491,22 @@ def _bootstrap(x, percentile, reps):
if ci_color is None:
ci_color = 'C0'

roller = results_values.rolling(f'{rolling_days}d', min_periods=rolling_days//2)
if label not in {None, "left", "right", "center"}:
raise ValueError(f"Unsupported value {label} for `label`")
if label is None:
label = "right"

if label == "right":
center = False
offset_days = 0
elif label == "center":
center = True
offset_days = 182
elif label == "left":
center = True
offset_days = 365

roller = results_values.rolling(f'{rolling_days}d', min_periods=rolling_days//2, center=center)
# unfortunately it seems that you can't return multiple values in the rolling.apply() kernel.
# TODO: figure out some workaround to return both percentiles in a single pass
if include_ci:
Expand All @@ -495,8 +517,10 @@ def _bootstrap(x, percentile, reps):
else:
ax = fig.axes[0]
if include_ci:
ax.fill_between(ci_lower.index, ci_lower, ci_upper, color=ci_color)
ax.plot(roller.median(), color=plot_color, **kwargs)
ax.fill_between(ci_lower.index - datetime.timedelta(days=offset_days),
ci_lower, ci_upper, color=ci_color)
ax.plot(roller.median().index - datetime.timedelta(days=offset_days),
roller.median(), color=plot_color, **kwargs)
ax.axhline(results_values.median(), c='k', ls='--')
plt.ylabel('Degradation trend (%/yr)')
fig.autofmt_xdate()
Expand Down
48 changes: 45 additions & 3 deletions rdtools/test/plotting_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,49 @@ def test_availability_summary_plots_empty(availability_analysis_object):
def test_degradation_timeseries_plot(degradation_info):
power, yoy_rd, yoy_ci, yoy_info = degradation_info

# test defaults
result = degradation_timeseries_plot(yoy_info)
assert_isinstance(result, plt.Figure)
# test defaults (label='right')
result_right = degradation_timeseries_plot(yoy_info)
assert_isinstance(result_right, plt.Figure)
xlim_right = result_right.get_axes()[0].get_xlim()[0]

# test label='center'
result_center = degradation_timeseries_plot(yoy_info=yoy_info, include_ci=False,
label='center', fig=result_right)
assert_isinstance(result_center, plt.Figure)
xlim_center = result_center.get_axes()[0].get_xlim()[0]

# test label='left'
result_left = degradation_timeseries_plot(yoy_info=yoy_info, include_ci=False, label='left')
assert_isinstance(result_left, plt.Figure)
xlim_left = result_left.get_axes()[0].get_xlim()[0]

# test label=None (should default to 'right')
result_none = degradation_timeseries_plot(yoy_info=yoy_info, include_ci=False, label=None)
assert_isinstance(result_none, plt.Figure)
xlim_none = result_none.get_axes()[0].get_xlim()[0]

# Check that the xlim values are offset as expected
# right > center > left (since offset_days increases)
assert xlim_right > xlim_center > xlim_left
assert xlim_right == xlim_none # label=None defaults to 'right'

# The expected difference from right to left is 548 days (1.5 yrs), allow 5% tolerance
expected_diff = 548
actual_diff = (xlim_right - xlim_left)
tolerance = expected_diff * 0.05
assert abs(actual_diff - expected_diff) <= tolerance, \
f"difference of right-left xlim {actual_diff} not within 5% of 1.5 yrs."

# The expected difference from right to center is 365 days, allow 5% tolerance
expected_diff2 = 365
actual_diff2 = (xlim_right - xlim_center)
tolerance2 = expected_diff2 * 0.05
assert abs(actual_diff2 - expected_diff2) <= tolerance2, \
f"difference of right-center xlim {actual_diff2} not within 5% of 1 yr."

with pytest.raises(KeyError):
degradation_timeseries_plot({'a': 1}, include_ci=False)
with pytest.raises(ValueError):
degradation_timeseries_plot(yoy_info, include_ci=False, label='CENTER')

plt.close('all')
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ python-dateutil==2.9.0
pytz==2024.1
arch==7.0.0
filterpy==1.4.5
requests==2.32.3
requests==2.32.4
retrying==1.3.4
scikit-learn==1.5.1
scipy==1.13.1
Expand All @@ -30,6 +30,6 @@ statsmodels==0.14.2
threadpoolctl==3.5.0
tomli==2.0.1
typing_extensions==4.12.2
urllib3==2.2.2
urllib3==2.5.0
xgboost==2.1.1

Loading