Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fit bounding box to coarser resolution #2793

Open
davidbrochart opened this issue Feb 28, 2019 · 2 comments
Open

Fit bounding box to coarser resolution #2793

davidbrochart opened this issue Feb 28, 2019 · 2 comments

Comments

@davidbrochart
Copy link
Contributor

davidbrochart commented Feb 28, 2019

When using coarsen, we often need to align the original DataArray with the coarser coordinates. For instance:

import xarray as xr
import numpy as np

da = xr.DataArray(np.arange(4*4).reshape(4, 4), coords=[np.arange(4, 0, -1) + 0.5, np.arange(4) + 0.5], dims=['lat', 'lon'])
# <xarray.DataArray (lat: 4, lon: 4)>
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11],
#        [12, 13, 14, 15]])
# Coordinates:
#   * lat      (lat) float64 4.5 3.5 2.5 1.5
#   * lon      (lon) float64 0.5 1.5 2.5 3.5

da.coarsen(lat=2, lon=2).mean()
# <xarray.DataArray (lat: 2, lon: 2)>
# array([[ 2.5,  4.5],
#        [10.5, 12.5]])
# Coordinates:
#   * lat      (lat) float64 4.0 2.0
#   * lon      (lon) float64 1.0 3.0

But if the coarser coordinates are aligned like:

lat: ... 5 3 1 ...
lon: ... 1 3 5 ...

Then directly applying coarsen will not work (here on the lat dimension). The following function extends the original DataArray so that it is aligned with the coarser coordinates:

def adjust_bbox(da, dims):
    """Adjust the bounding box of a DaskArray to a coarser resolution.

    Args:
        da: the DaskArray to adjust.
        dims: a dictionary where keys are the name of the dimensions on which to adjust, and the values are of the form [unsigned_coarse_resolution, signed_original_resolution]
    Returns:
        The DataArray bounding box adjusted to the coarser resolution.
    """
    coords = {}
    for k, v in dims.items():
        every, step = v
        offset = step / 2
        dim0 = da[k].values[0] - offset
        dim1 = da[k].values[-1] + offset
        if step < 0: # decreasing coordinate
            dim0 = dim0 + (every - dim0 % every) % every
            dim1 = dim1 - dim1 % every
        else: # increasing coordinate
            dim0 = dim0 - dim0 % every
            dim1 = dim1 + (every - dim1 % every) % every
        coord0 = np.arange(dim0+offset, da[k].values[0]-offset, step)
        coord1 = da[k].values
        coord2 = np.arange(da[k].values[-1]+step, dim1, step)
        coord = np.hstack((coord0, coord1, coord2))
        coords[k] = coord
    return da.reindex(**coords).fillna(0)

da = adjust_bbox(da, {'lat': (2, -1), 'lon': (2, 1)})
# <xarray.DataArray (lat: 6, lon: 4)>
# array([[ 0.,  0.,  0.,  0.],
#        [ 0.,  1.,  2.,  3.],
#        [ 4.,  5.,  6.,  7.],
#        [ 8.,  9., 10., 11.],
#        [12., 13., 14., 15.],
#        [ 0.,  0.,  0.,  0.]])
# Coordinates:
#   * lat      (lat) float64 5.5 4.5 3.5 2.5 1.5 0.5
#   * lon      (lon) float64 0.5 1.5 2.5 3.5

da.coarsen(lat=2, lon=2).mean()
# <xarray.DataArray (lat: 3, lon: 2)>
# array([[0.25, 1.25],
#        [6.5 , 8.5 ],
#        [6.25, 7.25]])
# Coordinates:
#   * lat      (lat) float64 5.0 3.0 1.0
#   * lon      (lon) float64 1.0 3.0

Now coarsen gives the right result. But adjust_bbox is rather complicated and specific to this use case (evenly spaced coordinate points...). Do you know of a better/more general way of doing it?

@shoyer
Copy link
Member

shoyer commented Mar 4, 2019

We have a bit of logic vaguely like this inside xarray's plotting methods:

def _infer_interval_breaks(coord, axis=0, check_monotonic=False):

This feels a padding operation. I don't think we have an equivalent of np.pad in xarray but that would probably be a reasonable addition.

@rabernat
Copy link
Contributor

I feel like the right way to solve this is to be able to explicitly use cell bounds in selecting and aligning (see #1475).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants