From 992ac213994cd04222a313c0197acf790a2533ba Mon Sep 17 00:00:00 2001 From: "Noah D. Brenowitz" Date: Sat, 24 Aug 2019 13:49:08 -0700 Subject: [PATCH 1/3] Begin work on 1->ND interpolation Solves #3252 --- xarray/tests/test_interp.py | 50 +++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/xarray/tests/test_interp.py b/xarray/tests/test_interp.py index b9dc9a71acc..3f80940612a 100644 --- a/xarray/tests/test_interp.py +++ b/xarray/tests/test_interp.py @@ -662,3 +662,53 @@ def test_datetime_interp_noerror(): coords={"time": pd.date_range("01-01-2001", periods=50, freq="H")}, ) a.interp(x=xi, time=xi.time) # should not raise an error + + +def interp_1d(data, dim, vals): + selectors = {dim: vals} + + old_coord = data[dim] + + lower = data.sel(**selectors, method='ffill').drop(dim) + upper = data.sel(**selectors, method='bfill').drop(dim) + lower_x = data[dim].sel(**selectors, method='ffill').drop(dim) + upper_x = data[dim].sel(**selectors, method='bfill').drop(dim) + + new_x = lower[dim] + weight = np.abs(new_x - lower_x)/np.abs(upper_x-lower_x) + ans = lower * (1-weight) + upper * weight + return ans + + +@pytest.mark.parametrize('dim',[ + 'x', 'y' +]) +def test_new_interp(dim): + + data = xr.DataArray(np.arange(10), dims=[dim]).assign_coords({dim: np.arange(10)}) + new_x = np.arange(9) + .5 + ans = interp_1d(data, dim, new_x) + np.testing.assert_allclose(new_x, ans.values) + + +def test_interp_1d_nd_targ(): + + data = xr.DataArray(np.arange(10), dims=['x'], coords={'x': np.arange(10)}) + new_x_2d = xr.DataArray(np.tile(np.r_[:10], (3, 1)), dims=['y', 'x']) + ans = interp_1d(data, 'x', new_x_2d) + np.testing.assert_allclose(new_x_2d, ans.values) + + +def test_sel_nd(): + npdata = np.tile(np.arange(10), (5, 1)) + data = xr.DataArray(npdata, dims=['y', 'x'], + coords={'x': np.r_[:10], 'y': np.r_[:5]}) + idx = xr.DataArray(npdata, dims=['z', 'x']) + + ans = data.sel(x=idx, method='bfill') + assert set(ans.dims) == {'z', 'y', 'x'} + print(ans) + + + + From a0e23148aec490c7abf9451b1eb5f00e10b3281c Mon Sep 17 00:00:00 2001 From: "Noah D. Brenowitz" Date: Sat, 24 Aug 2019 14:13:09 -0700 Subject: [PATCH 2/3] Implement linear interpolation The tests cover: 1. index is halfway between coordinates 2. index is the same as old coordinates 3. ND index --- xarray/tests/test_interp.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/xarray/tests/test_interp.py b/xarray/tests/test_interp.py index 3f80940612a..1779dd6f42c 100644 --- a/xarray/tests/test_interp.py +++ b/xarray/tests/test_interp.py @@ -669,13 +669,13 @@ def interp_1d(data, dim, vals): old_coord = data[dim] - lower = data.sel(**selectors, method='ffill').drop(dim) - upper = data.sel(**selectors, method='bfill').drop(dim) - lower_x = data[dim].sel(**selectors, method='ffill').drop(dim) - upper_x = data[dim].sel(**selectors, method='bfill').drop(dim) - - new_x = lower[dim] - weight = np.abs(new_x - lower_x)/np.abs(upper_x-lower_x) + lower = data.sel(**selectors, method='ffill') + upper = data.sel(**selectors, method='bfill') + lower_x = data[dim].sel(**selectors, method='ffill') + upper_x = data[dim].sel(**selectors, method='bfill') + weight = np.abs(vals - lower_x)/np.abs(upper_x-lower_x) + # needed if upper and lower coordinates are identical + weight = weight.fillna(1.0) ans = lower * (1-weight) + upper * weight return ans @@ -686,29 +686,34 @@ def interp_1d(data, dim, vals): def test_new_interp(dim): data = xr.DataArray(np.arange(10), dims=[dim]).assign_coords({dim: np.arange(10)}) - new_x = np.arange(9) + .5 + new_x = xr.DataArray(np.arange(9) + .5, dims=['xp']) ans = interp_1d(data, dim, new_x) np.testing.assert_allclose(new_x, ans.values) def test_interp_1d_nd_targ(): - data = xr.DataArray(np.arange(10), dims=['x'], coords={'x': np.arange(10)}) - new_x_2d = xr.DataArray(np.tile(np.r_[:10], (3, 1)), dims=['y', 'x']) + new_x_2d = xr.DataArray(np.tile(np.r_[:9] + .5, (3, 1)), dims=['y', 'xp']) ans = interp_1d(data, 'x', new_x_2d) np.testing.assert_allclose(new_x_2d, ans.values) +def test_interp_1d_nd_targ(): + # interp with actual coords should be an isel. + data = xr.DataArray(np.arange(10), dims=['x'], coords={'x': np.arange(10)}) + new_x_2d = xr.DataArray(np.tile(np.r_[:9], (3, 1)), dims=['y', 'xp']) + ans = interp_1d(data, 'x', new_x_2d) + np.testing.assert_allclose(new_x_2d, ans.values) + def test_sel_nd(): npdata = np.tile(np.arange(10), (5, 1)) data = xr.DataArray(npdata, dims=['y', 'x'], coords={'x': np.r_[:10], 'y': np.r_[:5]}) - idx = xr.DataArray(npdata, dims=['z', 'x']) + idx = xr.DataArray(npdata, dims=['z', 'xp']) - ans = data.sel(x=idx, method='bfill') - assert set(ans.dims) == {'z', 'y', 'x'} + ans = data.sel(x=idx) + assert set(ans.dims) == {'z', 'y', 'xp'} print(ans) - From 5f90f4ed52210aaa1e3afd6c5da2f2295df31363 Mon Sep 17 00:00:00 2001 From: "Noah D. Brenowitz" Date: Sat, 24 Aug 2019 14:19:39 -0700 Subject: [PATCH 3/3] Start interp_nd stub and failing test --- xarray/tests/test_interp.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/xarray/tests/test_interp.py b/xarray/tests/test_interp.py index 1779dd6f42c..d843dfdc282 100644 --- a/xarray/tests/test_interp.py +++ b/xarray/tests/test_interp.py @@ -680,6 +680,16 @@ def interp_1d(data, dim, vals): return ans +def interp_nd(data, coords): + for dim in coords: + data = interp_1d(data, dim, coords[dim]) + return data + + +def test_interp_nd(): + assert False + + @pytest.mark.parametrize('dim',[ 'x', 'y' ])