diff --git a/docs/sphinx/source/whatsnew/v0.15.2.rst b/docs/sphinx/source/whatsnew/v0.15.2.rst index 37f8692280..ac56307b23 100644 --- a/docs/sphinx/source/whatsnew/v0.15.2.rst +++ b/docs/sphinx/source/whatsnew/v0.15.2.rst @@ -14,6 +14,9 @@ Deprecations Bug fixes ~~~~~~~~~ +* Added test coverage for :py:func:`pvlib.irradiance.dirint` with + ``np.array`` and ``pd.Series`` inputs. + (:issue:`2751`, :pull:`2752`) * Corrects a bug in :py:func:`pvlib.temperature.fuentes`. If inputs were data type integer, users can expect modeled cell temperature values to increase slightly. diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 5a4a76df25..7af379ae78 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -132,7 +132,9 @@ def _handle_extra_radiation_types(datetime_or_doy, epoch_year): # a better way to do it. if isinstance(datetime_or_doy, pd.DatetimeIndex): to_doy = tools._pandas_to_doy # won't be evaluated unless necessary - def to_datetimeindex(x): return x # noqa: E306 + + def to_datetimeindex(x): + return x # noqa: E306 to_output = partial(pd.Series, index=datetime_or_doy) elif isinstance(datetime_or_doy, pd.Timestamp): to_doy = tools._pandas_to_doy @@ -146,12 +148,14 @@ def to_datetimeindex(x): return x # noqa: E306 tools._datetimelike_scalar_to_datetimeindex to_output = tools._scalar_out elif np.isscalar(datetime_or_doy): # ints and floats of various types - def to_doy(x): return x # noqa: E306 + def to_doy(x): + return x # noqa: E306 to_datetimeindex = partial(tools._doy_to_datetimeindex, epoch_year=epoch_year) to_output = tools._scalar_out else: # assume that we have an array-like object of doy - def to_doy(x): return x # noqa: E306 + def to_doy(x): + return x # noqa: E306 to_datetimeindex = partial(tools._doy_to_datetimeindex, epoch_year=epoch_year) to_output = tools._array_out @@ -1964,14 +1968,14 @@ def dirint(ghi, solar_zenith, times, pressure=101325., use_delta_kt_prime=True, Returns ------- - dni : array-like - The modeled direct normal irradiance, as provided by the - DIRINT model. [Wm⁻²] + dni : pd.Series + Estimated direct normal irradiance. [Wm⁻²] Notes ----- - DIRINT model requires time series data (ie. one of the inputs must - be a vector of length > 2). + The DIRINT model was developed for time series data with length > 2. + The implementation in pvlib assumes the data are periodic which may + affect the first and last DNI values. References ---------- @@ -2109,6 +2113,7 @@ def _dirint_bins(times, kt_prime, zenith, w, delta_kt_prime): ------- tuple of kt_prime_bin, zenith_bin, w_bin, delta_kt_prime_bin """ + # @wholmgren: the following bin assignments use MATLAB's 1-indexing. # Later, we'll subtract 1 to conform to Python's 0-indexing. diff --git a/tests/test_irradiance.py b/tests/test_irradiance.py index a416636ae9..115adeb0ac 100644 --- a/tests/test_irradiance.py +++ b/tests/test_irradiance.py @@ -1140,6 +1140,31 @@ def test_dirindex_min_cos_zenith_max_zenith(): assert_series_equal(out, expected) +def test_dirint_array_inputs(): + """np.array and pd.Series inputs work correctly. GH #2751""" + times = pd.date_range('2023-06-21 10:00', periods=2, freq='h', tz='UTC') + + # np.array input → should return pd.Series + result = irradiance.dirint( + ghi=np.array([500.0, 400.0]), + solar_zenith=np.array([45.0, 50.0]), + times=times, + use_delta_kt_prime=False + ) + assert isinstance(result, pd.Series) + assert result.iloc[0] > 0 + + # pd.Series input → should return pd.Series + times2 = pd.date_range('2023-06-21 10:00', periods=3, freq='h', tz='UTC') + result2 = irradiance.dirint( + ghi=pd.Series([400, 500, 300], index=times2), + solar_zenith=pd.Series([50, 40, 60], index=times2), + times=times2 + ) + assert isinstance(result2, pd.Series) + assert (result2 >= 0).all() + + def test_dni(): ghi = pd.Series([90, 100, 100, 100, 100]) dhi = pd.Series([100, 90, 50, 50, 50])