Core nD array interpolation routine. The first half arrays in `coords` are original coordinates, the other half are destination coordinates.
(
data: np.ndarray,
*coords: np.ndarray,
interp_func: Interpolator | InterpCallable,
interp_kwargs,
result_coord_core_dims: list[tuple[Hashable, ...]],
)
| 784 | |
| 785 | |
| 786 | def _interpnd( |
| 787 | data: np.ndarray, |
| 788 | *coords: np.ndarray, |
| 789 | interp_func: Interpolator | InterpCallable, |
| 790 | interp_kwargs, |
| 791 | result_coord_core_dims: list[tuple[Hashable, ...]], |
| 792 | ) -> np.ndarray: |
| 793 | """ |
| 794 | Core nD array interpolation routine. |
| 795 | The first half arrays in `coords` are original coordinates, |
| 796 | the other half are destination coordinates. |
| 797 | """ |
| 798 | n_x = len(coords) // 2 |
| 799 | ndim = data.ndim |
| 800 | nconst = ndim - n_x |
| 801 | |
| 802 | # Convert everything to Variables, since that makes applying |
| 803 | # `_localize` and `_floatize_x` much easier |
| 804 | x = [ |
| 805 | Variable([f"dim_{nconst + dim}"], _x, fastpath=True) |
| 806 | for dim, _x in enumerate(coords[:n_x]) |
| 807 | ] |
| 808 | new_x = list( |
| 809 | broadcast_variables( |
| 810 | *( |
| 811 | Variable(dims, _x, fastpath=True) |
| 812 | for dims, _x in zip(result_coord_core_dims, coords[n_x:], strict=True) |
| 813 | ) |
| 814 | ) |
| 815 | ) |
| 816 | var = Variable([f"dim_{dim}" for dim in range(ndim)], data, fastpath=True) |
| 817 | |
| 818 | if interp_kwargs.get("method") in ["linear", "nearest"]: |
| 819 | indexes_coords = { |
| 820 | _x.dims[0]: (_x, _new_x) for _x, _new_x in zip(x, new_x, strict=True) |
| 821 | } |
| 822 | # simple speed up for the local interpolation |
| 823 | var, indexes_coords = _localize(var, indexes_coords) |
| 824 | x, new_x = tuple( |
| 825 | list(_) |
| 826 | for _ in zip(*(indexes_coords[d] for d in indexes_coords), strict=True) |
| 827 | ) |
| 828 | |
| 829 | x_list, new_x_list = _floatize_x(x, new_x) |
| 830 | |
| 831 | if len(x) == 1: |
| 832 | # TODO: narrow interp_func to interpolator here |
| 833 | return _interp1d(var, x_list, new_x_list, interp_func, interp_kwargs) # type: ignore[arg-type] |
| 834 | |
| 835 | # move the interpolation axes to the start position |
| 836 | data = transpose(var._data, range(-len(x), var.ndim - len(x))) |
| 837 | |
| 838 | # stack new_x to 1 vector, with reshape |
| 839 | xi = stack([ravel(x1.data) for x1 in new_x_list], axis=-1) |
| 840 | rslt: np.ndarray = interp_func(x_list, data, xi, **interp_kwargs) # type: ignore[assignment] |
| 841 | # move back the interpolation axes to the last position |
| 842 | rslt = transpose(rslt, range(-rslt.ndim + 1, 1)) |
| 843 | return reshape(rslt, rslt.shape[:-1] + new_x[0].shape) |
nothing calls this directly
no test coverage detected
searching dependent graphs…