Skip to content
Open
Show file tree
Hide file tree
Changes from all 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`)
By :ghuser:`Omesh37`.
* 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
25 changes: 19 additions & 6 deletions pvlib/irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -1927,10 +1927,10 @@

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 @@

Returns
-------
dni : array-like
The modeled direct normal irradiance, as provided by the
DIRINT model. [Wm⁻²]
dni : numeric or pd.Series
Estimated direct normal irradiance. Returns float if all inputs
are scalar, pd.Series otherwise. [Wm⁻²]

Notes
-----
Expand All @@ -1983,7 +1983,8 @@
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)

Check failure on line 1987 in pvlib/irradiance.py

View workflow job for this annotation

GitHub Actions / flake8-linter

W293 blank line contains whitespace
disc_out = disc(ghi, solar_zenith, times, pressure=pressure,
min_cos_zenith=min_cos_zenith, max_zenith=max_zenith)
airmass = disc_out['airmass']
Expand All @@ -1998,9 +1999,12 @@
dirint_coeffs = _dirint_coeffs(times, kt_prime, solar_zenith, w,
delta_kt_prime)


# Perez eqn 5

Check failure on line 2003 in pvlib/irradiance.py

View workflow job for this annotation

GitHub Actions / flake8-linter

E303 too many blank lines (2)
dni = disc_out['dni'] * dirint_coeffs

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


Expand Down Expand Up @@ -2109,6 +2113,14 @@
-------
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
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 Expand Up @@ -2152,7 +2164,8 @@
return kt_prime_bin, zenith_bin, w_bin, delta_kt_prime_bin



Check failure on line 2167 in pvlib/irradiance.py

View workflow job for this annotation

GitHub Actions / flake8-linter

W293 blank line contains whitespace
def dirindex(ghi, ghi_clear, dni_clear, zenith, times, pressure=101325.,

Check failure on line 2168 in pvlib/irradiance.py

View workflow job for this annotation

GitHub Actions / flake8-linter

E303 too many blank lines (3)
use_delta_kt_prime=True, temp_dew=None, min_cos_zenith=0.065,
max_zenith=87):
"""
Expand Down
28 changes: 28 additions & 0 deletions tests/test_irradiance.py
Original file line number Diff line number Diff line change
Expand Up @@ -1139,8 +1139,36 @@
expected = pd.Series([nan, 5.], index=times)
assert_series_equal(out, expected)

def test_dirint_scalar_inputs():

Check failure on line 1142 in tests/test_irradiance.py

View workflow job for this annotation

GitHub Actions / flake8-linter

E302 expected 2 blank lines, found 1
"""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():

Check failure on line 1171 in tests/test_irradiance.py

View workflow job for this annotation

GitHub Actions / flake8-linter

E302 expected 2 blank lines, found 1
ghi = pd.Series([90, 100, 100, 100, 100])
dhi = pd.Series([100, 90, 50, 50, 50])
zenith = pd.Series([80, 100, 85, 70, 85])
Expand Down
Loading