pydata / xarray

N-D labeled arrays and datasets in Python
https://xarray.dev
Apache License 2.0
3.57k stars 1.07k forks source link

Cannot use documented interp() methods due to "vectorizeable_only" check and kwargs name clash #9049

Closed xxyxxyxyx1 closed 1 week ago

xxyxxyxyx1 commented 4 months ago

What happened?

I would like to use xarray.Dataset.interp() to interpolate data using the scipy "makima" interpolator, scipy.interpolate.Akima1DInterpolator(... method='makima'). It seems to me this is possible according to the documentation here: https://docs.xarray.dev/en/latest/generated/xarray.Dataset.interp.html https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.Akima1DInterpolator.html#scipy.interpolate.Akima1DInterpolator

However, I am not able to do this, I think due to two separate problems: 1) There is a check that only allows "vectorizeable interpolators" for one-dimensional interpolation, the motivation for which I do not understand. This makes 'akima', 'spline', and other documented interp methods unavailable.

2) The way kwargs are passed to the scipy interpolator results in multiple kwargs named "method", making specifically "makima" (modified akima) unavailable.

What did you expect to happen?

I expect interpolation to happen.

Minimal Complete Verifiable Example

## create a Dataset and new x array for interpolation
import numpy as np
import xarray as xr
x = np.arange(0, 5, 0.05)
x_dense = np.arange(0, 5, 0.01)
y = np.sin(x)
ds = xr.Dataset({'y': (('x'), y)}, coords={'x': x})

## do a cubic interpolation. this works as expected
ds_interp_cubic = ds.interp(x=x_dense, method='cubic')

## attempt akima interpolation. this fails.
ds_interp_akima = ds.interp(x=x_dense, method='akima')

## attempt makima interpolation. this also fails.
ds_interp_makima = ds.interp(x=x_dense, method='akima', kwargs={'method': 'makima'})

MVCE confirmation

Relevant log output

## For the akima failure, this is the ipython traceback:

File /opt/homebrew/Caskroom/miniforge/base/envs/npaccel-larch/lib/python3.11/site-packages/xarray/core/dataset.py:4003, in Dataset.interp(self, coords, method, assume_sorted, kwargs, method_non_numeric, **coords_kwargs)
   4000 if dtype_kind in "uifc":
   4001     # For normal number types do the interpolation:
   4002     var_indexers = {k: v for k, v in use_indexers.items() if k in var.dims}
-> 4003     variables[name] = missing.interp(var, var_indexers, method, **kwargs)
   4004 elif dtype_kind in "ObU" and (use_indexers.keys() & var.dims):
   4005     # For types that we do not understand do stepwise
   4006     # interpolation to avoid modifying the elements.
   (...)
   4009     # this loop there might be some duplicate code that slows it
   4010     # down, therefore collect these signals and run it later:
   4011     reindex = True

File /opt/homebrew/Caskroom/miniforge/base/envs/npaccel-larch/lib/python3.11/site-packages/xarray/core/missing.py:632, in interp(var, indexes_coords, method, **kwargs)
    630 original_dims = broadcast_dims + dims
    631 new_dims = broadcast_dims + list(destination[0].dims)
--> 632 interped = interp_func(
    633     var.transpose(*original_dims).data, x, destination, method, kwargs
    634 )
    636 result = Variable(new_dims, interped, attrs=var.attrs, fastpath=True)
    638 # dimension of the output array

File /opt/homebrew/Caskroom/miniforge/base/envs/npaccel-larch/lib/python3.11/site-packages/xarray/core/missing.py:687, in interp_func(var, x, new_x, method, kwargs)
    684     return var.copy()
    686 if len(x) == 1:
--> 687     func, kwargs = _get_interpolator(method, vectorizeable_only=True, **kwargs)
    688 else:
    689     func, kwargs = _get_interpolator_nd(method, **kwargs)

File /opt/homebrew/Caskroom/miniforge/base/envs/npaccel-larch/lib/python3.11/site-packages/xarray/core/missing.py:494, in _get_interpolator(method, vectorizeable_only, **kwargs)
    492     interp_class = ScipyInterpolator
    493 elif vectorizeable_only:
--> 494     raise ValueError(
    495         f"{method} is not a vectorizeable interpolator. "
    496         f"Available methods are {interp1d_methods}"
    497     )
    498 elif method == "barycentric":
    499     interp_class = _import_interpolant("BarycentricInterpolator", method)

ValueError: akima is not a vectorizeable interpolator. Available methods are ('linear', 'nearest', 'zero', 'slinear', 'quadratic', 'cubic', 'polynomial')

## for the makima failure, this is the ipython traceback:

/opt/homebrew/Caskroom/miniforge/base/envs/npaccel-larch/lib/python3.11/site-packages/xarray/core/dataset.py in ?(self, coords, method, assume
_sorted, kwargs, method_non_numeric, **coords_kwargs)
   3999             dtype_kind = var.dtype.kind
   4000             if dtype_kind in "uifc":
   4001                 # For normal number types do the interpolation:
   4002                 var_indexers = {k: v for k, v in use_indexers.items() if k in var.dims}
-> 4003                 variables[name] = missing.interp(var, var_indexers, method, **kwargs)
   4004             elif dtype_kind in "ObU" and (use_indexers.keys() & var.dims):
   4005                 # For types that we do not understand do stepwise
   4006                 # interpolation to avoid modifying the elements.

TypeError: interp() got multiple values for argument 'method'

Anything else we need to know?

No response

Environment

INSTALLED VERSIONS ------------------ commit: None python: 3.11.6 | packaged by conda-forge | (main, Oct 3 2023, 10:37:07) [Clang 15.0.7 ] python-bits: 64 OS: Darwin OS-release: 23.5.0 machine: arm64 processor: arm byteorder: little LC_ALL: en_US.UTF-8 LANG: en_US.UTF-8 LOCALE: ('en_US', 'UTF-8') libhdf5: 1.14.3 libnetcdf: None xarray: 2024.3.0 pandas: 2.2.2 numpy: 1.26.4 scipy: 1.13.0 netCDF4: None pydap: None h5netcdf: None h5py: 3.11.0 Nio: None zarr: None cftime: None nc_time_axis: None iris: None bottleneck: None dask: None distributed: None matplotlib: 3.8.4 cartopy: None seaborn: None numbagg: None fsspec: 2024.3.1 cupy: None pint: 0.23 sparse: None flox: 0.9.6 numpy_groupies: 0.11.1 setuptools: 69.5.1 pip: 24.0 conda: None pytest: None mypy: None IPython: 8.22.2 sphinx: None
welcome[bot] commented 4 months ago

Thanks for opening your first issue here at xarray! Be sure to follow the issue template! If you have an idea for a solution, we would really welcome a Pull Request with proposed changes. See the Contributing Guide for more. It may take us a while to respond here, but we really value your contribution. Contributors like you help make xarray better. Thank you!

dcherian commented 4 months ago

We need help with this: https://github.com/pydata/xarray/issues/7704

There is a check that only allows "vectorizeable interpolators" for one-dimensional interpolation,

In that past these interpolators required 1D input. I think this has changed recently and we have not adapted.

Are you able to help?

xxyxxyxyx1 commented 4 months ago

Thank you for responding. I'm sorry to say that I'm probably too amateur to help at this time. I haven't used python much beyond making figures, and I have not used git. But I plan to learn more when I've got bandwidth.

If someone else is able to address this soon, they should. If the problem hasn't been addressed in a few months, perhaps I will be able to give it a go.