Skip to content

Commit e1370ef

Browse files
authored
Fixes #134: add xr.Dataset as input type for appropriate modules (#854)
* Fixes #134: add xr.Dataset as input type for appropriate modules Add transparent Dataset support via two decorators in a new dataset_support module. Single-input functions (slope, aspect, curvature, hillshade, focal.mean, 10 classify functions, 3 proximity functions) iterate over data_vars and return a Dataset. Multi-input functions (10 multispectral indices) accept a Dataset with band-name kwargs. zonal.stats merges per-variable DataFrames with prefixed columns. Includes 18 new tests. * Update documentation for xr.Dataset support Update docstrings, prose docs, notebooks, README, and changelog to reflect that most public functions now accept xr.Dataset in addition to xr.DataArray.
1 parent 623eba0 commit e1370ef

File tree

19 files changed

+613
-113
lines changed

19 files changed

+613
-113
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
-----------
33

44

5+
### Version 0.5.3 (unreleased)
6+
- Fixes #134: Add `xr.Dataset` as input type for appropriate modules.
7+
Most public functions now transparently accept `xr.Dataset` in addition
8+
to `xr.DataArray`. Single-input functions (slope, aspect, curvature,
9+
hillshade, focal.mean, all classification functions, proximity/allocation/
10+
direction) iterate over data variables and return a Dataset. Multi-input
11+
functions (all multispectral indices) accept a Dataset with band-name
12+
keyword arguments. `zonal.stats` computes per-variable statistics and
13+
returns a merged DataFrame with prefixed columns.
14+
15+
516
### Version 0.5.2 - 2025-12-18
617
- Make dask optional (#835)
718
- Fixes 832 update citation info in readme (#834)

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,21 @@ my_dataarray = xr.DataArray(...)
258258
hillshaded_dataarray = hillshade(my_dataarray)
259259
```
260260

261+
##### Dataset Support
262+
263+
Most functions also accept an `xr.Dataset`. Single-input functions (surface, classification, focal, proximity) apply the operation to each data variable and return a Dataset. Multi-input functions (multispectral indices) accept a Dataset with band-name keyword arguments.
264+
265+
```python
266+
# Single-input: returns a Dataset with slope computed for each variable
267+
slope_ds = slope(my_dataset)
268+
269+
# Multi-input: map Dataset variables to band parameters
270+
ndvi_result = ndvi(my_dataset, nir='band_5', red='band_4')
271+
272+
# Zonal stats: columns prefixed by variable name
273+
stats_df = zonal.stats(zones, my_dataset) # → elevation_mean, temperature_mean, ...
274+
```
275+
261276
Check out the user guide [here](/examples/user_guide/).
262277

263278
------

docs/source/getting_started/usage.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,27 @@ Basic Pattern
1515
my_dataarray = xr.DataArray(...)
1616
hillshaded_dataarray = hillshade(my_dataarray)
1717
18+
19+
Dataset Support
20+
================
21+
22+
Most functions also accept an ``xr.Dataset``. Single-input functions apply
23+
the operation to each data variable and return a Dataset. Multi-input
24+
functions (multispectral indices) accept a Dataset with band-name keyword
25+
arguments.
26+
27+
.. code-block:: python
28+
29+
from xrspatial import slope
30+
from xrspatial.multispectral import ndvi
31+
32+
# Single-input: returns a Dataset with slope for each variable
33+
slope_ds = slope(my_dataset)
34+
35+
# Multi-input: map Dataset variables to band parameters
36+
ndvi_result = ndvi(my_dataset, nir='band_5', red='band_4')
37+
38+
1839
Check out the user guide `here <https://github.com/xarray-contrib/xarray-spatial/blob/master/examples/user_guide>`_.
1940

2041

docs/source/user_guide/data_types.rst

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,49 @@ Best Practices
227227
combined = (ndvi_result + savi_result) / 2
228228
229229
230+
Dataset Input Support
231+
=====================
232+
233+
Most functions accept an ``xr.Dataset`` in addition to ``xr.DataArray``.
234+
When a Dataset is passed, the operation is applied to each data variable
235+
independently and the result is returned as a new Dataset.
236+
237+
Single-input functions (surface, classification, focal, proximity):
238+
239+
.. code-block:: python
240+
241+
from xrspatial import slope
242+
243+
# Apply slope to every variable in the Dataset
244+
slope_ds = slope(my_dataset)
245+
# Returns an xr.Dataset with the same variable names
246+
247+
Multi-input functions (multispectral indices) accept a Dataset with keyword
248+
arguments that map band aliases to variable names:
249+
250+
.. code-block:: python
251+
252+
from xrspatial.multispectral import ndvi
253+
254+
# Map Dataset variables to band parameters
255+
ndvi_result = ndvi(my_dataset, nir='band_5', red='band_4')
256+
257+
``zonal.stats`` also accepts a Dataset for the ``values`` parameter, returning
258+
a merged DataFrame with columns prefixed by variable name:
259+
260+
.. code-block:: python
261+
262+
from xrspatial.zonal import stats
263+
264+
df = stats(zones, my_dataset)
265+
# Columns: zone, elevation_mean, elevation_max, ..., temperature_mean, ...
266+
267+
230268
Summary
231269
=======
232270

233-
- **Input**: xarray-spatial accepts any numeric data type (int or float)
271+
- **Input**: xarray-spatial accepts any numeric data type (int or float), as either ``xr.DataArray`` or ``xr.Dataset``
234272
- **Processing**: All calculations are performed in float32 precision
235-
- **Output**: Results are returned as float32 DataArrays
273+
- **Output**: Results are returned as float32 DataArrays (or a Dataset of float32 DataArrays when a Dataset is passed)
236274
- **Consistency**: This behavior is consistent across NumPy, Dask, and CuPy backends
237275
- **Rationale**: Float32 provides adequate precision for geospatial analysis while using half the memory of float64

docs/source/user_guide/multispectral.ipynb

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,7 @@
1010
{
1111
"cell_type": "markdown",
1212
"metadata": {},
13-
"source": [
14-
"Xarray-spatial's Multispectral tools provide a range of functions pertaining to remote sensing data such as satellite imagery. A range of functions are available to calculate various vegetation and environmental parameters from the range of band data available for an area. These functions accept and output data in the form of xarray.DataArray rasters.\n",
15-
"\n",
16-
"- [Generate terrain](#Generate-Terrain-Data) \n",
17-
"- [Bump](#Bump) \n",
18-
"- [NDVI](#NDVI) "
19-
]
13+
"source": "Xarray-spatial's Multispectral tools provide a range of functions pertaining to remote sensing data such as satellite imagery. A range of functions are available to calculate various vegetation and environmental parameters from the range of band data available for an area. These functions accept and output data in the form of xarray.DataArray rasters. They also accept an xr.Dataset as the first argument with band-name keyword arguments to map variables to bands (e.g. `ndvi(ds, nir='B5', red='B4')`).\n\n- [Generate terrain](#Generate-Terrain-Data) \n- [Bump](#Bump) \n- [NDVI](#NDVI) "
2014
},
2115
{
2216
"cell_type": "markdown",
@@ -64,11 +58,7 @@
6458
{
6559
"cell_type": "markdown",
6660
"metadata": {},
67-
"source": [
68-
"The following functions apply to image data with bands in different parts of the UV/Visible/IR spectrum (multispectral), so we'll bring in some multispectral satellite image data to work with.\n",
69-
"\n",
70-
"Below, we loaded all of the images and transformed them into the form of an xarray DataArray to use in the Xarray-spatial functions."
71-
]
61+
"source": "The following functions apply to image data with bands in different parts of the UV/Visible/IR spectrum (multispectral), so we'll bring in some multispectral satellite image data to work with.\n\nBelow, we loaded all of the images and transformed them into the form of an xarray DataArray to use in the Xarray-spatial functions. Note: you can also load bands into an `xr.Dataset` and pass it directly to multispectral functions with band-name keyword arguments (e.g. `ndvi(ds, nir='nir', red='red')`)."
7262
},
7363
{
7464
"cell_type": "code",
@@ -1408,4 +1398,4 @@
14081398
},
14091399
"nbformat": 4,
14101400
"nbformat_minor": 2
1411-
}
1401+
}

docs/source/user_guide/surface.ipynb

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,7 @@
1010
{
1111
"cell_type": "markdown",
1212
"metadata": {},
13-
"source": [
14-
"With the Surface tools, you can quantify and visualize a terrain landform represented by a digital elevation model.\n",
15-
"\n",
16-
"Starting with a raster elevation surface that represented as an Xarray DataArray, these tools help you in identifying some specific patterns that were not readily apparent in the original surface. Return of each function is also an Xarray DataArray.\n",
17-
"\n",
18-
"- [Hillshade](#Hillshade): Creates a shaded relief from a surface raster by considering the illumination source angle and shadows.\n",
19-
"- [Slope](#Slope): Identifies the slope from each cell of a raster.\n",
20-
"- [Curvature](#Curvature): Calculates the curvature of a raster surface.\n",
21-
"- [Aspect](#Aspect): Derives the aspect from each cell of a raster surface.\n",
22-
"- [Viewshed](#Viewshed): Determines visible locations in the input raster surface from a viewpoint with some optional observer features."
23-
]
13+
"source": "With the Surface tools, you can quantify and visualize a terrain landform represented by a digital elevation model.\n\nStarting with a raster elevation surface that represented as an Xarray DataArray (or an Xarray Dataset containing multiple elevation variables), these tools help you in identifying some specific patterns that were not readily apparent in the original surface. When a DataArray is passed, the return is a DataArray. When a Dataset is passed, the function is applied to each variable independently and the return is a Dataset.\n\n- [Hillshade](#Hillshade): Creates a shaded relief from a surface raster by considering the illumination source angle and shadows.\n- [Slope](#Slope): Identifies the slope from each cell of a raster.\n- [Curvature](#Curvature): Calculates the curvature of a raster surface.\n- [Aspect](#Aspect): Derives the aspect from each cell of a raster surface.\n- [Viewshed](#Viewshed): Determines visible locations in the input raster surface from a viewpoint with some optional observer features."
2414
},
2515
{
2616
"cell_type": "markdown",
@@ -932,4 +922,4 @@
932922
},
933923
"nbformat": 4,
934924
"nbformat_minor": 2
935-
}
925+
}

examples/user_guide/1_Surface.ipynb

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,7 @@
33
{
44
"cell_type": "markdown",
55
"metadata": {},
6-
"source": [
7-
"# Xarray-spatial\n",
8-
"### User Guide: Surface tools\n",
9-
"-----\n",
10-
"With the Surface tools, you can quantify and visualize a terrain landform represented by a digital elevation model.\n",
11-
"\n",
12-
"Starting with a raster elevation surface, represented as an Xarray DataArray, these tools can help you identify some specific patterns that may not be readily apparent in the original surface. The return of each function is also an Xarray DataArray.\n",
13-
"\n",
14-
"[Hillshade](#Hillshade): Creates a shaded relief from a surface raster by considering the illumination source angle and shadows.\n",
15-
"\n",
16-
"[Slope](#Slope): Identifies the slope for each cell of a raster.\n",
17-
"\n",
18-
"[Curvature](#Curvature): Calculates the curvature of a raster surface.\n",
19-
"\n",
20-
"[Aspect](#Aspect): Derives the aspect for each cell of a raster surface.\n",
21-
"\n",
22-
"[Viewshed](#Viewshed): Determines visible locations in the input raster surface from a viewpoint with an optional observer height.\n",
23-
"\n",
24-
"-----------\n"
25-
]
6+
"source": "# Xarray-spatial\n### User Guide: Surface tools\n-----\nWith the Surface tools, you can quantify and visualize a terrain landform represented by a digital elevation model.\n\nStarting with a raster elevation surface, represented as an Xarray DataArray (or an Xarray Dataset containing multiple elevation variables), these tools can help you identify some specific patterns that may not be readily apparent in the original surface. When a DataArray is passed, the return is a DataArray. When a Dataset is passed, the function is applied to each variable independently and the return is a Dataset.\n\n[Hillshade](#Hillshade): Creates a shaded relief from a surface raster by considering the illumination source angle and shadows.\n\n[Slope](#Slope): Identifies the slope for each cell of a raster.\n\n[Curvature](#Curvature): Calculates the curvature of a raster surface.\n\n[Aspect](#Aspect): Derives the aspect for each cell of a raster surface.\n\n[Viewshed](#Viewshed): Determines visible locations in the input raster surface from a viewpoint with an optional observer height.\n\n-----------\n"
267
},
278
{
289
"cell_type": "markdown",
@@ -524,4 +505,4 @@
524505
},
525506
"nbformat": 4,
526507
"nbformat_minor": 4
527-
}
508+
}

examples/user_guide/6_Remote_Sensing.ipynb

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,7 @@
33
{
44
"cell_type": "markdown",
55
"metadata": {},
6-
"source": [
7-
"# Xarray-spatial\n",
8-
"### User Guide: Remote Sensing tools\n",
9-
"-----\n",
10-
"\n",
11-
"Xarray-spatial's Remote Sensing tools provide a range of functions pertaining to remote sensing data such as satellite imagery. A range of functions are available to calculate various vegetation and environmental parameters from the range of band data available for an area. These functions accept and output data in the form of xarray.DataArray rasters.\n",
12-
"\n",
13-
"[True Color](#True-Color) \n",
14-
"[Vegetation Index](#Vegetation-Index): [NDVI](#NDVI), [SAVI](#SAVI), [ARVI](#ARVI), [EVI](#EVI) \n",
15-
"[Green Chlorophyll Index - GCI](#Green-Chlorophyll-Index-(GCI)) \n",
16-
"[Normalized Burn Ratio](#Normalized-Burn-Ratio): [NBR](#NBR), [NBR2](#NBR2) \n",
17-
"[Normalized Difference Moisture Index - NDMI](#Normalized-Difference-Moisture-Index-(NDMI)) \n",
18-
"[Structure Insensitive Pigment Index - SIPI](#Structure-Insensitive-Pigment-Index-(SIPI)) \n",
19-
"[Enhanced Built-Up and Bareness Index - EBBI](#Enhanced-Built-Up-and-Bareness-Index-(EBBI)) \n",
20-
"[Bump Mapping](#Bump-Mapping) \n",
21-
"\n",
22-
"-----------\n"
23-
]
6+
"source": "# Xarray-spatial\n### User Guide: Remote Sensing tools\n-----\n\nXarray-spatial's Remote Sensing tools provide a range of functions pertaining to remote sensing data such as satellite imagery. A range of functions are available to calculate various vegetation and environmental parameters from the range of band data available for an area. These functions accept and output data in the form of xarray.DataArray rasters. They also accept an xr.Dataset as the first argument with band-name keyword arguments to map variables to bands (e.g. `ndvi(ds, nir='B5', red='B4')`).\n\n[True Color](#True-Color) \n[Vegetation Index](#Vegetation-Index): [NDVI](#NDVI), [SAVI](#SAVI), [ARVI](#ARVI), [EVI](#EVI) \n[Green Chlorophyll Index - GCI](#Green-Chlorophyll-Index-(GCI)) \n[Normalized Burn Ratio](#Normalized-Burn-Ratio): [NBR](#NBR), [NBR2](#NBR2) \n[Normalized Difference Moisture Index - NDMI](#Normalized-Difference-Moisture-Index-(NDMI)) \n[Structure Insensitive Pigment Index - SIPI](#Structure-Insensitive-Pigment-Index-(SIPI)) \n[Enhanced Built-Up and Bareness Index - EBBI](#Enhanced-Built-Up-and-Bareness-Index-(EBBI)) \n[Bump Mapping](#Bump-Mapping) \n\n-----------\n"
247
},
258
{
269
"cell_type": "markdown",
@@ -68,11 +51,7 @@
6851
{
6952
"cell_type": "markdown",
7053
"metadata": {},
71-
"source": [
72-
"The following functions apply to image data with bands in different parts of the UV/Visible/IR spectrum (multispectral), so we'll bring in some multispectral satellite image data to work with.\n",
73-
"\n",
74-
"Below, we loaded all of the images and transformed them into the form of an xarray DataArray to use in the Xarray-spatial functions."
75-
]
54+
"source": "The following functions apply to image data with bands in different parts of the UV/Visible/IR spectrum (multispectral), so we'll bring in some multispectral satellite image data to work with.\n\nBelow, we loaded all of the images and transformed them into the form of an xarray DataArray to use in the Xarray-spatial functions. Note: you can also load bands into an `xr.Dataset` and pass it directly to multispectral functions with band-name keyword arguments (e.g. `ndvi(ds, nir='nir', red='red')`)."
7655
},
7756
{
7857
"cell_type": "code",
@@ -695,4 +674,4 @@
695674
},
696675
"nbformat": 4,
697676
"nbformat_minor": 4
698-
}
677+
}

xrspatial/aspect.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from xrspatial.utils import _extract_latlon_coords
2020
from xrspatial.utils import cuda_args
2121
from xrspatial.utils import ngjit
22+
from xrspatial.dataset_support import supports_dataset
2223

2324

2425
def _geodesic_cuda_dims(shape):
@@ -270,6 +271,7 @@ def _run_dask_cupy_geodesic(data, lat_2d, lon_2d, a2, b2, z_factor):
270271
# Public API
271272
# =====================================================================
272273

274+
@supports_dataset
273275
def aspect(agg: xr.DataArray,
274276
name: Optional[str] = 'aspect',
275277
method: str = 'planar',
@@ -296,9 +298,11 @@ def aspect(agg: xr.DataArray,
296298
297299
Parameters
298300
----------
299-
agg : xarray.DataArray
301+
agg : xarray.DataArray or xr.Dataset
300302
2D NumPy, CuPy, or Dask with NumPy-backed xarray DataArray
301303
of elevation values.
304+
If a Dataset is passed, the operation is applied to each
305+
data variable independently.
302306
name : str, default='aspect'
303307
Name of ouput DataArray.
304308
method : str, default='planar'
@@ -313,7 +317,10 @@ def aspect(agg: xr.DataArray,
313317
314318
Returns
315319
-------
316-
aspect_agg : xarray.DataArray of the same type as `agg`
320+
aspect_agg : xarray.DataArray or xr.Dataset
321+
If `agg` is a DataArray, returns a DataArray of the same type.
322+
If `agg` is a Dataset, returns a Dataset with aspect computed
323+
for each data variable.
317324
2D aggregate array of calculated aspect values.
318325
All other input attributes are preserved.
319326

0 commit comments

Comments
 (0)