Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
3 changes: 3 additions & 0 deletions docs/sphinx/source/whatsnew/v0.15.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Deprecations

Bug fixes
~~~~~~~~~
* Fixed :py:func:`pvlib.irradiance.dirint` raising ``KeyError`` with
scalar inputs on pandas >= 2.0. (:pull:`2752`, :issue:`2751`)
Comment thread
Omesh37 marked this conversation as resolved.
Outdated
By :ghuser:`Omesh37`.
Comment thread
Omesh37 marked this conversation as resolved.
Outdated
* 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.
Expand Down
21 changes: 16 additions & 5 deletions pvlib/irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -1927,10 +1927,10 @@ def dirint(ghi, solar_zenith, times, pressure=101325., use_delta_kt_prime=True,

Parameters
----------
ghi : array-like
ghi : numeric
Global horizontal irradiance. See :term:`ghi`. [Wm⁻²]

solar_zenith : array-like
solar_zenith : numeric
True (not refraction-corrected) solar zenith angles. See
:term:`solar_zenith`. [°]

Expand Down Expand Up @@ -1964,9 +1964,9 @@ 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 : numeric or pd.Series
Comment thread
Omesh37 marked this conversation as resolved.
Outdated
Estimated direct normal irradiance. Returns float if all inputs
are scalar, pd.Series otherwise. [Wm⁻²]

Notes
-----
Expand All @@ -1983,6 +1983,7 @@ def dirint(ghi, solar_zenith, times, pressure=101325., use_delta_kt_prime=True,
Global Horizontal to Direct Normal Insolation", Technical Report No.
SERI/TR-215-3087, Golden, CO: Solar Energy Research Institute, 1987.
"""
scalar_input = np.isscalar(solar_zenith)

disc_out = disc(ghi, solar_zenith, times, pressure=pressure,
min_cos_zenith=min_cos_zenith, max_zenith=max_zenith)
Expand All @@ -2001,6 +2002,8 @@ def dirint(ghi, solar_zenith, times, pressure=101325., use_delta_kt_prime=True,
# Perez eqn 5
dni = disc_out['dni'] * dirint_coeffs

if scalar_input:
return float(dni.iloc[0])
return dni


Expand Down Expand Up @@ -2109,6 +2112,14 @@ def _dirint_bins(times, kt_prime, zenith, w, delta_kt_prime):
-------
tuple of kt_prime_bin, zenith_bin, w_bin, delta_kt_prime_bin
"""
# Ensure scalar inputs are converted to Series so that boolean masks
# produce a boolean Series rather than a scalar bool.
# Scalar bools cause KeyError in pandas >= 2.0. GH #XXXX
Comment thread
Omesh37 marked this conversation as resolved.
kt_prime = pd.Series(kt_prime, index=times, dtype=float)
zenith = pd.Series(zenith, index=times, dtype=float)
w = pd.Series(w, index=times, dtype=float)
delta_kt_prime = pd.Series(delta_kt_prime, index=times, dtype=float)

# @wholmgren: the following bin assignments use MATLAB's 1-indexing.
# Later, we'll subtract 1 to conform to Python's 0-indexing.

Expand Down
30 changes: 30 additions & 0 deletions tests/test_irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,36 @@ def test_dirindex_min_cos_zenith_max_zenith():
assert_series_equal(out, expected)


def test_dirint_scalar_inputs():
"""Scalar numeric inputs return scalar float output. GH #2751"""
times = pd.DatetimeIndex(['2023-06-21 12:00'], tz='UTC')

# scalar int input → should return float (not Series)
result = irradiance.dirint(
ghi=500, solar_zenith=45, times=times
)
assert np.isscalar(result), "scalar input should return scalar output"
assert isinstance(result, float)

# scalar float with delta_kt_prime disabled → non-NaN value check
result = irradiance.dirint(
ghi=500.0, solar_zenith=45.0, times=times,
use_delta_kt_prime=False
)
assert np.isscalar(result)
assert isinstance(result, float)
assert result > 0 # should be positive DNI

# Series input → should still return Series (regression check)
times2 = pd.date_range('2023-06-21 10:00', periods=3, freq='h', tz='UTC')
result_series = irradiance.dirint(
ghi=pd.Series([400, 500, 300], index=times2),
solar_zenith=pd.Series([50, 40, 60], index=times2),
times=times2
)
assert isinstance(result_series, pd.Series)


def test_dni():
ghi = pd.Series([90, 100, 100, 100, 100])
dhi = pd.Series([100, 90, 50, 50, 50])
Expand Down
Loading