Source code for windkit.xarray_structures.wsbin

# (c) 2026 DTU Wind Energy
"""
Routines for working with the wsbin coordinate.
"""

__all__ = [
    "create_wsbin_coords",
]

import numpy as np
import xarray as xr

from .metadata import _WSBIN_COORD_ATTRS

_WSBIN_DIM = "wsbin"
_WSBIN_CENTER_COORD = "wsbin"
_WSBIN_CEIL_COORD = "wsceil"
_WSBIN_FLOOR_COORD = "wsfloor"


[docs] def create_wsbin_coords(bins=40, width=1.0, start=0.0): """Create wind speed bins coordinates. Create a data array with the wind speed bins, ceiling and floor. Parameters ---------- bins : int, array_like Wind speed bins. Either a single integer number of bins, or an array of float bin edges. width : float, optional Width of the bins, by default 1.0. Only used if bins is an integer. start : float, optional Starting value of the bins, by default 0.0. Only used if bins is an integer. Returns ------- xarray.DataArray Data array with wind speed bins and center, ceiling, and floor coordinates. """ # Check if bins is an integer or a numpy.ndarray if isinstance(bins, (int, np.integer)): if bins <= 0: raise ValueError("'bins' must be a positive integer") if width <= 0.0: raise ValueError("'width' must be a positive float") if start < 0.0: raise ValueError("'start' must be zero or a positive float") bins = np.linspace(start, start + bins * width, bins + 1) bins = np.asarray(bins, dtype="float64") if bins.ndim != 1: raise ValueError( "'bins' must be an integer or a 1D numpy.ndarray. Got: %sD array." % bins.ndim ) # Check if bins are sorted if not np.all(np.diff(bins) > 0): raise ValueError("'bins' must be sorted in ascending order") # Check if bins are positive if not np.all(bins >= 0): raise ValueError("'bins' must be positive") # Check if bins are finite if not np.all(np.isfinite(bins)): raise ValueError("'bins' must be finite") center = 0.5 * (bins[:-1] + bins[1:]) ceils = bins[1:] floors = bins[:-1] da = xr.DataArray( center, dims=_WSBIN_DIM, coords={ _WSBIN_CENTER_COORD: ((_WSBIN_DIM,), center), _WSBIN_CEIL_COORD: ((_WSBIN_DIM,), ceils), _WSBIN_FLOOR_COORD: ((_WSBIN_DIM,), floors), }, attrs={ **_WSBIN_COORD_ATTRS[_WSBIN_DIM], }, ) da[_WSBIN_CEIL_COORD].attrs = {**_WSBIN_COORD_ATTRS[_WSBIN_CEIL_COORD]} da[_WSBIN_FLOOR_COORD].attrs = {**_WSBIN_COORD_ATTRS[_WSBIN_FLOOR_COORD]} da[_WSBIN_CENTER_COORD].attrs = {**_WSBIN_COORD_ATTRS[_WSBIN_CENTER_COORD]} return da