From 4e774db12d5ebe7a20eded6dd434a289e27999e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Picca=20Fr=C3=A9d=C3=A9ric-Emmanuel?= Date: Wed, 2 Feb 2022 14:19:58 +0100 Subject: New upstream version 1.0.0+dfsg --- src/silx/test/__init__.py | 53 ++++++++ src/silx/test/test_resources.py | 187 ++++++++++++++++++++++++++++ src/silx/test/test_sx.py | 265 ++++++++++++++++++++++++++++++++++++++++ src/silx/test/test_version.py | 38 ++++++ src/silx/test/utils.py | 198 ++++++++++++++++++++++++++++++ 5 files changed, 741 insertions(+) create mode 100644 src/silx/test/__init__.py create mode 100644 src/silx/test/test_resources.py create mode 100644 src/silx/test/test_sx.py create mode 100644 src/silx/test/test_version.py create mode 100644 src/silx/test/utils.py (limited to 'src/silx/test') diff --git a/src/silx/test/__init__.py b/src/silx/test/__init__.py new file mode 100644 index 0000000..d9d3e42 --- /dev/null +++ b/src/silx/test/__init__.py @@ -0,0 +1,53 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2015-2021 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. +# +# ###########################################################################*/ +"""This package provides test of the root modules +""" + +import logging + + +try: + import pytest +except ImportError: + logging.getLogger(__name__).error( + "pytest is required to run the tests, please install it.") + raise + +def run_tests(module: str='silx', verbosity: int=0, args=()): + """Run tests + + :param module: Name of the silx module to test (default: 'silx') + :param verbosity: Requested level of verbosity + :param args: List of extra arguments to pass to `pytest` + """ + return pytest.main([ + '--pyargs', + module, + '--verbosity', + str(verbosity), + '-o python_files=["test/test*.py","test/Test*.py"]', + '-o python_classes=["Test"]', + '-o python_functions=["Test"]', + ] + list(args)) diff --git a/src/silx/test/test_resources.py b/src/silx/test/test_resources.py new file mode 100644 index 0000000..4030271 --- /dev/null +++ b/src/silx/test/test_resources.py @@ -0,0 +1,187 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2016-2018 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 for resource files management.""" + +__authors__ = ["T. Vincent"] +__license__ = "MIT" +__date__ = "08/03/2019" + + +import os +import unittest +import shutil +import tempfile + +import silx.resources + + +class TestResources(unittest.TestCase): + + @classmethod + def setUpClass(cls): + super(TestResources, cls).setUpClass() + + cls.tmpDirectory = tempfile.mkdtemp(prefix="resource_") + os.mkdir(os.path.join(cls.tmpDirectory, "gui")) + destination_dir = os.path.join(cls.tmpDirectory, "gui", "icons") + os.mkdir(destination_dir) + source = silx.resources.resource_filename("gui/icons/zoom-in.png") + destination = os.path.join(destination_dir, "foo.png") + shutil.copy(source, destination) + source = silx.resources.resource_filename("gui/icons/zoom-out.svg") + destination = os.path.join(destination_dir, "close.png") + shutil.copy(source, destination) + + @classmethod + def tearDownClass(cls): + super(TestResources, cls).tearDownClass() + shutil.rmtree(cls.tmpDirectory) + + def setUp(self): + # Store the original configuration + self._oldResources = dict(silx.resources._RESOURCE_DIRECTORIES) + unittest.TestCase.setUp(self) + + def tearDown(self): + unittest.TestCase.tearDown(self) + # Restiture the original configuration + silx.resources._RESOURCE_DIRECTORIES = self._oldResources + + def test_resource_dir(self): + """Get a resource directory""" + icons_dirname = silx.resources.resource_filename('gui/icons/') + self.assertTrue(os.path.isdir(icons_dirname)) + + def test_resource_file(self): + """Get a resource file name""" + filename = silx.resources.resource_filename('gui/icons/colormap.png') + self.assertTrue(os.path.isfile(filename)) + + def test_resource_nonexistent(self): + """Get a non existent resource""" + filename = silx.resources.resource_filename('non_existent_file.txt') + self.assertFalse(os.path.exists(filename)) + + def test_isdir(self): + self.assertTrue(silx.resources.is_dir('gui/icons')) + + def test_not_isdir(self): + self.assertFalse(silx.resources.is_dir('gui/icons/colormap.png')) + + def test_list_dir(self): + result = silx.resources.list_dir('gui/icons') + self.assertTrue(len(result) > 10) + + # With prefixed resources + + def test_resource_dir_with_prefix(self): + """Get a resource directory""" + icons_dirname = silx.resources.resource_filename('silx:gui/icons/') + self.assertTrue(os.path.isdir(icons_dirname)) + + def test_resource_file_with_prefix(self): + """Get a resource file name""" + filename = silx.resources.resource_filename('silx:gui/icons/colormap.png') + self.assertTrue(os.path.isfile(filename)) + + def test_resource_nonexistent_with_prefix(self): + """Get a non existent resource""" + filename = silx.resources.resource_filename('silx:non_existent_file.txt') + self.assertFalse(os.path.exists(filename)) + + def test_isdir_with_prefix(self): + self.assertTrue(silx.resources.is_dir('silx:gui/icons')) + + def test_not_isdir_with_prefix(self): + self.assertFalse(silx.resources.is_dir('silx:gui/icons/colormap.png')) + + def test_list_dir_with_prefix(self): + result = silx.resources.list_dir('silx:gui/icons') + self.assertTrue(len(result) > 10) + + # Test new repository + + def test_repository_not_exists(self): + """The resource from 'test' is available""" + self.assertRaises(ValueError, silx.resources.resource_filename, 'test:foo.png') + + def test_adding_test_directory(self): + """The resource from 'test' is available""" + silx.resources.register_resource_directory("test", "silx.test.resources", forced_path=self.tmpDirectory) + path = silx.resources.resource_filename('test:gui/icons/foo.png') + self.assertTrue(os.path.exists(path)) + + def test_adding_test_directory_no_override(self): + """The resource from 'silx' is still available""" + silx.resources.register_resource_directory("test", "silx.test.resources", forced_path=self.tmpDirectory) + filename1 = silx.resources.resource_filename('gui/icons/close.png') + filename2 = silx.resources.resource_filename('silx:gui/icons/close.png') + filename3 = silx.resources.resource_filename('test:gui/icons/close.png') + self.assertTrue(os.path.isfile(filename1)) + self.assertTrue(os.path.isfile(filename2)) + self.assertTrue(os.path.isfile(filename3)) + self.assertEqual(filename1, filename2) + self.assertNotEqual(filename1, filename3) + + def test_adding_test_directory_non_existing(self): + """A resource while not exists in test is not available anyway it exists + in silx""" + silx.resources.register_resource_directory("test", "silx.test.resources", forced_path=self.tmpDirectory) + resource_name = "gui/icons/colormap.png" + path = silx.resources.resource_filename('test:' + resource_name) + path2 = silx.resources.resource_filename('silx:' + resource_name) + self.assertFalse(os.path.exists(path)) + self.assertTrue(os.path.exists(path2)) + + +class TestResourcesWithoutPkgResources(TestResources): + + @classmethod + def setUpClass(cls): + super(TestResourcesWithoutPkgResources, cls).setUpClass() + cls._old = silx.resources.pkg_resources + silx.resources.pkg_resources = None + + @classmethod + def tearDownClass(cls): + silx.resources.pkg_resources = cls._old + del cls._old + super(TestResourcesWithoutPkgResources, cls).tearDownClass() + + +class TestResourcesWithCustomDirectory(TestResources): + + @classmethod + def setUpClass(cls): + super(TestResourcesWithCustomDirectory, cls).setUpClass() + cls._old = silx.resources._RESOURCES_DIR + base = os.path.dirname(silx.resources.__file__) + silx.resources._RESOURCES_DIR = base + + @classmethod + def tearDownClass(cls): + silx.resources._RESOURCES_DIR = cls._old + del cls._old + super(TestResourcesWithCustomDirectory, cls).tearDownClass() diff --git a/src/silx/test/test_sx.py b/src/silx/test/test_sx.py new file mode 100644 index 0000000..9836285 --- /dev/null +++ b/src/silx/test/test_sx.py @@ -0,0 +1,265 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2016-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. +# +# ###########################################################################*/ +__authors__ = ["T. Vincent", "P. Knobel"] +__license__ = "MIT" +__date__ = "06/11/2018" + + +import numpy +import pytest + +from silx.gui import qt +from silx.gui.colors import rgba +from silx.gui.colors import Colormap + + +@pytest.fixture(scope="module") +def sx(qapp): + """Lazy loading to avoid it to create QApplication before qapp fixture""" + from silx import sx + if sx._IS_NOTEBOOK: + pytest.skip("notebook context") + if sx._NO_DISPLAY: + pytest.skip("no DISPLAY specified") + yield sx + + +def test_plot(sx, qapp_utils): + """Test plot function""" + y = numpy.random.random(100) + x = numpy.arange(len(y)) * 0.5 + + # Nothing + plt = sx.plot() + qapp_utils.exposeAndClose(plt) + + # y + plt = sx.plot(y, title='y') + qapp_utils.exposeAndClose(plt) + + # y, style + plt = sx.plot(y, 'blued ', title='y, "blued "') + qapp_utils.exposeAndClose(plt) + + # x, y + plt = sx.plot(x, y, title='x, y') + qapp_utils.exposeAndClose(plt) + + # x, y, style + plt = sx.plot(x, y, 'ro-', xlabel='x', title='x, y, "ro-"') + qapp_utils.exposeAndClose(plt) + + # x, y, style, y + plt = sx.plot(x, y, 'ro-', y ** 2, xlabel='x', ylabel='y', + title='x, y, "ro-", y ** 2') + qapp_utils.exposeAndClose(plt) + + # x, y, style, y, style + plt = sx.plot(x, y, 'ro-', y ** 2, 'b--', + title='x, y, "ro-", y ** 2, "b--"') + qapp_utils.exposeAndClose(plt) + + # x, y, style, x, y, style + plt = sx.plot(x, y, 'ro-', x, y ** 2, 'b--', + title='x, y, "ro-", x, y ** 2, "b--"') + qapp_utils.exposeAndClose(plt) + + # x, y, x, y + plt = sx.plot(x, y, x, y ** 2, title='x, y, x, y ** 2') + qapp_utils.exposeAndClose(plt) + + +def test_imshow(sx, qapp_utils): + """Test imshow function""" + img = numpy.arange(100.).reshape(10, 10) + 1 + + # Nothing + plt = sx.imshow() + qapp_utils.exposeAndClose(plt) + + # image + plt = sx.imshow(img) + qapp_utils.exposeAndClose(plt) + + # image, named cmap + plt = sx.imshow(img, cmap='jet', title='jet cmap') + qapp_utils.exposeAndClose(plt) + + # image, custom colormap + plt = sx.imshow(img, cmap=Colormap(), title='custom colormap') + qapp_utils.exposeAndClose(plt) + + # image, log cmap + plt = sx.imshow(img, norm='log', title='log cmap') + qapp_utils.exposeAndClose(plt) + + # image, fixed range + plt = sx.imshow(img, vmin=10, vmax=20, + title='[10,20] cmap') + qapp_utils.exposeAndClose(plt) + + # image, keep ratio + plt = sx.imshow(img, aspect=True, + title='keep ratio') + qapp_utils.exposeAndClose(plt) + + # image, change origin and scale + plt = sx.imshow(img, origin=(10, 10), scale=(2, 2), + title='origin=(10, 10), scale=(2, 2)') + qapp_utils.exposeAndClose(plt) + + # image, origin='lower' + plt = sx.imshow(img, origin='upper', title='origin="lower"') + qapp_utils.exposeAndClose(plt) + + +def test_scatter(sx, qapp_utils): + """Test scatter function""" + x = numpy.arange(100) + y = numpy.arange(100) + values = numpy.arange(100) + + # simple scatter + plt = sx.scatter(x, y, values) + qapp_utils.exposeAndClose(plt) + + # No value + plt = sx.scatter(x, y, values) + qapp_utils.exposeAndClose(plt) + + # single value + plt = sx.scatter(x, y, 10.) + qapp_utils.exposeAndClose(plt) + + # set size + plt = sx.scatter(x, y, values, size=20) + qapp_utils.exposeAndClose(plt) + + # set colormap + plt = sx.scatter(x, y, values, cmap='jet') + qapp_utils.exposeAndClose(plt) + + # set colormap range + plt = sx.scatter(x, y, values, vmin=2, vmax=50) + qapp_utils.exposeAndClose(plt) + + # set colormap normalisation + plt = sx.scatter(x, y, values, norm='log') + qapp_utils.exposeAndClose(plt) + + +@pytest.mark.parametrize("plot_kind", ["plot", "imshow", "scatter"]) +def test_ginput(sx, qapp, qapp_utils, plot_kind): + """Test ginput function + + This does NOT perform interactive tests + """ + create_plot = getattr(sx, plot_kind) + plt = create_plot() + qapp_utils.qWaitForWindowExposed(plt) + qapp.processEvents() + + result = sx.ginput(1, timeout=0.1) + assert len(result) == 0 + + plt.setAttribute(qt.Qt.WA_DeleteOnClose) + plt.close() + + +@pytest.mark.usefixtures("use_opengl") +def test_contour3d(sx, qapp_utils): + """Test contour3d function""" + coords = numpy.linspace(-10, 10, 64) + z = coords.reshape(-1, 1, 1) + y = coords.reshape(1, -1, 1) + x = coords.reshape(1, 1, -1) + data = numpy.sin(x * y * z) / (x * y * z) + + # Just data + window = sx.contour3d(data) + + isosurfaces = window.getIsosurfaces() + assert len(isosurfaces) == 1 + + if not window.getPlot3DWidget().isValid(): + del window, isosurfaces # Release widget reference + pytest.skip("OpenGL context is not valid") + + # N contours + color + colors = ['red', 'green', 'blue'] + window = sx.contour3d(data, copy=False, contours=len(colors), + color=colors) + + isosurfaces = window.getIsosurfaces() + assert len(isosurfaces) == len(colors) + for iso, color in zip(isosurfaces, colors): + assert rgba(iso.getColor()) == rgba(color) + + # by isolevel, single color + contours = 0.2, 0.5 + window = sx.contour3d(data, copy=False, contours=contours, + color='yellow') + + isosurfaces = window.getIsosurfaces() + assert len(isosurfaces) == len(contours) + for iso, level in zip(isosurfaces, contours): + assert iso.getLevel() == level + assert rgba(iso.getColor()) == rgba('yellow') + + # Single isolevel, colormap + window = sx.contour3d(data, copy=False, contours=0.5, + colormap='gray', vmin=0.6, opacity=0.4) + + isosurfaces = window.getIsosurfaces() + assert len(isosurfaces) == 1 + assert isosurfaces[0].getLevel() == 0.5 + assert rgba(isosurfaces[0].getColor()) == (0., 0., 0., 0.4) + + +@pytest.mark.usefixtures("use_opengl") +def test_points3d(sx, qapp_utils): + """Test points3d function""" + x = numpy.random.random(1024) + y = numpy.random.random(1024) + z = numpy.random.random(1024) + values = numpy.random.random(1024) + + # 3D positions, no value + window = sx.points3d(x, y, z) + + if not window.getSceneWidget().isValid(): + del window # Release widget reference + pytest.skip("OpenGL context is not valid") + + # 3D positions, values + window = sx.points3d(x, y, z, values, mode='2dsquare', + colormap='magma', vmin=0.4, vmax=0.5) + + # 2D positions, no value + window = sx.points3d(x, y) + + # 2D positions, values + window = sx.points3d(x, y, values=values, mode=',', + colormap='magma', vmin=0.4, vmax=0.5) diff --git a/src/silx/test/test_version.py b/src/silx/test/test_version.py new file mode 100644 index 0000000..80084f9 --- /dev/null +++ b/src/silx/test/test_version.py @@ -0,0 +1,38 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2015-2016 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. +# +# ###########################################################################*/ +"""Basic test of top-level package import and existence of version info.""" + +__authors__ = ["T. Vincent"] +__license__ = "MIT" +__date__ = "26/02/2016" + +import unittest + +import silx + + +class TestVersion(unittest.TestCase): + def test_version(self): + self.assertTrue(isinstance(silx.version, str)) diff --git a/src/silx/test/utils.py b/src/silx/test/utils.py new file mode 100644 index 0000000..0c2d5bf --- /dev/null +++ b/src/silx/test/utils.py @@ -0,0 +1,198 @@ +# coding: utf-8 +# /*########################################################################## +# +# Copyright (c) 2016-2021 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. +# +# ###########################################################################*/ +"""Utilities for writing tests. + +- :func:`temp_dir` provides a with context to create/delete a temporary + directory. +""" + +__authors__ = ["T. Vincent"] +__license__ = "MIT" +__date__ = "03/01/2019" + + +import sys +import contextlib +import os +import numpy +import shutil +import tempfile +from ..resources import ExternalResources + + +utilstest = ExternalResources(project="silx", + url_base="http://www.silx.org/pub/silx/", + env_key="SILX_DATA", + timeout=60) +"This is the instance to be used. Singleton-like feature provided by module" + + +class _TestOptions(object): + + def __init__(self): + self.WITH_QT_TEST = True + """Qt tests are included""" + + self.WITH_QT_TEST_REASON = "" + """Reason for Qt tests are disabled if any""" + + self.WITH_OPENCL_TEST = True + """OpenCL tests are included""" + + self.WITH_OPENCL_TEST_REASON = "" + """Reason for OpenCL tests are disabled if any""" + + self.WITH_GL_TEST = True + """OpenGL tests are included""" + + self.WITH_GL_TEST_REASON = "" + """Reason for OpenGL tests are disabled if any""" + + self.TEST_LOW_MEM = False + """Skip tests using too much memory""" + + self.TEST_LOW_MEM_REASON = "" + """Reason for low_memory tests are disabled if any""" + + def configure(self, parsed_options=None): + """Configure the TestOptions class from the command line arguments and the + environment variables + """ + if parsed_options is not None and not parsed_options.gui: + self.WITH_QT_TEST = False + self.WITH_QT_TEST_REASON = "Skipped by command line" + elif os.environ.get('WITH_QT_TEST', 'True') == 'False': + self.WITH_QT_TEST = False + self.WITH_QT_TEST_REASON = "Skipped by WITH_QT_TEST env var" + elif sys.platform.startswith('linux') and not os.environ.get('DISPLAY', ''): + self.WITH_QT_TEST = False + self.WITH_QT_TEST_REASON = "DISPLAY env variable not set" + + if parsed_options is not None and not parsed_options.opencl: + self.WITH_OPENCL_TEST_REASON = "Skipped by command line" + self.WITH_OPENCL_TEST = False + elif os.environ.get('SILX_OPENCL', 'True') == 'False': + self.WITH_OPENCL_TEST_REASON = "Skipped by SILX_OPENCL env var" + self.WITH_OPENCL_TEST = False + + if not self.WITH_OPENCL_TEST: + # That's an easy way to skip OpenCL tests + # It disable the use of OpenCL on the full silx project + os.environ['SILX_OPENCL'] = "False" + + if parsed_options is not None and not parsed_options.opengl: + self.WITH_GL_TEST = False + self.WITH_GL_TEST_REASON = "Skipped by command line" + elif os.environ.get('WITH_GL_TEST', 'True') == 'False': + self.WITH_GL_TEST = False + self.WITH_GL_TEST_REASON = "Skipped by WITH_GL_TEST env var" + elif sys.platform.startswith('linux') and not os.environ.get('DISPLAY', ''): + self.WITH_GL_TEST = False + self.WITH_GL_TEST_REASON = "DISPLAY env variable not set" + else: + try: + import OpenGL + except ImportError: + self.WITH_GL_TEST = False + self.WITH_GL_TEST_REASON = "OpenGL package not available" + + if parsed_options is not None and parsed_options.low_mem: + self.TEST_LOW_MEM = True + self.TEST_LOW_MEM_REASON = "Skipped by command line" + elif os.environ.get('SILX_TEST_LOW_MEM', 'True') == 'False': + self.TEST_LOW_MEM = True + self.TEST_LOW_MEM_REASON = "Skipped by SILX_TEST_LOW_MEM env var" + + if self.WITH_QT_TEST: + try: + from silx.gui import qt + except ImportError: + self.WITH_QT_TEST = False + self.WITH_QT_TEST_REASON = "Qt is not installed" + else: + if sys.platform == "win32" and qt.qVersion() == "5.9.2": + self.SKIP_TEST_FOR_ISSUE_936 = True + + +# Temporary directory context ################################################# + +@contextlib.contextmanager +def temp_dir(): + """with context providing a temporary directory. + + >>> import os.path + >>> with temp_dir() as tmp: + ... print(os.path.isdir(tmp)) # Use tmp directory + """ + tmp_dir = tempfile.mkdtemp() + try: + yield tmp_dir + finally: + shutil.rmtree(tmp_dir) + + +# Synthetic data and random noise ############################################# +def add_gaussian_noise(y, stdev=1., mean=0.): + """Add random gaussian noise to synthetic data. + + :param ndarray y: Array of synthetic data + :param float mean: Mean of the gaussian distribution of noise. + :param float stdev: Standard deviation of the gaussian distribution of + noise. + :return: Array of data with noise added + """ + noise = numpy.random.normal(mean, stdev, size=y.size) + noise.shape = y.shape + return y + noise + + +def add_poisson_noise(y): + """Add random noise from a poisson distribution to synthetic data. + + :param ndarray y: Array of synthetic data + :return: Array of data with noise added + """ + yn = numpy.random.poisson(y) + yn.shape = y.shape + return yn + + +def add_relative_noise(y, max_noise=5.): + """Add relative random noise to synthetic data. The maximum noise level + is given in percents. + + An array of noise in the interval [-max_noise, max_noise] (continuous + uniform distribution) is generated, and applied to the data the + following way: + + :math:`yn = y * (1. + noise / 100.)` + + :param ndarray y: Array of synthetic data + :param float max_noise: Maximum percentage of noise + :return: Array of data with noise added + """ + noise = max_noise * (2 * numpy.random.random(size=y.size) - 1) + noise.shape = y.shape + return y * (1. + noise / 100.) -- cgit v1.2.3