From 35aee00e45006df7d4148ee76c02bb70fc56a96d Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Mon, 30 Mar 2026 11:28:13 +0200 Subject: [PATCH 1/2] Optimize add_bounds --- cf_xarray/helpers.py | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/cf_xarray/helpers.py b/cf_xarray/helpers.py index 5ca5b1b9..8b66e51d 100644 --- a/cf_xarray/helpers.py +++ b/cf_xarray/helpers.py @@ -17,25 +17,18 @@ def _guess_bounds_1d(da, dim): """ if dim not in da.dims: (dim,) = da.cf.axes[dim] - ADDED_INDEX = False - if dim not in da.coords: - # For proper alignment in the lines below, we need an index on dim. - da = da.assign_coords({dim: da[dim]}) - ADDED_INDEX = True bound_position = 0.5 - diff = da.diff(dim).pad({dim: (1, 1)}, mode="edge").reset_index(dim) - lower = ( - da.reset_index(dim) - bound_position * diff.isel({dim: slice(0, -1)}) - ).assign_coords({dim: da[dim]}) - upper = ( - da.reset_index(dim) + bound_position * diff.isel({dim: slice(1, None)}) - ).assign_coords({dim: da[dim]}) - result = xr.concat([lower, upper], dim="bounds").transpose(..., "bounds") - - if ADDED_INDEX: - result = result.drop_vars(dim) - return result.drop_attrs(deep=False) + + diff = da.diff(dim).pad({dim: (1, 1)}, mode="edge") + lower = da.data - bound_position * diff.isel({dim: slice(0, -1)}).data + upper = da.data + bound_position * diff.isel({dim: slice(1, None)}).data + return ( + da.expand_dims({"bounds": 2}) + .copy(deep=False, data=[lower, upper]) + .transpose(..., "bounds") + .drop_attrs(deep=False) + ) def _guess_bounds_2d(da, dims): From f466765d32ac9b8e0ceaa1c3cc4a31fbdcbcfc16 Mon Sep 17 00:00:00 2001 From: Bouwe Andela Date: Wed, 1 Apr 2026 08:38:37 +0200 Subject: [PATCH 2/2] Preserve array type --- cf_xarray/helpers.py | 13 +++++++++---- cf_xarray/tests/test_accessor.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/cf_xarray/helpers.py b/cf_xarray/helpers.py index 8b66e51d..108a9c81 100644 --- a/cf_xarray/helpers.py +++ b/cf_xarray/helpers.py @@ -21,11 +21,16 @@ def _guess_bounds_1d(da, dim): bound_position = 0.5 diff = da.diff(dim).pad({dim: (1, 1)}, mode="edge") - lower = da.data - bound_position * diff.isel({dim: slice(0, -1)}).data - upper = da.data + bound_position * diff.isel({dim: slice(1, None)}).data + lower = da.copy( + deep=False, + data=da.data - bound_position * diff.isel({dim: slice(0, -1)}).data, + ) + upper = da.copy( + deep=False, + data=da.data + bound_position * diff.isel({dim: slice(1, None)}).data, + ) return ( - da.expand_dims({"bounds": 2}) - .copy(deep=False, data=[lower, upper]) + xr.concat([lower, upper], dim="bounds") .transpose(..., "bounds") .drop_attrs(deep=False) ) diff --git a/cf_xarray/tests/test_accessor.py b/cf_xarray/tests/test_accessor.py index b9ef3ed9..ce9c7a78 100644 --- a/cf_xarray/tests/test_accessor.py +++ b/cf_xarray/tests/test_accessor.py @@ -3,6 +3,7 @@ import warnings from textwrap import dedent +import dask.array import matplotlib as mpl import numpy as np import pandas as pd @@ -839,6 +840,21 @@ def test_add_bounds(dims): _check_unchanged(original, ds) +def test_add_bounds_preserves_array_type() -> None: + # Test that the array type of the bounds variable is the same as the original variable. + ds = airds + original = ds.copy(deep=True) + ds = ds.drop_indexes("lat").rename_dims(lat="x") + ds["lat"] = ds.lat.copy(data=dask.array.asarray(ds.lat.data)) + added = ds.cf.add_bounds("lat") + + assert isinstance(added.lat.data, dask.array.Array) + assert isinstance(added.lat_bounds.data, dask.array.Array) + + assert isinstance(ds.lat.data, dask.array.Array) + _check_unchanged(original, ds) + + def test_add_irregularly_spaced_bounds_do_not_overlap() -> None: # Test that added bounds with irregular spacing do not overlap. ds = airds