Skip to content

Commit

Permalink
Address several numpy/pandas deprecation warnings; clean up test outp…
Browse files Browse the repository at this point in the history
…ut (#1930)

* install pytest-remotedata from conda-forge

The version in default channel is old.  Version in conda-forge is up to date and contains a fix for this deprecation warning:

DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead.

* nix `unit='T'` in pd.to_timedelta

Use `unit='minutes'` instead of `unit='T'` ('T' was deprecated in pandas 2.1).  Fixes:

FutureWarning: Unit 'T' is deprecated and will be removed in a future version.

* Fix StringIO error regex for python 3.12

* use iloc with pandas Series

Fixes:

FutureWarning: Series.__setitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To set a value by position, use `ser.iloc[pos] = value`

* use pandas bfill()/ffill() instead of fillna(method='...')

Fixes:

FutureWarning: DataFrame.fillna with 'method' is deprecated and will raise in a future version. Use obj.ffill() or obj.bfill() instead.

* avoid incompatible dtypes in solarposition.ephemeris

Fixes:

FutureWarning: Setting an item of incompatible dtype is deprecated and will raise in a future error of pandas. Value '[69.43454873]' has dtype incompatible with int64, please explicitly cast to a compatible dtype first.

* convert np array of length 1 to scalar

Fixes:

DeprecationWarning: Conversion of an array with ndim > 0 to a scalar is deprecated, and will error in future. Ensure you extract a single element from your array before performing this operation. (Deprecated NumPy 1.25.)

* use numpy.errstate in bifacial.utils tests

Fixes:

RuntimeWarning: invalid value encountered in multiply
RuntimeWarning: invalid value encountered in scalar multiply

* Fix another pandas iloc warning

Fixes:

FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  • Loading branch information
kandersolar authored Dec 19, 2023
1 parent 12ba8ee commit 8057393
Show file tree
Hide file tree
Showing 14 changed files with 29 additions and 21 deletions.
2 changes: 1 addition & 1 deletion ci/requirements-py3.10.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies:
- requests-mock
- pytest-timeout
- pytest-rerunfailures
- pytest-remotedata
- conda-forge::pytest-remotedata # version in default channel is old
- python=3.10
- pytz
- requests
Expand Down
2 changes: 1 addition & 1 deletion ci/requirements-py3.11.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies:
- requests-mock
- pytest-timeout
- pytest-rerunfailures
- pytest-remotedata
- conda-forge::pytest-remotedata # version in default channel is old
- python=3.11
- pytz
- requests
Expand Down
2 changes: 1 addition & 1 deletion ci/requirements-py3.12.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies:
- requests-mock
- pytest-timeout
- pytest-rerunfailures
- pytest-remotedata
- conda-forge::pytest-remotedata # version in default channel is old
- python=3.12
- pytz
- requests
Expand Down
2 changes: 1 addition & 1 deletion ci/requirements-py3.7.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies:
- requests-mock
- pytest-timeout
- pytest-rerunfailures
- pytest-remotedata
- conda-forge::pytest-remotedata # version in default channel is old
- python=3.7
- pytz
- requests
Expand Down
2 changes: 1 addition & 1 deletion ci/requirements-py3.8.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies:
- requests-mock
- pytest-timeout
- pytest-rerunfailures
- pytest-remotedata
- conda-forge::pytest-remotedata # version in default channel is old
- python=3.8
- pytz
- requests
Expand Down
2 changes: 1 addition & 1 deletion ci/requirements-py3.9.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies:
- requests-mock
- pytest-timeout
- pytest-rerunfailures
- pytest-remotedata
- conda-forge::pytest-remotedata # version in default channel is old
- python=3.9
- pytz
- requests
Expand Down
6 changes: 3 additions & 3 deletions pvlib/iotools/bsrn.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def parse_bsrn(fbuf, logical_records=('0100',)):
LR_0100.columns = BSRN_LR0100_COLUMNS
# Set datetime index
LR_0100.index = (start_date+pd.to_timedelta(LR_0100['day']-1, unit='d')
+ pd.to_timedelta(LR_0100['minute'], unit='T'))
+ pd.to_timedelta(LR_0100['minute'], unit='minutes'))
# Drop empty, minute, and day columns
LR_0100 = LR_0100.drop(columns=['empty', 'day', 'minute'])
dfs.append(LR_0100)
Expand All @@ -335,7 +335,7 @@ def parse_bsrn(fbuf, logical_records=('0100',)):
colspecs=BSRN_LR0300_COL_SPECS,
names=BSRN_LR0300_COLUMNS)
LR_0300.index = (start_date+pd.to_timedelta(LR_0300['day']-1, unit='d')
+ pd.to_timedelta(LR_0300['minute'], unit='T'))
+ pd.to_timedelta(LR_0300['minute'], unit='minutes'))
LR_0300 = LR_0300.drop(columns=['day', 'minute']).astype(float)
dfs.append(LR_0300)

Expand All @@ -352,7 +352,7 @@ def parse_bsrn(fbuf, logical_records=('0100',)):
LR_0500 = LR_0500.reindex(sorted(LR_0500.columns), axis='columns')
LR_0500.columns = BSRN_LR0500_COLUMNS
LR_0500.index = (start_date+pd.to_timedelta(LR_0500['day']-1, unit='d')
+ pd.to_timedelta(LR_0500['minute'], unit='T'))
+ pd.to_timedelta(LR_0500['minute'], unit='minutes'))
LR_0500 = LR_0500.drop(columns=['empty', 'day', 'minute'])
dfs.append(LR_0500)

Expand Down
2 changes: 1 addition & 1 deletion pvlib/ivtools/sdm.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ def _fit_desoto_sandia_diode(ee, voc, vth, tc, specs, const):
y = voc - specs['beta_voc'] * (tc - const['T0'])
new_x = sm.add_constant(x)
res = sm.RLM(y, new_x).fit()
return res.params[1]
return np.array(res.params)[1]


def _initial_iv_params(ivcurves, ee, voc, isc, rsh, nnsvth):
Expand Down
3 changes: 2 additions & 1 deletion pvlib/scaling.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ def fn(x):
return np.abs((x ** 2 - x) / 2 - n_pairs)

n_dist = np.round(scipy.optimize.fmin(fn, np.sqrt(n_pairs), disp=False))
n_dist = n_dist.item()
# Compute VR
A = cloud_speed / 2 # Resultant fit for A from [2]
vr = np.zeros(tmscales.shape)
Expand Down Expand Up @@ -276,7 +277,7 @@ def _compute_wavelet(clearsky_index, dt=None):
# Produces slightly different end effects than the MATLAB version
df = cs_long.rolling(window=intvlen, center=True, min_periods=1).mean()
# Fill nan's in both directions
df = df.fillna(method='bfill').fillna(method='ffill')
df = df.bfill().ffill()
# Pop values back out of the dataframe and store
csi_mean[i, :] = df.values.flatten()
# Shift to account for different indexing in MATLAB moving average
Expand Down
4 changes: 2 additions & 2 deletions pvlib/snow.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ def fully_covered_nrel(snowfall, threshold_snowfall=1.):
freq = pd.infer_freq(snowfall.index)
if freq is not None:
timedelta = pd.tseries.frequencies.to_offset(freq) / pd.Timedelta('1h')
hourly_snow_rate.iloc[0] = snowfall[0] / timedelta
hourly_snow_rate.iloc[0] = snowfall.iloc[0] / timedelta
else: # can't infer frequency from index
hourly_snow_rate[0] = 0 # replaces NaN
hourly_snow_rate.iloc[0] = 0 # replaces NaN
return hourly_snow_rate > threshold_snowfall


Expand Down
2 changes: 1 addition & 1 deletion pvlib/soiling.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def hsu(rainfall, cleaning_threshold, surface_tilt, pm2_5, pm10,
mass_no_cleaning = pd.Series(index=rainfall.index, data=tms_cumsum)
# specify dtype so pandas doesn't assume object
mass_removed = pd.Series(index=rainfall.index, dtype='float64')
mass_removed[0] = 0.
mass_removed.iloc[0] = 0.
mass_removed[cleaning_times] = mass_no_cleaning[cleaning_times]
accum_mass = mass_no_cleaning - mass_removed.ffill()

Expand Down
2 changes: 1 addition & 1 deletion pvlib/solarposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ def ephemeris(time, latitude, longitude, pressure=101325, temperature=12):
# Calculate refraction correction
Elevation = SunEl
TanEl = pd.Series(np.tan(np.radians(Elevation)), index=time_utc)
Refract = pd.Series(0, index=time_utc)
Refract = pd.Series(0., index=time_utc)

Refract[(Elevation > 5) & (Elevation <= 85)] = (
58.1/TanEl - 0.07/(TanEl**3) + 8.6e-05/(TanEl**5))
Expand Down
14 changes: 10 additions & 4 deletions pvlib/tests/bifacial/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,15 @@ def test_vf_row_sky_2d(test_system_fixed_tilt):
def test_vf_row_sky_2d_integ(test_system_fixed_tilt):
ts, _, _ = test_system_fixed_tilt
# with float input, check end position
vf = utils.vf_row_sky_2d_integ(ts['surface_tilt'], ts['gcr'], 1., 1.)
with np.errstate(invalid='ignore'):
vf = utils.vf_row_sky_2d_integ(ts['surface_tilt'], ts['gcr'], 1., 1.)
expected = utils.vf_row_sky_2d(ts['surface_tilt'], ts['gcr'], 1.)
assert np.isclose(vf, expected)
# with array input
fx0 = np.array([0., 0.5])
fx1 = np.array([0., 0.8])
vf = utils.vf_row_sky_2d_integ(ts['surface_tilt'], ts['gcr'], fx0, fx1)
with np.errstate(invalid='ignore'):
vf = utils.vf_row_sky_2d_integ(ts['surface_tilt'], ts['gcr'], fx0, fx1)
phi = masking_angle(ts['surface_tilt'], ts['gcr'], fx0[0])
y0 = 0.5 * (1 + cosd(ts['surface_tilt'] + phi))
x = np.arange(fx0[1], fx1[1], 1e-4)
Expand Down Expand Up @@ -161,13 +163,17 @@ def test_vf_row_ground_2d(test_system_fixed_tilt):
def test_vf_ground_2d_integ(test_system_fixed_tilt):
ts, _, _ = test_system_fixed_tilt
# with float input, check end position
vf = utils.vf_row_ground_2d_integ(ts['surface_tilt'], ts['gcr'], 0., 0.)
with np.errstate(invalid='ignore'):
vf = utils.vf_row_ground_2d_integ(ts['surface_tilt'], ts['gcr'],
0., 0.)
expected = utils.vf_row_ground_2d(ts['surface_tilt'], ts['gcr'], 0.)
assert np.isclose(vf, expected)
# with array input
fx0 = np.array([0., 0.5])
fx1 = np.array([0., 0.8])
vf = utils.vf_row_ground_2d_integ(ts['surface_tilt'], ts['gcr'], fx0, fx1)
with np.errstate(invalid='ignore'):
vf = utils.vf_row_ground_2d_integ(ts['surface_tilt'], ts['gcr'],
fx0, fx1)
phi = ground_angle(ts['surface_tilt'], ts['gcr'], fx0[0])
y0 = 0.5 * (1 - cosd(phi - ts['surface_tilt']))
x = np.arange(fx0[1], fx1[1], 1e-4)
Expand Down
5 changes: 3 additions & 2 deletions pvlib/tests/iotools/test_pvgis.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,9 @@ def test_read_pvgis_hourly_bad_extension():
# Test if ValueError is raised if an unkonwn pvgis_format is specified
with pytest.raises(ValueError, match="pvgis format 'txt' was unknown"):
read_pvgis_hourly(testfile_pv_json, pvgis_format='txt')
# Test if TypeError is raised if input is a buffer and pvgis_format=None
with pytest.raises(TypeError, match="expected str, bytes or os.PathLike"):
# Test if TypeError is raised if input is a buffer and pvgis_format=None.
# The error text changed in python 3.12. This regex matches both versions:
with pytest.raises(TypeError, match="str.*os.PathLike"):
read_pvgis_hourly(io.StringIO())


Expand Down

0 comments on commit 8057393

Please sign in to comment.