summaryrefslogtreecommitdiff
path: root/silx/opencl/test/test_convolution.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/opencl/test/test_convolution.py')
-rw-r--r--silx/opencl/test/test_convolution.py265
1 files changed, 0 insertions, 265 deletions
diff --git a/silx/opencl/test/test_convolution.py b/silx/opencl/test/test_convolution.py
deleted file mode 100644
index 7bceb0d..0000000
--- a/silx/opencl/test/test_convolution.py
+++ /dev/null
@@ -1,265 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2019 European Synchrotron Radiation Facility
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-# ###########################################################################*/
-
-"""
-Test of the Convolution class.
-"""
-
-from __future__ import division, print_function
-
-__authors__ = ["Pierre Paleo"]
-__contact__ = "pierre.paleo@esrf.fr"
-__license__ = "MIT"
-__copyright__ = "2019 European Synchrotron Radiation Facility, Grenoble, France"
-__date__ = "01/08/2019"
-
-import logging
-from itertools import product
-import numpy as np
-from silx.utils.testutils import parameterize
-from silx.image.utils import gaussian_kernel
-
-try:
- from scipy.ndimage import convolve, convolve1d
- from scipy.misc import ascent
-
- scipy_convolve = convolve
- scipy_convolve1d = convolve1d
-except ImportError:
- scipy_convolve = None
-import unittest
-from ..common import ocl, check_textures_availability
-
-if ocl:
- import pyopencl as cl
- import pyopencl.array as parray
- from silx.opencl.convolution import Convolution
-logger = logging.getLogger(__name__)
-
-
-@unittest.skipUnless(ocl and scipy_convolve, "PyOpenCl/scipy is missing")
-class TestConvolution(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
- super(TestConvolution, cls).setUpClass()
- cls.image = np.ascontiguousarray(ascent()[:, :511], dtype="f")
- cls.data1d = cls.image[0]
- cls.data2d = cls.image
- cls.data3d = np.tile(cls.image[224:-224, 224:-224], (62, 1, 1))
- cls.kernel1d = gaussian_kernel(1.0)
- cls.kernel2d = np.outer(cls.kernel1d, cls.kernel1d)
- cls.kernel3d = np.multiply.outer(cls.kernel2d, cls.kernel1d)
- cls.ctx = ocl.create_context()
- cls.tol = {
- "1D": 1e-4,
- "2D": 1e-3,
- "3D": 1e-3,
- }
-
- @classmethod
- def tearDownClass(cls):
- cls.data1d = cls.data2d = cls.data3d = cls.image = None
- cls.kernel1d = cls.kernel2d = cls.kernel3d = None
-
- @staticmethod
- def compare(arr1, arr2):
- return np.max(np.abs(arr1 - arr2))
-
- @staticmethod
- def print_err(conv):
- errmsg = str(
- """
- Something wrong with %s
- mode=%s, texture=%s
- """
- % (conv.use_case_desc, conv.mode, conv.use_textures)
- )
- return errmsg
-
- def __init__(self, methodName="runTest", param=None):
- unittest.TestCase.__init__(self, methodName)
- self.param = param
- self.mode = param["boundary_handling"]
- logger.debug(
- """
- Testing convolution with boundary_handling=%s,
- use_textures=%s, input_device=%s, output_device=%s
- """
- % (
- self.mode,
- param["use_textures"],
- param["input_on_device"],
- param["output_on_device"],
- )
- )
-
- def instantiate_convol(self, shape, kernel, axes=None):
- if self.mode == "constant":
- if not (self.param["use_textures"]) or (
- self.param["use_textures"]
- and not (check_textures_availability(self.ctx))
- ):
- self.skipTest("mode=constant not implemented without textures")
- C = Convolution(
- shape,
- kernel,
- mode=self.mode,
- ctx=self.ctx,
- axes=axes,
- extra_options={"dont_use_textures": not (self.param["use_textures"])},
- )
- return C
-
- def get_data_and_kernel(self, test_name):
- dims = {
- "test_1D": (1, 1),
- "test_separable_2D": (2, 1),
- "test_separable_3D": (3, 1),
- "test_nonseparable_2D": (2, 2),
- "test_nonseparable_3D": (3, 3),
- }
- dim_data = {1: self.data1d, 2: self.data2d, 3: self.data3d}
- dim_kernel = {
- 1: self.kernel1d,
- 2: self.kernel2d,
- 3: self.kernel3d,
- }
- dd, kd = dims[test_name]
- return dim_data[dd], dim_kernel[kd]
-
- def get_reference_function(self, test_name):
- ref_func = {
- "test_1D": lambda x, y: scipy_convolve1d(x, y, mode=self.mode),
- "test_separable_2D": lambda x, y: scipy_convolve1d(
- scipy_convolve1d(x, y, mode=self.mode, axis=1),
- y,
- mode=self.mode,
- axis=0,
- ),
- "test_separable_3D": lambda x, y: scipy_convolve1d(
- scipy_convolve1d(
- scipy_convolve1d(x, y, mode=self.mode, axis=2),
- y,
- mode=self.mode,
- axis=1,
- ),
- y,
- mode=self.mode,
- axis=0,
- ),
- "test_nonseparable_2D": lambda x, y: scipy_convolve(x, y, mode=self.mode),
- "test_nonseparable_3D": lambda x, y: scipy_convolve(x, y, mode=self.mode),
- }
- return ref_func[test_name]
-
- def template_test(self, test_name):
- data, kernel = self.get_data_and_kernel(test_name)
- conv = self.instantiate_convol(data.shape, kernel)
- if self.param["input_on_device"]:
- data_ref = parray.to_device(conv.queue, data)
- else:
- data_ref = data
- if self.param["output_on_device"]:
- d_res = parray.empty_like(conv.data_out)
- d_res.fill(0)
- res = d_res
- else:
- res = None
- res = conv(data_ref, output=res)
- if self.param["output_on_device"]:
- res = res.get()
- ref_func = self.get_reference_function(test_name)
- ref = ref_func(data, kernel)
- metric = self.compare(res, ref)
- logger.info("%s: max error = %.2e" % (test_name, metric))
- tol = self.tol[str("%dD" % kernel.ndim)]
- self.assertLess(metric, tol, self.print_err(conv))
-
- def test_1D(self):
- self.template_test("test_1D")
-
- def test_separable_2D(self):
- self.template_test("test_separable_2D")
-
- def test_separable_3D(self):
- self.template_test("test_separable_3D")
-
- def test_nonseparable_2D(self):
- self.template_test("test_nonseparable_2D")
-
- def test_nonseparable_3D(self):
- self.template_test("test_nonseparable_3D")
-
- def test_batched_2D(self):
- """
- Test batched (nonseparable) 2D convolution on 3D data.
- In this test: batch along "z" (axis 0)
- """
- data = self.data3d
- kernel = self.kernel2d
- conv = self.instantiate_convol(data.shape, kernel, axes=(0,))
- res = conv(data) # 3D
- ref = scipy_convolve(data[0], kernel, mode=self.mode) # 2D
-
- std = np.std(res, axis=0)
- std_max = np.max(np.abs(std))
- self.assertLess(std_max, self.tol["2D"], self.print_err(conv))
- metric = self.compare(res[0], ref)
- logger.info("test_nonseparable_3D: max error = %.2e" % metric)
- self.assertLess(metric, self.tol["2D"], self.print_err(conv))
-
-
-def test_convolution():
- boundary_handling_ = ["reflect", "nearest", "wrap", "constant"]
- use_textures_ = [True, False]
- input_on_device_ = [True, False]
- output_on_device_ = [True, False]
- testSuite = unittest.TestSuite()
-
- param_vals = list(
- product(boundary_handling_, use_textures_, input_on_device_, output_on_device_)
- )
- for boundary_handling, use_textures, input_dev, output_dev in param_vals:
- testcase = parameterize(
- TestConvolution,
- param={
- "boundary_handling": boundary_handling,
- "input_on_device": input_dev,
- "output_on_device": output_dev,
- "use_textures": use_textures,
- },
- )
- testSuite.addTest(testcase)
- return testSuite
-
-
-def suite():
- testSuite = test_convolution()
- return testSuite
-
-
-if __name__ == "__main__":
- unittest.main(defaultTest="suite")