Skip to content

Commit ed3b018

Browse files
cwhansewholmgren
authored andcommitted
Correct condition 5 in detect_clearksy (#596)
* Fixed inconsistencies between the detect_clearsky function and the original reference. * Minor cleanup. * Revert samples_per_interval change, rename to clarify * Style fixes * Style fixes * whatsnew * Variable name edits, delete extinct commented code lines * Document change to API of detect_clearsky
1 parent 4538bef commit ed3b018

File tree

2 files changed

+31
-18
lines changed

2 files changed

+31
-18
lines changed

docs/sphinx/source/whatsnew/v0.6.1.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ API Changes
1818
and :py:func:`pvlib.iotools.read_tmy3` instead. (:issue:`261`)
1919
* Added keyword argument ``horizon`` to :func:`~pvlib.solarposition.pyephem`
2020
and :func:`~pvlib.solarposition.calc_time` with default value ``'+0:00'``
21+
* Changed key names for `components` returned from :py:func:`pvlib.clearsky.detect_clearsky`
2122

2223

2324
Enhancements
@@ -35,6 +36,7 @@ Bug fixes
3536
~~~~~~~~~
3637
* Fix when building documentation using Matplotlib 3.0 or greater.
3738
* Fix and improve :func:`~pvlib.solarposition.hour_angle` (:issue:`598`)
39+
* Fix error in :func:`pvlib.clearsky.detect_clearsky` (:issue:`506`)
3840

3941

4042
Testing
@@ -45,6 +47,7 @@ Testing
4547
Contributors
4648
~~~~~~~~~~~~
4749
* Will Holmgren (:ghuser:`wholmgren`)
48-
* Cliff Hansen (:ghuser:`cwhanse`)
4950
* Leland Boeman (:ghuser:`lboeman`)
51+
* Ben Ellis (:ghuser:`bhellis725`)
52+
* Cliff Hansen (:ghuser:`cwhanse`)
5053
* Mark Mikofski (:ghuser:`mikofski`)

pvlib/clearsky.py

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -680,36 +680,37 @@ def detect_clearsky(measured, clearsky, times, window_length,
680680
raise NotImplementedError('algorithm does not yet support unequal '
681681
'times. consider resampling your data.')
682682

683-
samples_per_window = int(window_length / sample_interval)
683+
intervals_per_window = int(window_length / sample_interval)
684684

685685
# generate matrix of integers for creating windows with indexing
686686
from scipy.linalg import hankel
687-
H = hankel(np.arange(samples_per_window), # noqa: N806
688-
np.arange(samples_per_window-1, len(times)))
687+
H = hankel(np.arange(intervals_per_window), # noqa: N806
688+
np.arange(intervals_per_window - 1, len(times)))
689689

690690
# calculate measurement statistics
691691
meas_mean = np.mean(measured[H], axis=0)
692692
meas_max = np.max(measured[H], axis=0)
693-
meas_slope = np.diff(measured[H], n=1, axis=0)
693+
meas_diff = np.diff(measured[H], n=1, axis=0)
694+
meas_slope = np.diff(measured[H], n=1, axis=0) / sample_interval
694695
# matlab std function normalizes by N-1, so set ddof=1 here
695696
meas_slope_nstd = np.std(meas_slope, axis=0, ddof=1) / meas_mean
696-
meas_slope_max = np.max(np.abs(meas_slope), axis=0)
697697
meas_line_length = np.sum(np.sqrt(
698-
meas_slope*meas_slope + sample_interval*sample_interval), axis=0)
698+
meas_diff * meas_diff +
699+
sample_interval * sample_interval), axis=0)
699700

700701
# calculate clear sky statistics
701702
clear_mean = np.mean(clearsky[H], axis=0)
702703
clear_max = np.max(clearsky[H], axis=0)
703-
clear_slope = np.diff(clearsky[H], n=1, axis=0)
704-
clear_slope_max = np.max(np.abs(clear_slope), axis=0)
704+
clear_diff = np.diff(clearsky[H], n=1, axis=0)
705+
clear_slope = np.diff(clearsky[H], n=1, axis=0) / sample_interval
705706

706707
from scipy.optimize import minimize_scalar
707708

708709
alpha = 1
709710
for iteration in range(max_iterations):
710711
clear_line_length = np.sum(np.sqrt(
711-
alpha*alpha*clear_slope*clear_slope +
712-
sample_interval*sample_interval), axis=0)
712+
alpha * alpha * clear_diff * clear_diff +
713+
sample_interval * sample_interval), axis=0)
713714

714715
line_diff = meas_line_length - clear_line_length
715716

@@ -718,7 +719,8 @@ def detect_clearsky(measured, clearsky, times, window_length,
718719
c2 = np.abs(meas_max - alpha*clear_max) < max_diff
719720
c3 = (line_diff > lower_line_length) & (line_diff < upper_line_length)
720721
c4 = meas_slope_nstd < var_diff
721-
c5 = (meas_slope_max - alpha*clear_slope_max) < slope_dev
722+
c5 = np.max(np.abs(meas_slope -
723+
alpha * clear_slope), axis=0) < slope_dev
722724
c6 = (clear_mean != 0) & ~np.isnan(clear_mean)
723725
clear_windows = c1 & c2 & c3 & c4 & c5 & c6
724726

@@ -749,13 +751,21 @@ def rmse(alpha):
749751

750752
if return_components:
751753
components = OrderedDict()
752-
components['mean_diff'] = c1
753-
components['max_diff'] = c2
754-
components['line_length'] = c3
755-
components['slope_nstd'] = c4
756-
components['slope_max'] = c5
757-
components['mean_nan'] = c6
754+
components['mean_diff_flag'] = c1
755+
components['max_diff_flag'] = c2
756+
components['line_length_flag'] = c3
757+
components['slope_nstd_flag'] = c4
758+
components['slope_max_flag'] = c5
759+
components['mean_nan_flag'] = c6
758760
components['windows'] = clear_windows
761+
762+
components['mean_diff'] = np.abs(meas_mean - alpha * clear_mean)
763+
components['max_diff'] = np.abs(meas_max - alpha * clear_max)
764+
components['line_length'] = meas_line_length - clear_line_length
765+
components['slope_nstd'] = meas_slope_nstd
766+
components['slope_max'] = (np.max(
767+
meas_slope - alpha * clear_slope, axis=0))
768+
759769
return clear_samples, components, alpha
760770
else:
761771
return clear_samples

0 commit comments

Comments
 (0)