Repository: pvlib/pvlib-python
Pull request #638 (2019-01-03 21:12:20)

fix _delta_kt_prime_dirint end values
pvlib python pull request guidelines
====================================

Thank you for your contribution to pvlib python! You may delete all of these instructions except for the list below.

You may submit a pull request with your code at any stage of completion.

The following items must be addressed before the code can be merged. Please don't hesitate to ask for help if you're unsure of how to accomplish any of the items below:

 - [x] Closes  #637
 - [x] I am familiar with the [contributing guidelines](http://pvlib-python.readthedocs.io/en/latest/contributing.html).
 - [x] Fully tested. Added and/or modified tests to ensure correct behavior for all reasonable inputs. Tests (usually) must pass on the TravisCI and Appveyor testing services.
 - [ ] Updates entries to `docs/sphinx/source/api.rst` for API changes.
 - [x] Adds description and name entries in the appropriate `docs/sphinx/source/whatsnew` file for all changes.
 - [x] Code quality and style is sufficient. Passes LGTM and SticklerCI checks.
 - [x] New code is fully documented. Includes sphinx/numpydoc compliant docstrings and comments in the code where necessary.
 - [x] Pull request is nearly complete and ready for detailed review.

Brief description of the problem and proposed solution (if not already fully described in the issue linked to above):

_delta_kt_prime_dirint does not implement Eq. 3 from Perez et al. reference in the calculation of `delta_kt_prime`.  Fixes that.


Patch:
diff --git a/docs/sphinx/source/whatsnew/v0.6.1.rst b/docs/sphinx/source/whatsnew/v0.6.1.rst
index ec8cc5b..3c1dda4 100644
--- a/docs/sphinx/source/whatsnew/v0.6.1.rst
+++ b/docs/sphinx/source/whatsnew/v0.6.1.rst
@@ -73,6 +73,8 @@ Bug fixes
 * Fix documentation errors when using IPython >= 7.0.
 * Fix error in :func:`pvlib.modelchain.ModelChain.infer_spectral_model` (:issue:`619`)
 * Fix error in ``pvlib.spa`` when using Python 3.7 on some platforms.
+* Fix error in :func:`pvlib.irradiance._delta_kt_prime_dirint` (:issue:`637`). The error affects
+  the first and last values of DNI calculated by the function :func:`pvlib.irradiance.dirint`
 
 
 Testing
diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py
index 4855187..84193d3 100644
--- a/pvlib/irradiance.py
+++ b/pvlib/irradiance.py
@@ -1558,14 +1558,20 @@ def _dirint_from_dni_ktprime(dni, kt_prime, solar_zenith, use_delta_kt_prime,
 
 def _delta_kt_prime_dirint(kt_prime, use_delta_kt_prime, times):
     """
-    Calculate delta kt prime (Perez eqn 2), or return a default value
+    Calculate delta_kt_prime (Perez eqn 2 and eqn 3), or return a default value
     for use with :py:func:`_dirint_bins`.
     """
     if use_delta_kt_prime:
         # Perez eqn 2
-        delta_kt_prime = 0.5*((kt_prime - kt_prime.shift(1)).abs().add(
-                              (kt_prime - kt_prime.shift(-1)).abs(),
-                              fill_value=0))
+        kt_next = kt_prime.shift(-1)
+        kt_previous = kt_prime.shift(1)
+        # replace nan with values that implement Perez Eq 3 for first and last
+        # positions. Use kt_previous and kt_next to handle series of length 1
+        kt_next.iloc[-1] = kt_previous.iloc[-1]
+        kt_previous.iloc[0] = kt_next.iloc[0]
+        delta_kt_prime = 0.5 * ((kt_prime - kt_next).abs().add(
+                                (kt_prime - kt_previous).abs(),
+                                fill_value=0))
     else:
         # do not change unless also modifying _dirint_bins
         delta_kt_prime = pd.Series(-1, index=times)


Test patch:
diff --git a/pvlib/test/test_irradiance.py b/pvlib/test/test_irradiance.py
index cd1c5b1..883d130 100644
--- a/pvlib/test/test_irradiance.py
+++ b/pvlib/test/test_irradiance.py
@@ -466,13 +466,13 @@ def test_dirint_value():
     pressure = 93193.
     dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure)
     assert_almost_equal(dirint_data.values,
-                        np.array([ 888. ,  683.7]), 1)
+                        np.array([868.8,  699.7]), 1)
 
 
 def test_dirint_nans():
     times = pd.DatetimeIndex(start='2014-06-24T12-0700', periods=5, freq='6H')
     ghi = pd.Series([np.nan, 1038.62, 1038.62, 1038.62, 1038.62], index=times)
-    zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567,], index=times)
+    zenith = pd.Series([10.567, np.nan, 10.567, 10.567, 10.567], index=times)
     pressure = pd.Series([93193., 93193., np.nan, 93193., 93193.], index=times)
     temp_dew = pd.Series([10, 10, 10, np.nan, 10], index=times)
     dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
@@ -489,7 +489,7 @@ def test_dirint_tdew():
     dirint_data = irradiance.dirint(ghi, zenith, times, pressure=pressure,
                                     temp_dew=10)
     assert_almost_equal(dirint_data.values,
-                        np.array([892.9,  636.5]), 1)
+                        np.array([882.1,  672.6]), 1)
 
 
 def test_dirint_no_delta_kt():
@@ -559,7 +559,7 @@ def test_gti_dirint():
     expected = pd.DataFrame(array(
         [[  21.05796198,    0.        ,   21.05796198],
          [ 288.22574368,   60.59964218,  245.37532576],
-         [ 930.85454521,  695.8504884 ,  276.96897609]]),
+         [ 931.04078010,  695.94965324,  277.06172442]]),
         columns=expected_col_order, index=times)
 
     assert_frame_equal(output, expected)
@@ -583,7 +583,7 @@ def test_gti_dirint():
     expected = pd.DataFrame(array(
         [[  21.05796198,    0.        ,   21.05796198],
          [ 289.81109139,   60.52460392,  247.01373353],
-         [ 932.22047435,  647.68716072,  323.59362885]]),
+         [ 932.46756378,  648.05001357,  323.49974813]]),
         columns=expected_col_order, index=times)
 
     assert_frame_equal(output, expected)
@@ -595,9 +595,9 @@ def test_gti_dirint():
         albedo=albedo)
 
     expected = pd.DataFrame(array(
-        [[  21.3592591 ,    0.        ,   21.3592591 ],
-         [ 292.5162373 ,   64.42628826,  246.95997198],
-         [ 941.47847463,  727.07261187,  258.25370648]]),
+        [[  21.3592591,    0.        ,   21.3592591 ],
+         [ 292.5162373,   64.42628826,  246.95997198],
+         [ 941.6753031,  727.16311901,  258.36548605]]),
         columns=expected_col_order, index=times)
 
     assert_frame_equal(output, expected)
@@ -611,7 +611,7 @@ def test_gti_dirint():
     expected = pd.DataFrame(array(
         [[  21.05796198,    0.        ,   21.05796198],
          [ 292.40468994,   36.79559287,  266.3862767 ],
-         [ 930.72198876,  712.36063132,  261.32196017]]),
+         [ 931.79627208,  689.81549269,  283.5817439]]),
         columns=expected_col_order, index=times)
 
     assert_frame_equal(output, expected)