From c91181161b12f11227368495e0e04a461011f2eb Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Thu, 18 May 2023 18:08:11 +0100 Subject: [PATCH 1/3] Avoid numpy warning when converting float array containing NaNs to int --- datashader/reductions.py | 6 +++++- datashader/transfer_functions/__init__.py | 12 ++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/datashader/reductions.py b/datashader/reductions.py index 530f2398c..d6c348875 100644 --- a/datashader/reductions.py +++ b/datashader/reductions.py @@ -199,7 +199,11 @@ def apply(self, df): values = df[self.column].to_numpy() nan_values = np.isnan(values) - index = ((values - self.bin0) / self.binsize).astype(int) + index_float = (values - self.bin0) / self.binsize + # NaN values are corrected below, so set them to zero to avoid warnings when + # converting from float to int. + index_float[nan_values] = 0 + index = index_float.astype(int) index[index < 0] = self.bin_under index[index >= self.nbins] = self.bin_over index[nan_values] = self.nbins diff --git a/datashader/transfer_functions/__init__.py b/datashader/transfer_functions/__init__.py index e2de7b22d..c0fd1b014 100755 --- a/datashader/transfer_functions/__init__.py +++ b/datashader/transfer_functions/__init__.py @@ -307,9 +307,9 @@ def _interpolate(agg, cmap, how, alpha, span, min_alpha, name, rescale_discrete_ if isinstance(cmap, list): rspan, gspan, bspan = np.array(list(zip(*map(rgb, cmap)))) span = np.linspace(span[0], span[1], len(cmap)) - r = interp(data, span, rspan, left=255).astype(np.uint8) - g = interp(data, span, gspan, left=255).astype(np.uint8) - b = interp(data, span, bspan, left=255).astype(np.uint8) + r = np.nan_to_num(interp(data, span, rspan, left=255), copy=False).astype(np.uint8) + g = np.nan_to_num(interp(data, span, gspan, left=255), copy=False).astype(np.uint8) + b = np.nan_to_num(interp(data, span, bspan, left=255), copy=False).astype(np.uint8) a = np.where(np.isnan(data), 0, alpha).astype(np.uint8) rgba = np.dstack([r, g, b, a]) elif isinstance(cmap, str) or isinstance(cmap, tuple): @@ -319,7 +319,7 @@ def _interpolate(agg, cmap, how, alpha, span, min_alpha, name, rescale_discrete_ r = np.full(data.shape, color[0], dtype=np.uint8) g = np.full(data.shape, color[1], dtype=np.uint8) b = np.full(data.shape, color[2], dtype=np.uint8) - a = interp(data, span, aspan, left=0, right=255).astype(np.uint8) + a = np.nan_to_num(interp(data, span, aspan, left=0, right=255), copy=False).astype(np.uint8) rgba = np.dstack([r, g, b, a]) elif callable(cmap): # Assume callable is matplotlib colormap @@ -494,8 +494,8 @@ def _interpolate_alpha(data, total, mask, how, alpha, span, min_alpha, rescale_d norm_span = array_module.hstack(norm_span) # Interpolate the alpha values - a = interp(a_scaled, norm_span, array_module.array([min_alpha, alpha]), - left=0, right=255).astype(np.uint8) + a_float = interp(a_scaled, norm_span, array_module.array([min_alpha, alpha]), left=0, right=255) + a = np.nan_to_num(a_float, copy=False).astype(np.uint8) return a From c57c7764e886780cde036d810aeab281e42604d6 Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Fri, 19 May 2023 11:08:14 +0100 Subject: [PATCH 2/3] Avoid numpy warning about all-nan slice --- datashader/transfer_functions/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/datashader/transfer_functions/__init__.py b/datashader/transfer_functions/__init__.py index c0fd1b014..17d82209c 100755 --- a/datashader/transfer_functions/__init__.py +++ b/datashader/transfer_functions/__init__.py @@ -379,7 +379,9 @@ def _colorize(agg, color_key, how, alpha, span, min_alpha, name, color_baseline, color_data = data.copy() # subtract color_baseline if needed - baseline = np.nanmin(color_data) if color_baseline is None else color_baseline + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'All-NaN slice encountered') + baseline = np.nanmin(color_data) if color_baseline is None else color_baseline with np.errstate(invalid='ignore'): if baseline > 0: color_data -= baseline @@ -444,7 +446,9 @@ def _interpolate_alpha(data, total, mask, how, alpha, span, min_alpha, rescale_d # if span is provided, use it, otherwise produce a span based off the # min/max of the data if span is None: - offset = np.nanmin(total) + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', r'All-NaN slice encountered') + offset = np.nanmin(total) if total.dtype.kind == 'u' and offset == 0: mask = mask | (total == 0) # If at least one element is not masked, use the minimum as the offset From 26c8f4ad8f3a8d99f26a8a871cfbe440af8eab7f Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Fri, 19 May 2023 11:44:09 +0100 Subject: [PATCH 3/3] Fix raster fill_type to be integer if dtype is integer --- datashader/core.py | 2 ++ datashader/tests/test_raster.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/datashader/core.py b/datashader/core.py index 2a7b845cf..7d6a59ba2 100644 --- a/datashader/core.py +++ b/datashader/core.py @@ -1070,6 +1070,8 @@ def raster(self, mask = array==nan_value array = np.ma.masked_array(array, mask=mask, fill_value=nan_value) fill_value = nan_value + elif np.issubdtype(source.dtype, np.integer): + fill_value = 0 else: fill_value = np.NaN diff --git a/datashader/tests/test_raster.py b/datashader/tests/test_raster.py index 2df4689e9..c8f957fb4 100644 --- a/datashader/tests/test_raster.py +++ b/datashader/tests/test_raster.py @@ -11,6 +11,10 @@ except ImportError: rioxarray = None +from dask.context import config + +config.set(scheduler='synchronous') + open_rasterio_available = pytest.mark.skipif(rioxarray is None and rasterio is None, reason="requires rioxarray or rasterio") from os import path