Source code for hydromt_fiat.gis.raster
"""Raster functions."""
import logging
import math
import numpy as np
import xarray as xr
from affine import Affine
__all__ = ["expand_raster_to_bounds"]
logger = logging.getLogger(f"hydromt.{__name__}")
[docs]
def expand_raster_to_bounds(
ds: xr.Dataset | xr.DataArray,
bbox: tuple[float] | np.ndarray,
) -> xr.Dataset | xr.DataArray:
"""Expand a raster to (beyond) the borders of a bounding box.
When expanded, the new raster will be aligned with the old one.
Parameters
----------
da : xr.DataArray
The input raster dataset.
bounds : tuple[float] | np.ndarray
The bounds to which to expand the raster.
Returns
-------
xr.DataArray
An expanded raster.
"""
logger.info("Checking raster extent versus region bounding box")
# Get some metadata
old_bounds = [round(float(item), 4) for item in ds.raster.bounds]
bounds = list(ds.raster.bounds)
shape = [ds[ds.raster.x_dim].size, ds[ds.raster.y_dim].size]
check = False
for idx in range(4):
if not idx // 2: # Minimum side (xmin, ymin)
side_check = bounds[idx] <= bbox[idx]
sign = -1
else: # Maximum sides (xmax, ymax)
side_check = bounds[idx] >= bbox[idx]
sign = 1
if side_check: # It checks out, so return
continue
check = True
offset = abs(bounds[idx] - bbox[idx])
offset = math.ceil(offset / abs(ds.raster.res[idx % 2]))
bounds[idx] += offset * abs(ds.raster.res[idx % 2]) * sign
shape[idx % 2] += offset
if not check:
return ds
# Some logging
logger.warning("Raster smaller than the region bounding box")
# Metadata for building the geotransform
dx, dy = ds.raster.res
xsign = int(dx / abs(dx))
ysign = int(dy / abs(dy))
# New geotransform
new_transform = Affine(
dx,
ds.raster.rotation,
bounds[(1 - xsign)],
ds.raster.rotation,
dy,
bounds[(1 - ysign) + 1],
)
bounds_repr = [round(float(item), 4) for item in bounds]
logger.info(f"Expanding raster from {old_bounds} to {bounds_repr}")
# Reproject the data to the new transform
ds = ds.raster.reproject(
dst_transform=new_transform,
dst_width=shape[0],
dst_height=shape[1],
method="nearest", # Same resolution and location, so nearest is the way to go
)
return ds