Source code for windkit.xarray_structures.sector
# (c) 2026 DTU Wind Energy
"""
Routines for working with the sector coordinate.
"""
__all__ = [
"create_sector_coords",
]
import numpy as np
import xarray as xr
from .metadata import _SECTOR_COORD_ATTRS
_SECTOR_DIM = "sector"
_SECTOR_CENTER_COORD = "sector"
_SECTOR_CEIL_COORD = "sector_ceil"
_SECTOR_FLOOR_COORD = "sector_floor"
[docs]
def create_sector_coords(bins=12, start="infer"):
"""Create wind sector coordinate as a data array.
The data array contains the sector, the sector ceiling and the
sector floor. The sector width is 360 / bins if bins is an integer.
Parameters
----------
bins : int, array_like
Number of bins or an array of bin edges. If bins is an integer,
the width and start parameters are used to create the bin edges.
If bins is an array, it must be sorted in ascending order and span the
negative and positive directions to give the proper center, ceiling,
and floor values for the sector. All values are made positive
by taking the modulo 360 after calculating the center, ceiling, and floor.
start : float, optional
Starting value of the bins, by default "infer", which, if bins is an integer,
sets the start to -360/bins/2.0. If bins is an array, start is ignored.
Returns
-------
xarray.DataArray
Data array with sector coordinates, ceiling and floor.
"""
# 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 start == "infer":
start = -360 / bins / 2.0
start = float(start)
bins = np.linspace(start, start + 360, 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")
center = 0.5 * (bins[:-1] + bins[1:])
ceils = bins[1:]
floors = bins[:-1]
# modulo to 360
center = np.mod(center, 360)
ceils = np.mod(ceils, 360)
floors = np.mod(floors, 360)
da = xr.DataArray(
center,
dims=_SECTOR_DIM,
coords={
_SECTOR_CENTER_COORD: ((_SECTOR_DIM,), center),
_SECTOR_CEIL_COORD: ((_SECTOR_DIM,), ceils),
_SECTOR_FLOOR_COORD: ((_SECTOR_DIM,), floors),
},
attrs={
**_SECTOR_COORD_ATTRS[_SECTOR_DIM],
},
)
da[_SECTOR_CEIL_COORD].attrs = {**_SECTOR_COORD_ATTRS[_SECTOR_CEIL_COORD]}
da[_SECTOR_FLOOR_COORD].attrs = {**_SECTOR_COORD_ATTRS[_SECTOR_FLOOR_COORD]}
da[_SECTOR_CENTER_COORD].attrs = {**_SECTOR_COORD_ATTRS[_SECTOR_CENTER_COORD]}
return da