Skip to content

Commit 0e0d88d

Browse files
committed
Add interpolation.map_coordinates
1 parent 4fdf6d4 commit 0e0d88d

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

xarray/core/interpolation.py

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import collections
2+
import itertools
3+
4+
import numpy as np
5+
6+
from .dataarray import DataArray
7+
8+
9+
def map_coordinates(source, target, keep_attrs=False, **kwargs):
10+
"""
11+
Uses ``scipy.ndimage.interpolation.map_coordinates`` to map the
12+
source data array to the given target coordinates using spline
13+
interpolation. Target must consist of numerical coordinates only.
14+
15+
Parameters
16+
------------
17+
source : DataArray
18+
Gridded source data.
19+
target : dict
20+
Target coordinates; mapping from dimension names to coordinate
21+
values to sample at.
22+
keep_attrs : boolean, optional
23+
If True, attributes are copied from source (default is False).
24+
**kwargs
25+
Additional keyword args are passed to
26+
``scipy.ndimage.interpolation.map_coordinates``.
27+
28+
Returns
29+
---------
30+
interpolated : DataArray
31+
Data array with interpolated values. Coordinates and dimensions
32+
are copied from source.
33+
34+
"""
35+
from scipy.interpolate import interp1d
36+
from scipy import ndimage
37+
38+
# Set up the interpolators to map coordinates onto array indices
39+
interpolators = {}
40+
for dim_name in target.keys():
41+
dim = source.coords[dim_name]
42+
if not np.issubdtype(dim.dtype, np.number):
43+
raise ValueError('Only numerical dimensions '
44+
'can be interpolated on.')
45+
try:
46+
interpolators[dim_name] = interp1d(dim, list(range(len(dim))))
47+
except ValueError: # Raised if there is only one entry
48+
# 0 is the only index that exists
49+
interpolators[dim_name] = lambda x: 0
50+
51+
# Set up the array indices on which to interpolate,
52+
# and the final coordinates to apply to the result
53+
indices = collections.OrderedDict()
54+
coords = collections.OrderedDict()
55+
for d in source.dims:
56+
if d not in target.keys():
57+
# Choose all entries from non-interpolated dimensions
58+
indices[d] = list(range(len(source.coords[d])))
59+
coords[d] = source.coords[d]
60+
else:
61+
# Choose selected entries from interpolated dimensions
62+
indices[d] = [interpolators[d](i) for i in target[d]]
63+
coords[d] = target[d]
64+
65+
# Generate array of all coordinates
66+
# Shape should be n(dims) * n(product of all interpolators)
67+
coordinates = np.array(list(zip(
68+
*itertools.product(*[i for i in indices.values()]))
69+
))
70+
71+
interp_array = ndimage.map_coordinates(source.values, coordinates,
72+
**kwargs)
73+
74+
# Reshape the resulting array according to the target coordinates
75+
result_shape = [len(i) for i in indices.values()]
76+
attrs = source.attrs if keep_attrs else None # Copy attrs if asked for
77+
return DataArray(interp_array.reshape(result_shape),
78+
coords=coords, attrs=attrs)

0 commit comments

Comments
 (0)