core routine that returns the interpolated variable.
(
var: Variable,
indexes_coords: SourceDest,
*,
method: InterpOptions,
kwargs: dict[str, Any],
)
| 684 | |
| 685 | |
| 686 | def interpolate_variable( |
| 687 | var: Variable, |
| 688 | indexes_coords: SourceDest, |
| 689 | *, |
| 690 | method: InterpOptions, |
| 691 | kwargs: dict[str, Any], |
| 692 | ) -> Variable: |
| 693 | """core routine that returns the interpolated variable.""" |
| 694 | if not indexes_coords: |
| 695 | return var.copy() |
| 696 | |
| 697 | if len(indexes_coords) == 1: |
| 698 | func, kwargs = _get_interpolator(method, vectorizeable_only=True, **kwargs) |
| 699 | else: |
| 700 | func, kwargs = _get_interpolator_nd(method, **kwargs) |
| 701 | |
| 702 | in_coords, result_coords = zip(*(v for v in indexes_coords.values()), strict=True) |
| 703 | |
| 704 | # input coordinates along which we are interpolation are core dimensions |
| 705 | # the corresponding output coordinates may or may not have the same name, |
| 706 | # so `all_in_core_dims` is also `exclude_dims` |
| 707 | all_in_core_dims = set(indexes_coords) |
| 708 | |
| 709 | result_dims = OrderedSet(itertools.chain(*(_.dims for _ in result_coords))) |
| 710 | result_sizes = ChainMap(*(_.sizes for _ in result_coords)) |
| 711 | |
| 712 | # any dimensions on the output that are present on the input, but are not being |
| 713 | # interpolated along are dimensions along which we automatically vectorize. |
| 714 | # Consider the problem in https://github.com/pydata/xarray/issues/6799#issuecomment-2474126217 |
| 715 | # In the following, dimension names are listed out in []. |
| 716 | # # da[time, q, lat, lon].interp(q=bar[lat,lon]). Here `lat`, `lon` |
| 717 | # are input dimensions, present on the output, but are not the coordinates |
| 718 | # we are explicitly interpolating. These are the dimensions along which we vectorize. |
| 719 | # `q` is the only input core dimensions, and changes size (disappears) |
| 720 | # so it is in exclude_dims. |
| 721 | vectorize_dims = (result_dims - all_in_core_dims) & set(var.dims) |
| 722 | |
| 723 | # remove any output broadcast dimensions from the list of core dimensions |
| 724 | output_core_dims = tuple(d for d in result_dims if d not in vectorize_dims) |
| 725 | input_core_dims = ( |
| 726 | # all coordinates on the input that we interpolate along |
| 727 | [tuple(indexes_coords)] |
| 728 | # the input coordinates are always 1D at the moment, so we just need to list out their names |
| 729 | + [tuple(_.dims) for _ in in_coords] |
| 730 | # The last set of inputs are the coordinates we are interpolating to. |
| 731 | + [ |
| 732 | tuple(d for d in coord.dims if d not in vectorize_dims) |
| 733 | for coord in result_coords |
| 734 | ] |
| 735 | ) |
| 736 | output_sizes = {k: result_sizes[k] for k in output_core_dims} |
| 737 | |
| 738 | # scipy.interpolate.interp1d always forces to float. |
| 739 | dtype = float if not issubclass(var.dtype.type, np.inexact) else var.dtype |
| 740 | result = apply_ufunc( |
| 741 | _interpnd, |
| 742 | var, |
| 743 | *in_coords, |
no test coverage detected
searching dependent graphs…