Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convolve_2d gpu fixes #702

Merged
merged 5 commits into from
May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions xrspatial/convolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,13 @@ def _convolve_2d_cuda(data, kernel, out):
return

# The out at coordinates (i, j) is equal to
# sum_{k, h} kernel[k, h] * data[i - k + delta_rows, j - h + delta_cols]
# sum_{k, h} kernel[k, h] * data[i + k - delta_rows, j + h - delta_cols]
# with k and h going through the whole kernel array:
s = 0
for k in range(kernel.shape[0]):
for h in range(kernel.shape[1]):
i_k = i - k + delta_rows
j_h = j - h + delta_cols
i_k = i + k - delta_rows
j_h = j + h - delta_cols
# (-4-) Check if (i_k, j_h) coordinates are inside the array:
if (i_k >= 0) and (i_k < data_rows) and \
(j_h >= 0) and (j_h < data_cols):
Expand Down Expand Up @@ -496,8 +496,8 @@ def convolution_2d(agg, kernel, name='convolution_2d'):
>>> convolved_agg
<xarray.DataArray 'convolution_2d' (dim_0: 4, dim_1: 6)>
array([[ nan, nan, nan, nan, nan, nan],
[ nan, 56., 64., 72., 80., nan],
[ nan, 104., 112., 120., 128., nan],
[ nan, 50., 58., 66., 74., nan],
[ nan, 98., 106., 114., 122., nan],
[ nan, nan, nan, nan, nan, nan]], dtype=float32)
Dimensions without coordinates: dim_0, dim_1
"""
Expand Down
39 changes: 30 additions & 9 deletions xrspatial/tests/test_focal.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,20 @@ def convolution_kernel_annulus_2_2_1():
return expected_result


@pytest.fixture
def convolution_custom_kernel():
kernel = np.array([[1, 0, 0], [1, 1, 0], [1, 0, 0]])
expected_result = np.array([
[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
[np.nan, 2., 3., 3., 4., np.nan],
[np.nan, 4., np.nan, np.nan, np.nan, np.nan],
[np.nan, 4., np.nan, np.nan, np.nan, np.nan],
[np.nan, 4., np.nan, np.nan, np.nan, np.nan],
[np.nan, np.nan, np.nan, np.nan, np.nan, np.nan]
])
return kernel, expected_result


def test_kernel_custom_kernel_invalid_type():
kernel = [1, 0, 0] # only arrays are accepted, not lists
with pytest.raises(ValueError):
Expand All @@ -159,16 +173,18 @@ def test_kernel(kernel_circle_1_1_1, kernel_annulus_2_2_2_1):

def test_convolution_numpy(
convolve_2d_data,
convolution_custom_kernel,
kernel_circle_1_1_1,
convolution_kernel_circle_1_1_1,
kernel_annulus_2_2_2_1,
convolution_kernel_annulus_2_2_1
):
kernel_custom = np.ones((1, 1))
kernel_custom, expected_result_custom = convolution_custom_kernel
result_kernel_custom = convolve_2d(convolve_2d_data, kernel_custom)
assert isinstance(result_kernel_custom, np.ndarray)
# kernel is [[1]], thus the result equals input data
np.testing.assert_allclose(result_kernel_custom, convolve_2d_data, equal_nan=True)
np.testing.assert_allclose(
result_kernel_custom, expected_result_custom, equal_nan=True
)

result_kernel_circle = convolve_2d(convolve_2d_data, kernel_circle_1_1_1)
assert isinstance(result_kernel_circle, np.ndarray)
Expand All @@ -185,17 +201,20 @@ def test_convolution_numpy(

def test_convolution_dask_numpy(
convolve_2d_data,
convolution_custom_kernel,
kernel_circle_1_1_1,
convolution_kernel_circle_1_1_1,
kernel_annulus_2_2_2_1,
convolution_kernel_annulus_2_2_1
):
dask_agg = create_test_raster(convolve_2d_data, backend='dask+numpy')
kernel_custom = np.ones((1, 1))

kernel_custom, expected_result_custom = convolution_custom_kernel
result_kernel_custom = convolution_2d(dask_agg, kernel_custom)
assert isinstance(result_kernel_custom.data, da.Array)
# kernel is [[1]], thus the result equals input data
np.testing.assert_allclose(result_kernel_custom.compute(), convolve_2d_data, equal_nan=True)
np.testing.assert_allclose(
result_kernel_custom.compute(), expected_result_custom, equal_nan=True
)

result_kernel_circle = convolution_2d(dask_agg, kernel_circle_1_1_1)
assert isinstance(result_kernel_circle.data, da.Array)
Expand All @@ -213,6 +232,7 @@ def test_convolution_dask_numpy(
@cuda_and_cupy_available
def test_2d_convolution_gpu(
convolve_2d_data,
convolution_custom_kernel,
kernel_circle_1_1_1,
convolution_kernel_circle_1_1_1,
kernel_annulus_2_2_2_1,
Expand All @@ -221,11 +241,12 @@ def test_2d_convolution_gpu(
import cupy
cupy_data = cupy.asarray(convolve_2d_data)

kernel_custom = np.ones((1, 1))
kernel_custom, expected_result_custom = convolution_custom_kernel
result_kernel_custom = convolve_2d(cupy_data, kernel_custom)
assert isinstance(result_kernel_custom, cupy.ndarray)
# kernel is [[1]], thus the result equals input data
np.testing.assert_allclose(result_kernel_custom.get(), convolve_2d_data, equal_nan=True)
np.testing.assert_allclose(
result_kernel_custom.get(), expected_result_custom, equal_nan=True
)

result_kernel_circle = convolve_2d(cupy_data, kernel_circle_1_1_1)
assert isinstance(result_kernel_circle, cupy.ndarray)
Expand Down