From 835c3c04efa4a915c57e2dc25a728e4e1374f7ae Mon Sep 17 00:00:00 2001 From: Daniele Nerini Date: Thu, 26 Feb 2026 20:59:19 +0100 Subject: [PATCH 1/3] Fix pandas-compatible scalar assignment in tdating --- pysteps/tracking/tdating.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/pysteps/tracking/tdating.py b/pysteps/tracking/tdating.py index 97b1de9e4..cb01f2037 100644 --- a/pysteps/tracking/tdating.py +++ b/pysteps/tracking/tdating.py @@ -381,17 +381,18 @@ def advect(cells_id, labels, V1, output_splits_merges=False): new_cen_x = cell.cen_x + ad_x new_cen_y = cell.cen_y + ad_y - cells_ad.loc[ID, "x"] = new_x - cells_ad.loc[ID, "y"] = new_y - cells_ad.loc[ID, "flowx"] = ad_x - cells_ad.loc[ID, "flowy"] = ad_y - cells_ad.loc[ID, "cen_x"] = new_cen_x - cells_ad.loc[ID, "cen_y"] = new_cen_y - cells_ad.loc[ID, "ID"] = cell.ID + # Use scalar cell assignment (.at) to store array-like payloads in object columns. + cells_ad.at[ID, "x"] = new_x + cells_ad.at[ID, "y"] = new_y + cells_ad.at[ID, "flowx"] = ad_x + cells_ad.at[ID, "flowy"] = ad_y + cells_ad.at[ID, "cen_x"] = new_cen_x + cells_ad.at[ID, "cen_y"] = new_cen_y + cells_ad.at[ID, "ID"] = cell.ID cell_unique = np.zeros(labels.shape) cell_unique[new_y, new_x] = 1 - cells_ad.loc[ID, "cont"] = skime.find_contours(cell_unique, 0.8) + cells_ad.at[ID, "cont"] = skime.find_contours(cell_unique, 0.8) return cells_ad @@ -411,7 +412,7 @@ def match(cells_ad, labels, match_frac=0.4, split_frac=0.1, output_splits_merges IDs = np.unique(ID_vec) n_IDs = len(IDs) if n_IDs == 1 and IDs[0] == 0: - cells_ov.loc[ID_a, "t_ID"] = 0 + cells_ov.at[ID_a, "t_ID"] = 0 continue IDs = IDs[IDs != 0] n_IDs = len(IDs) @@ -429,18 +430,18 @@ def match(cells_ad, labels, match_frac=0.4, split_frac=0.1, output_splits_merges # splits here if sum(valid_split_ids) > 1: # Save split information - cells_ov.loc[ID_a, "splitted"] = True - cells_ov.loc[ID_a, "split_IDs"] = IDs[valid_split_ids] - cells_ov.loc[ID_a, "split_fracs"] = N / len(ID_vec) + cells_ov.at[ID_a, "splitted"] = True + cells_ov.at[ID_a, "split_IDs"] = IDs[valid_split_ids].tolist() + cells_ov.at[ID_a, "split_fracs"] = (N / len(ID_vec)).tolist() m = np.argmax(N) ID_match = IDs[m] ID_coverage = N[m] / len(ID_vec) if ID_coverage >= match_frac: - cells_ov.loc[ID_a, "t_ID"] = ID_match + cells_ov.at[ID_a, "t_ID"] = ID_match else: - cells_ov.loc[ID_a, "t_ID"] = 0 - cells_ov.loc[ID_a, "frac"] = ID_coverage + cells_ov.at[ID_a, "t_ID"] = 0 + cells_ov.at[ID_a, "frac"] = ID_coverage return cells_ov, labels, possible_merge_ids From 8accf76230e416947199f304b6c657aebf98accb Mon Sep 17 00:00:00 2001 From: Daniele Nerini Date: Thu, 26 Feb 2026 21:16:51 +0100 Subject: [PATCH 2/3] Fix invalid escape sequence warnings in docstrings and labels --- pysteps/nowcasts/interface.py | 4 ++-- pysteps/scripts/fit_vel_pert_params.py | 4 ++-- pysteps/timeseries/correlation.py | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pysteps/nowcasts/interface.py b/pysteps/nowcasts/interface.py index 19b01a523..16d015dd0 100644 --- a/pysteps/nowcasts/interface.py +++ b/pysteps/nowcasts/interface.py @@ -1,4 +1,4 @@ -""" +r""" pysteps.nowcasts.interface ========================== @@ -55,7 +55,7 @@ def get_method(name): - """ + r""" Return a callable function for computing nowcasts. Description: diff --git a/pysteps/scripts/fit_vel_pert_params.py b/pysteps/scripts/fit_vel_pert_params.py index 17dcb3684..06e9fcac4 100644 --- a/pysteps/scripts/fit_vel_pert_params.py +++ b/pysteps/scripts/fit_vel_pert_params.py @@ -74,8 +74,8 @@ (l1,) = pyplot.plot(t, f(t, *p_par), "r-") (l2,) = pyplot.plot(t, f(t, *p_perp), "g-") - p_str_1 = lambda p: "%.2f\cdot t^{%.2f}+%.2f" % (p[0], p[1], p[2]) - p_str_2 = lambda p: "%.2f\cdot t^{%.2f}%.2f" % (p[0], p[1], p[2]) + p_str_1 = lambda p: "%.2f\\cdot t^{%.2f}+%.2f" % (p[0], p[1], p[2]) + p_str_2 = lambda p: "%.2f\\cdot t^{%.2f}%.2f" % (p[0], p[1], p[2]) if fit_succeeded: lbl = lambda p: p_str_1(p) if p[2] > 0.0 else p_str_2(p) pyplot.legend( diff --git a/pysteps/timeseries/correlation.py b/pysteps/timeseries/correlation.py index a43b41a7e..4fa3fe8ef 100644 --- a/pysteps/timeseries/correlation.py +++ b/pysteps/timeseries/correlation.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -""" +r""" pysteps.timeseries.correlation ============================== @@ -28,7 +28,7 @@ def temporal_autocorrelation( window="gaussian", window_radius=np.inf, ): - """ + r""" Compute lag-l temporal autocorrelation coefficients :math:`\gamma_l=\mbox{corr}(x(t),x(t-l))`, :math:`l=1,2,\dots,n-1`, from a time series :math:`x_1,x_2,\dots,x_n`. If a multivariate time series @@ -133,7 +133,7 @@ def temporal_autocorrelation( def temporal_autocorrelation_multivariate( x, d=0, mask=None, window="gaussian", window_radius=np.inf ): - """ + r""" For a :math:`q`-variate time series :math:`\mathbf{x}_1,\mathbf{x}_2,\dots,\mathbf{x}_n`, compute the lag-l correlation matrices :math:`\mathbf{\Gamma}_l`, where From de06a876a28043c8b6a129c663711d04a3bd7ab6 Mon Sep 17 00:00:00 2001 From: Daniele Nerini Date: Thu, 26 Feb 2026 21:28:08 +0100 Subject: [PATCH 3/3] Fix GDAL and NumPy deprecation warnings in IO modules --- pysteps/io/exporters.py | 4 ++++ pysteps/io/importers.py | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/pysteps/io/exporters.py b/pysteps/io/exporters.py index 1f7685cba..7c966b2b9 100644 --- a/pysteps/io/exporters.py +++ b/pysteps/io/exporters.py @@ -100,6 +100,10 @@ try: from osgeo import gdal, osr + # Preserve current behavior explicitly (no GDAL exceptions) and avoid the + # GDAL 4.0 future-warning emitted when neither mode is selected. + if hasattr(gdal, "DontUseExceptions"): + gdal.DontUseExceptions() GDAL_IMPORTED = True except ImportError: GDAL_IMPORTED = False diff --git a/pysteps/io/importers.py b/pysteps/io/importers.py index 1c890e465..ad687c53c 100644 --- a/pysteps/io/importers.py +++ b/pysteps/io/importers.py @@ -104,6 +104,10 @@ try: from osgeo import gdal, gdalconst, osr + # Preserve current behavior explicitly (no GDAL exceptions) and avoid the + # GDAL 4.0 future-warning emitted when neither mode is selected. + if hasattr(gdal, "DontUseExceptions"): + gdal.DontUseExceptions() GDAL_IMPORTED = True except ImportError: GDAL_IMPORTED = False @@ -1615,11 +1619,11 @@ def _import_saf_crri_data(filename, idx_x=None, idx_y=None): ds_rainfall = netCDF4.Dataset(filename) if "crr_intensity" in ds_rainfall.variables.keys(): if idx_x is not None: - data = np.array(ds_rainfall.variables["crr_intensity"][idx_y, idx_x]) - quality = np.array(ds_rainfall.variables["crr_quality"][idx_y, idx_x]) + data = np.asarray(ds_rainfall.variables["crr_intensity"][idx_y, idx_x]) + quality = np.asarray(ds_rainfall.variables["crr_quality"][idx_y, idx_x]) else: - data = np.array(ds_rainfall.variables["crr_intensity"]) - quality = np.array(ds_rainfall.variables["crr_quality"]) + data = np.asarray(ds_rainfall.variables["crr_intensity"][:]) + quality = np.asarray(ds_rainfall.variables["crr_quality"][:]) precipitation = np.where(data == 65535, np.nan, data) else: precipitation = None