diff options
Diffstat (limited to 'silx/gui/plot3d/test')
-rw-r--r-- | silx/gui/plot3d/test/__init__.py | 75 | ||||
-rw-r--r-- | silx/gui/plot3d/test/testGL.py | 84 | ||||
-rw-r--r-- | silx/gui/plot3d/test/testScalarFieldView.py | 139 | ||||
-rw-r--r-- | silx/gui/plot3d/test/testSceneWidget.py | 84 | ||||
-rw-r--r-- | silx/gui/plot3d/test/testSceneWidgetPicking.py | 326 | ||||
-rw-r--r-- | silx/gui/plot3d/test/testSceneWindow.py | 245 | ||||
-rw-r--r-- | silx/gui/plot3d/test/testStatsWidget.py | 216 |
7 files changed, 0 insertions, 1169 deletions
diff --git a/silx/gui/plot3d/test/__init__.py b/silx/gui/plot3d/test/__init__.py deleted file mode 100644 index 77172d1..0000000 --- a/silx/gui/plot3d/test/__init__.py +++ /dev/null @@ -1,75 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2015-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. -# -# ###########################################################################*/ -"""plot3d test suite.""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "09/11/2017" - - -import logging -import unittest -from silx.test.utils import test_options - - -_logger = logging.getLogger(__name__) - - -def suite(): - testsuite = unittest.TestSuite() - - if not test_options.WITH_GL_TEST: - # Explicitly disabled tests - msg = "silx.gui.plot3d tests disabled: %s" % test_options.WITH_GL_TEST_REASON - _logger.warning(msg) - - class SkipPlot3DTest(unittest.TestCase): - def runTest(self): - self.skipTest(test_options.WITH_GL_TEST_REASON) - - testsuite.addTest(SkipPlot3DTest()) - return testsuite - - # Import here to avoid loading modules if tests are disabled - - from ..scene.test import suite as sceneTestSuite - from ..tools.test import suite as toolsTestSuite - from .testGL import suite as testGLSuite - from .testScalarFieldView import suite as testScalarFieldViewSuite - from .testSceneWidget import suite as testSceneWidgetSuite - from .testSceneWidgetPicking import suite as testSceneWidgetPickingSuite - from .testSceneWindow import suite as testSceneWindowSuite - from .testStatsWidget import suite as testStatsWidgetSuite - - testsuite = unittest.TestSuite() - testsuite.addTest(testGLSuite()) - testsuite.addTest(sceneTestSuite()) - testsuite.addTest(testScalarFieldViewSuite()) - testsuite.addTest(testSceneWidgetSuite()) - testsuite.addTest(testSceneWidgetPickingSuite()) - testsuite.addTest(testSceneWindowSuite()) - testsuite.addTest(toolsTestSuite()) - testsuite.addTest(testStatsWidgetSuite()) - return testsuite diff --git a/silx/gui/plot3d/test/testGL.py b/silx/gui/plot3d/test/testGL.py deleted file mode 100644 index ae167ab..0000000 --- a/silx/gui/plot3d/test/testGL.py +++ /dev/null @@ -1,84 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2017 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 OpenGL""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "10/08/2017" - - -import logging -import unittest - -from silx.gui._glutils import gl, OpenGLWidget -from silx.gui.utils.testutils import TestCaseQt -from silx.gui import qt - - -_logger = logging.getLogger(__name__) - - -class TestOpenGL(TestCaseQt): - """Tests of OpenGL widget.""" - - class OpenGLWidgetLogger(OpenGLWidget): - """Widget logging information of available OpenGL version""" - - def __init__(self): - self._dump = False - super(TestOpenGL.OpenGLWidgetLogger, self).__init__(version=(1, 0)) - - def paintOpenGL(self): - """Perform the rendering and logging""" - if not self._dump: - self._dump = True - _logger.info('OpenGL info:') - _logger.info('\tQt OpenGL context version: %d.%d', *self.getOpenGLVersion()) - _logger.info('\tGL_VERSION: %s' % gl.glGetString(gl.GL_VERSION)) - _logger.info('\tGL_SHADING_LANGUAGE_VERSION: %s' % - gl.glGetString(gl.GL_SHADING_LANGUAGE_VERSION)) - _logger.debug('\tGL_EXTENSIONS: %s' % gl.glGetString(gl.GL_EXTENSIONS)) - - gl.glClearColor(1., 1., 1., 1.) - gl.glClear(gl.GL_COLOR_BUFFER_BIT) - - def testOpenGL(self): - """Log OpenGL version using an OpenGLWidget""" - super(TestOpenGL, self).setUp() - widget = self.OpenGLWidgetLogger() - widget.show() - widget.setAttribute(qt.Qt.WA_DeleteOnClose) - self.qWaitForWindowExposed(widget) - widget.close() - - -def suite(): - test_suite = unittest.TestSuite() - loadTests = unittest.defaultTestLoader.loadTestsFromTestCase - test_suite.addTest(loadTests(TestOpenGL)) - return test_suite - - -if __name__ == '__main__': - unittest.main(defaultTest='suite') diff --git a/silx/gui/plot3d/test/testScalarFieldView.py b/silx/gui/plot3d/test/testScalarFieldView.py deleted file mode 100644 index d9c743b..0000000 --- a/silx/gui/plot3d/test/testScalarFieldView.py +++ /dev/null @@ -1,139 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2017-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 ScalarFieldView widget""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "17/01/2018" - - -import logging -import unittest - -import numpy - -from silx.utils.testutils import ParametricTestCase -from silx.gui.utils.testutils import TestCaseQt -from silx.gui import qt - -from silx.gui.plot3d.ScalarFieldView import ScalarFieldView -from silx.gui.plot3d.SFViewParamTree import TreeView - - -_logger = logging.getLogger(__name__) - - -class TestScalarFieldView(TestCaseQt, ParametricTestCase): - """Tests of ScalarFieldView widget.""" - - def setUp(self): - super(TestScalarFieldView, self).setUp() - self.widget = ScalarFieldView() - self.widget.show() - - paramTreeWidget = TreeView() - paramTreeWidget.setSfView(self.widget) - - dock = qt.QDockWidget() - dock.setWidget(paramTreeWidget) - self.widget.addDockWidget(qt.Qt.BottomDockWidgetArea, dock) - - # Commented as it slows down the tests - # self.qWaitForWindowExposed(self.widget) - - def tearDown(self): - self.qapp.processEvents() - self.widget.setAttribute(qt.Qt.WA_DeleteOnClose) - self.widget.close() - del self.widget - super(TestScalarFieldView, self).tearDown() - - @staticmethod - def _buildData(size): - """Make a 3D dataset""" - coords = numpy.linspace(-10, 10, size) - z = coords.reshape(-1, 1, 1) - y = coords.reshape(1, -1, 1) - x = coords.reshape(1, 1, -1) - return numpy.sin(x * y * z) / (x * y * z) - - def testSimple(self): - """Set the data and an isosurface""" - data = self._buildData(size=32) - - self.widget.setData(data) - self.widget.addIsosurface(0.5, (1., 0., 0., 0.5)) - self.widget.addIsosurface(0.7, qt.QColor('green')) - self.qapp.processEvents() - - def testNotFinite(self): - """Test with NaN and inf in data set""" - - # Some NaNs and inf - data = self._buildData(size=32) - data[8, :, :] = numpy.nan - data[16, :, :] = numpy.inf - data[24, :, :] = - numpy.inf - - self.widget.addIsosurface(0.5, 'red') - self.widget.setData(data, copy=True) - self.qapp.processEvents() - self.widget.setData(None) - - # All NaNs or inf - data = numpy.empty((4, 4, 4), dtype=numpy.float32) - for value in (numpy.nan, numpy.inf): - with self.subTest(value=str(value)): - data[:] = value - self.widget.setData(data, copy=True) - self.qapp.processEvents() - - def testIsoSliderNormalization(self): - """Test set TreeView with a different isoslider normalization""" - data = self._buildData(size=32) - - self.widget.setData(data) - self.widget.addIsosurface(0.5, (1., 0., 0., 0.5)) - self.widget.addIsosurface(0.7, qt.QColor('green')) - self.qapp.processEvents() - - # Add a second TreeView - paramTreeWidget = TreeView(self.widget) - paramTreeWidget.setIsoLevelSliderNormalization('arcsinh') - paramTreeWidget.setSfView(self.widget) - - dock = qt.QDockWidget() - dock.setWidget(paramTreeWidget) - self.widget.addDockWidget(qt.Qt.BottomDockWidgetArea, dock) - - -def suite(): - test_suite = unittest.TestSuite() - loadTests = unittest.defaultTestLoader.loadTestsFromTestCase - test_suite.addTest(loadTests(TestScalarFieldView)) - return test_suite - - -if __name__ == '__main__': - unittest.main(defaultTest='suite') diff --git a/silx/gui/plot3d/test/testSceneWidget.py b/silx/gui/plot3d/test/testSceneWidget.py deleted file mode 100644 index 13ddd37..0000000 --- a/silx/gui/plot3d/test/testSceneWidget.py +++ /dev/null @@ -1,84 +0,0 @@ -# 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 SceneWidget""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "06/03/2019" - - -import unittest - -import numpy - -from silx.utils.testutils import ParametricTestCase -from silx.gui.utils.testutils import TestCaseQt -from silx.gui import qt - -from silx.gui.plot3d.SceneWidget import SceneWidget - - -class TestSceneWidget(TestCaseQt, ParametricTestCase): - """Tests SceneWidget picking feature""" - - def setUp(self): - super(TestSceneWidget, self).setUp() - self.widget = SceneWidget() - self.widget.show() - self.qWaitForWindowExposed(self.widget) - - def tearDown(self): - self.qapp.processEvents() - self.widget.setAttribute(qt.Qt.WA_DeleteOnClose) - self.widget.close() - del self.widget - super(TestSceneWidget, self).tearDown() - - def testFogEffect(self): - """Test fog effect on scene primitive""" - image = self.widget.addImage(numpy.arange(100).reshape(10, 10)) - scatter = self.widget.add3DScatter(*numpy.random.random(4000).reshape(4, -1)) - scatter.setTranslation(10, 10) - scatter.setScale(10, 10, 10) - - self.widget.resetZoom('front') - self.qapp.processEvents() - - self.widget.setFogMode(self.widget.FogMode.LINEAR) - self.qapp.processEvents() - - self.widget.setFogMode(self.widget.FogMode.NONE) - self.qapp.processEvents() - - -def suite(): - testsuite = unittest.TestSuite() - testsuite.addTest( - unittest.defaultTestLoader.loadTestsFromTestCase( - TestSceneWidget)) - return testsuite - - -if __name__ == '__main__': - unittest.main(defaultTest='suite') diff --git a/silx/gui/plot3d/test/testSceneWidgetPicking.py b/silx/gui/plot3d/test/testSceneWidgetPicking.py deleted file mode 100644 index aea30f6..0000000 --- a/silx/gui/plot3d/test/testSceneWidgetPicking.py +++ /dev/null @@ -1,326 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2018-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 SceneWidget picking feature""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "03/10/2018" - - -import unittest - -import numpy - -from silx.utils.testutils import ParametricTestCase -from silx.gui.utils.testutils import TestCaseQt -from silx.gui import qt - -from silx.gui.plot3d.SceneWidget import SceneWidget, items - - -class TestSceneWidgetPicking(TestCaseQt, ParametricTestCase): - """Tests SceneWidget picking feature""" - - def setUp(self): - super(TestSceneWidgetPicking, self).setUp() - self.widget = SceneWidget() - self.widget.resize(300, 300) - self.widget.show() - # self.qWaitForWindowExposed(self.widget) - - def tearDown(self): - self.qapp.processEvents() - self.widget.setAttribute(qt.Qt.WA_DeleteOnClose) - self.widget.close() - del self.widget - super(TestSceneWidgetPicking, self).tearDown() - - def _widgetCenter(self): - """Returns widget center""" - size = self.widget.size() - return size.width() // 2, size.height() // 2 - - def testPickImage(self): - """Test picking of ImageData and ImageRgba items""" - imageData = items.ImageData() - imageData.setData(numpy.arange(100).reshape(10, 10)) - - imageRgba = items.ImageRgba() - imageRgba.setData( - numpy.arange(300, dtype=numpy.uint8).reshape(10, 10, 3)) - - for item in (imageData, imageRgba): - with self.subTest(item=item.__class__.__name__): - # Add item - self.widget.clearItems() - self.widget.addItem(item) - self.widget.resetZoom('front') - self.qapp.processEvents() - - # Picking on data (at widget center) - picking = list(self.widget.pickItems(*self._widgetCenter())) - - self.assertEqual(len(picking), 1) - self.assertIs(picking[0].getItem(), item) - self.assertEqual(picking[0].getPositions('ndc').shape, (1, 3)) - data = picking[0].getData() - self.assertEqual(len(data), 1) - self.assertTrue(numpy.array_equal( - data, - item.getData()[picking[0].getIndices()])) - - # Picking outside data - picking = list(self.widget.pickItems(1, 1)) - self.assertEqual(len(picking), 0) - - def testPickScatter(self): - """Test picking of Scatter2D and Scatter3D items""" - data = numpy.arange(100) - - scatter2d = items.Scatter2D() - scatter2d.setData(x=data, y=data, value=data) - - scatter3d = items.Scatter3D() - scatter3d.setData(x=data, y=data, z=data, value=data) - - for item in (scatter2d, scatter3d): - with self.subTest(item=item.__class__.__name__): - # Add item - self.widget.clearItems() - self.widget.addItem(item) - self.widget.resetZoom('front') - self.qapp.processEvents() - - # Picking on data (at widget center) - picking = list(self.widget.pickItems(*self._widgetCenter())) - - self.assertEqual(len(picking), 1) - self.assertIs(picking[0].getItem(), item) - nbPos = len(picking[0].getPositions('ndc')) - data = picking[0].getData() - self.assertEqual(nbPos, len(data)) - self.assertTrue(numpy.array_equal( - data, - item.getValueData()[picking[0].getIndices()])) - - # Picking outside data - picking = list(self.widget.pickItems(1, 1)) - self.assertEqual(len(picking), 0) - - def testPickVolume(self): - """Test picking of volume CutPlane and Isosurface items""" - for dtype in (numpy.float32, numpy.complex64): - with self.subTest(dtype=dtype): - refData = numpy.arange(10**3, dtype=dtype).reshape(10, 10, 10) - volume = self.widget.addVolume(refData) - if dtype == numpy.complex64: - volume.setComplexMode(volume.ComplexMode.REAL) - refData = numpy.real(refData) - self.widget.resetZoom('front') - - cutplane = volume.getCutPlanes()[0] - if dtype == numpy.complex64: - cutplane.setComplexMode(volume.ComplexMode.REAL) - cutplane.getColormap().setVRange(0, 100) - cutplane.setNormal((0, 0, 1)) - - # Picking on data without anything displayed - cutplane.setVisible(False) - picking = list(self.widget.pickItems(*self._widgetCenter())) - self.assertEqual(len(picking), 0) - - # Picking on data with the cut plane - cutplane.setVisible(True) - picking = list(self.widget.pickItems(*self._widgetCenter())) - - self.assertEqual(len(picking), 1) - self.assertIs(picking[0].getItem(), cutplane) - data = picking[0].getData() - self.assertEqual(len(data), 1) - self.assertEqual(picking[0].getPositions().shape, (1, 3)) - self.assertTrue(numpy.array_equal( - data, - refData[picking[0].getIndices()])) - - # Picking on data with an isosurface - isosurface = volume.addIsosurface( - level=500, color=(1., 0., 0., .5)) - picking = list(self.widget.pickItems(*self._widgetCenter())) - self.assertEqual(len(picking), 2) - self.assertIs(picking[0].getItem(), cutplane) - self.assertIs(picking[1].getItem(), isosurface) - self.assertEqual(picking[1].getPositions().shape, (1, 3)) - data = picking[1].getData() - self.assertEqual(len(data), 1) - self.assertTrue(numpy.array_equal( - data, - refData[picking[1].getIndices()])) - - # Picking outside data - picking = list(self.widget.pickItems(1, 1)) - self.assertEqual(len(picking), 0) - - self.widget.clearItems() - - def testPickMesh(self): - """Test picking of Mesh items""" - - triangles = items.Mesh() - triangles.setData( - position=((0, 0, 0), (1, 0, 0), (1, 1, 0), - (0, 0, 0), (1, 1, 0), (0, 1, 0)), - color=(1, 0, 0, 1), - mode='triangles') - triangleStrip = items.Mesh() - triangleStrip.setData( - position=(((1, 0, 0), (0, 0, 0), (1, 1, 0), (0, 1, 0))), - color=(0, 1, 0, 1), - mode='triangle_strip') - triangleFan = items.Mesh() - triangleFan.setData( - position=((0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0)), - color=(0, 0, 1, 1), - mode='fan') - - for item in (triangles, triangleStrip, triangleFan): - with self.subTest(mode=item.getDrawMode()): - # Add item - self.widget.clearItems() - self.widget.addItem(item) - self.widget.resetZoom('front') - self.qapp.processEvents() - - # Picking on data (at widget center) - picking = list(self.widget.pickItems(*self._widgetCenter())) - - self.assertEqual(len(picking), 1) - self.assertIs(picking[0].getItem(), item) - nbPos = len(picking[0].getPositions()) - data = picking[0].getData() - self.assertEqual(nbPos, len(data)) - self.assertTrue(numpy.array_equal( - data, - item.getPositionData()[picking[0].getIndices()])) - - # Picking outside data - picking = list(self.widget.pickItems(1, 1)) - self.assertEqual(len(picking), 0) - - def testPickMeshWithIndices(self): - """Test picking of Mesh items defined by indices""" - - triangles = items.Mesh() - triangles.setData( - position=((0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0)), - color=(1, 0, 0, 1), - indices=numpy.array( # dummy triangles and square - (0, 0, 1, 0, 1, 2, 1, 2, 3), dtype=numpy.uint8), - mode='triangles') - triangleStrip = items.Mesh() - triangleStrip.setData( - position=((0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0)), - color=(0, 1, 0, 1), - indices=numpy.array( # dummy triangles and square - (1, 0, 0, 1, 2, 3), dtype=numpy.uint8), - mode='triangle_strip') - triangleFan = items.Mesh() - triangleFan.setData( - position=((0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0)), - color=(0, 0, 1, 1), - indices=numpy.array( # dummy triangle, square, dummy - (1, 1, 0, 2, 3, 3), dtype=numpy.uint8), - mode='fan') - - for item in (triangles, triangleStrip, triangleFan): - with self.subTest(mode=item.getDrawMode()): - # Add item - self.widget.clearItems() - self.widget.addItem(item) - self.widget.resetZoom('front') - self.qapp.processEvents() - - # Picking on data (at widget center) - picking = list(self.widget.pickItems(*self._widgetCenter())) - - self.assertEqual(len(picking), 1) - self.assertIs(picking[0].getItem(), item) - nbPos = len(picking[0].getPositions()) - data = picking[0].getData() - self.assertEqual(nbPos, len(data)) - self.assertTrue(numpy.array_equal( - data, - item.getPositionData()[picking[0].getIndices()])) - - # Picking outside data - picking = list(self.widget.pickItems(1, 1)) - self.assertEqual(len(picking), 0) - - def testPickCylindricalMesh(self): - """Test picking of Box, Cylinder and Hexagon items""" - - positions = numpy.array(((0., 0., 0.), (1., 1., 0.), (2., 2., 0.))) - box = items.Box() - box.setData(position=positions) - cylinder = items.Cylinder() - cylinder.setData(position=positions) - hexagon = items.Hexagon() - hexagon.setData(position=positions) - - for item in (box, cylinder, hexagon): - with self.subTest(item=item.__class__.__name__): - # Add item - self.widget.clearItems() - self.widget.addItem(item) - self.widget.resetZoom('front') - self.qapp.processEvents() - - # Picking on data (at widget center) - picking = list(self.widget.pickItems(*self._widgetCenter())) - - self.assertEqual(len(picking), 1) - self.assertIs(picking[0].getItem(), item) - nbPos = len(picking[0].getPositions()) - data = picking[0].getData() - print(item.__class__.__name__, [positions[1]], data) - self.assertTrue(numpy.all(numpy.equal(positions[1], data))) - self.assertEqual(nbPos, len(data)) - self.assertTrue(numpy.array_equal( - data, - item.getPosition()[picking[0].getIndices()])) - - # Picking outside data - picking = list(self.widget.pickItems(1, 1)) - self.assertEqual(len(picking), 0) - - -def suite(): - testsuite = unittest.TestSuite() - testsuite.addTest( - unittest.defaultTestLoader.loadTestsFromTestCase( - TestSceneWidgetPicking)) - return testsuite - - -if __name__ == '__main__': - unittest.main(defaultTest='suite') diff --git a/silx/gui/plot3d/test/testSceneWindow.py b/silx/gui/plot3d/test/testSceneWindow.py deleted file mode 100644 index 8cf6b81..0000000 --- a/silx/gui/plot3d/test/testSceneWindow.py +++ /dev/null @@ -1,245 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2019-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. -# ###########################################################################*/ -"""Test SceneWindow""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "22/03/2019" - - -import unittest - -import numpy - -from silx.utils.testutils import ParametricTestCase -from silx.gui.utils.testutils import TestCaseQt -from silx.gui import qt - -from silx.gui.plot3d.SceneWindow import SceneWindow -from silx.gui.plot3d.items import HeightMapData, HeightMapRGBA - -class TestSceneWindow(TestCaseQt, ParametricTestCase): - """Tests SceneWidget picking feature""" - - def setUp(self): - super(TestSceneWindow, self).setUp() - self.window = SceneWindow() - self.window.show() - self.qWaitForWindowExposed(self.window) - - def tearDown(self): - self.qapp.processEvents() - self.window.setAttribute(qt.Qt.WA_DeleteOnClose) - self.window.close() - del self.window - super(TestSceneWindow, self).tearDown() - - def testAdd(self): - """Test add basic scene primitive""" - sceneWidget = self.window.getSceneWidget() - items = [] - - # RGB image - image = sceneWidget.addImage(numpy.random.random( - 10*10*3).astype(numpy.float32).reshape(10, 10, 3)) - image.setLabel('RGB image') - items.append(image) - self.assertEqual(sceneWidget.getItems(), tuple(items)) - - # Data image - image = sceneWidget.addImage( - numpy.arange(100, dtype=numpy.float32).reshape(10, 10)) - image.setTranslation(10.) - items.append(image) - self.assertEqual(sceneWidget.getItems(), tuple(items)) - - # 2D scatter - scatter = sceneWidget.add2DScatter( - *numpy.random.random(3000).astype(numpy.float32).reshape(3, -1), - index=0) - scatter.setTranslation(0, 10) - scatter.setScale(10, 10, 10) - items.insert(0, scatter) - self.assertEqual(sceneWidget.getItems(), tuple(items)) - - # 3D scatter - scatter = sceneWidget.add3DScatter( - *numpy.random.random(4000).astype(numpy.float32).reshape(4, -1)) - scatter.setTranslation(10, 10) - scatter.setScale(10, 10, 10) - items.append(scatter) - self.assertEqual(sceneWidget.getItems(), tuple(items)) - - # 3D array of float - volume = sceneWidget.addVolume( - numpy.arange(10**3, dtype=numpy.float32).reshape(10, 10, 10)) - volume.setTranslation(0, 0, 10) - volume.setRotation(45, (0, 0, 1)) - volume.addIsosurface(500, 'red') - volume.getCutPlanes()[0].getColormap().setName('viridis') - items.append(volume) - self.assertEqual(sceneWidget.getItems(), tuple(items)) - - # 3D array of complex - volume = sceneWidget.addVolume( - numpy.arange(10**3).reshape(10, 10, 10).astype(numpy.complex64)) - volume.setTranslation(10, 0, 10) - volume.setRotation(45, (0, 0, 1)) - volume.setComplexMode(volume.ComplexMode.REAL) - volume.addIsosurface(500, (1., 0., 0., .5)) - items.append(volume) - self.assertEqual(sceneWidget.getItems(), tuple(items)) - - sceneWidget.resetZoom('front') - self.qapp.processEvents() - - def testHeightMap(self): - """Test height map items""" - sceneWidget = self.window.getSceneWidget() - - height = numpy.arange(10000).reshape(100, 100) /100. - - for shape in ((100, 100), (4, 5), (150, 20), (110, 110)): - with self.subTest(shape=shape): - items = [] - - # Colormapped data height map - data = numpy.arange(numpy.prod(shape)).astype(numpy.float32).reshape(shape) - - heightmap = HeightMapData() - heightmap.setData(height) - heightmap.setColormappedData(data) - heightmap.getColormap().setName('viridis') - items.append(heightmap) - sceneWidget.addItem(heightmap) - - # RGBA height map - colors = numpy.zeros(shape + (3,), dtype=numpy.float32) - colors[:, :, 1] = numpy.random.random(shape) - - heightmap = HeightMapRGBA() - heightmap.setData(height) - heightmap.setColorData(colors) - heightmap.setTranslation(100., 0., 0.) - items.append(heightmap) - sceneWidget.addItem(heightmap) - - self.assertEqual(sceneWidget.getItems(), tuple(items)) - sceneWidget.resetZoom('front') - self.qapp.processEvents() - sceneWidget.clearItems() - - def testChangeContent(self): - """Test add/remove/clear items""" - sceneWidget = self.window.getSceneWidget() - items = [] - - # Add 2 images - image = numpy.arange(100, dtype=numpy.float32).reshape(10, 10) - items.append(sceneWidget.addImage(image)) - items.append(sceneWidget.addImage(image)) - self.qapp.processEvents() - self.assertEqual(sceneWidget.getItems(), tuple(items)) - - # Clear - sceneWidget.clearItems() - self.qapp.processEvents() - self.assertEqual(sceneWidget.getItems(), ()) - - # Add 2 images and remove first one - image = numpy.arange(100, dtype=numpy.float32).reshape(10, 10) - sceneWidget.addImage(image) - items = (sceneWidget.addImage(image),) - self.qapp.processEvents() - - sceneWidget.removeItem(sceneWidget.getItems()[0]) - self.qapp.processEvents() - self.assertEqual(sceneWidget.getItems(), items) - - def testColors(self): - """Test setting scene colors""" - sceneWidget = self.window.getSceneWidget() - - color = qt.QColor(128, 128, 128) - sceneWidget.setBackgroundColor(color) - self.assertEqual(sceneWidget.getBackgroundColor(), color) - - color = qt.QColor(0, 0, 0) - sceneWidget.setForegroundColor(color) - self.assertEqual(sceneWidget.getForegroundColor(), color) - - color = qt.QColor(255, 0, 0) - sceneWidget.setTextColor(color) - self.assertEqual(sceneWidget.getTextColor(), color) - - color = qt.QColor(0, 255, 0) - sceneWidget.setHighlightColor(color) - self.assertEqual(sceneWidget.getHighlightColor(), color) - - self.qapp.processEvents() - - def testInteractiveMode(self): - """Test changing interactive mode""" - sceneWidget = self.window.getSceneWidget() - center = numpy.array((sceneWidget.width() //2, sceneWidget.height() // 2)) - - self.mouseMove(sceneWidget, pos=center) - self.mouseClick(sceneWidget, qt.Qt.LeftButton, pos=center) - - volume = sceneWidget.addVolume( - numpy.arange(10**3).astype(numpy.float32).reshape(10, 10, 10)) - sceneWidget.selection().setCurrentItem( volume.getCutPlanes()[0]) - sceneWidget.resetZoom('side') - - for mode in (None, 'rotate', 'pan', 'panSelectedPlane'): - with self.subTest(mode=mode): - sceneWidget.setInteractiveMode(mode) - self.qapp.processEvents() - self.assertEqual(sceneWidget.getInteractiveMode(), mode) - - self.mouseMove(sceneWidget, pos=center) - self.mousePress(sceneWidget, qt.Qt.LeftButton, pos=center) - self.mouseMove(sceneWidget, pos=center-10) - self.mouseMove(sceneWidget, pos=center-20) - self.mouseRelease(sceneWidget, qt.Qt.LeftButton, pos=center-20) - - self.keyPress(sceneWidget, qt.Qt.Key_Control) - self.mouseMove(sceneWidget, pos=center) - self.mousePress(sceneWidget, qt.Qt.LeftButton, pos=center) - self.mouseMove(sceneWidget, pos=center-10) - self.mouseMove(sceneWidget, pos=center-20) - self.mouseRelease(sceneWidget, qt.Qt.LeftButton, pos=center-20) - self.keyRelease(sceneWidget, qt.Qt.Key_Control) - - -def suite(): - testsuite = unittest.TestSuite() - testsuite.addTest( - unittest.defaultTestLoader.loadTestsFromTestCase( - TestSceneWindow)) - return testsuite - - -if __name__ == '__main__': - unittest.main(defaultTest='suite') diff --git a/silx/gui/plot3d/test/testStatsWidget.py b/silx/gui/plot3d/test/testStatsWidget.py deleted file mode 100644 index bcab1a4..0000000 --- a/silx/gui/plot3d/test/testStatsWidget.py +++ /dev/null @@ -1,216 +0,0 @@ -# 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 silx.gui.plot.StatsWidget with SceneWidget and ScalarFieldView""" - -__authors__ = ["T. Vincent"] -__license__ = "MIT" -__date__ = "25/01/2019" - - -import unittest - -import numpy - -from silx.utils.testutils import ParametricTestCase -from silx.gui.utils.testutils import TestCaseQt -from silx.gui.plot.stats.stats import Stats -from silx.gui import qt - -from silx.gui.plot.StatsWidget import BasicStatsWidget - -from silx.gui.plot3d.ScalarFieldView import ScalarFieldView -from silx.gui.plot3d.SceneWidget import SceneWidget, items - - -class TestSceneWidget(TestCaseQt, ParametricTestCase): - """Tests StatsWidget combined with SceneWidget""" - - def setUp(self): - super(TestSceneWidget, self).setUp() - self.sceneWidget = SceneWidget() - self.sceneWidget.resize(300, 300) - self.sceneWidget.show() - self.statsWidget = BasicStatsWidget() - self.statsWidget.setPlot(self.sceneWidget) - # self.qWaitForWindowExposed(self.sceneWidget) - - def tearDown(self): - Stats._getContext.cache_clear() - self.qapp.processEvents() - self.sceneWidget.setAttribute(qt.Qt.WA_DeleteOnClose) - self.sceneWidget.close() - del self.sceneWidget - self.statsWidget.setAttribute(qt.Qt.WA_DeleteOnClose) - self.statsWidget.close() - del self.statsWidget - super(TestSceneWidget, self).tearDown() - - def test(self): - """Test StatsWidget with SceneWidget""" - # Prepare scene - - # Data image - image = self.sceneWidget.addImage(numpy.arange(100).reshape(10, 10)) - image.setLabel('Image') - # RGB image - imageRGB = self.sceneWidget.addImage( - numpy.arange(300, dtype=numpy.uint8).reshape(10, 10, 3)) - imageRGB.setLabel('RGB Image') - # 2D scatter - data = numpy.arange(100) - scatter2D = self.sceneWidget.add2DScatter(x=data, y=data, value=data) - scatter2D.setLabel('2D Scatter') - # 3D scatter - scatter3D = self.sceneWidget.add3DScatter(x=data, y=data, z=data, value=data) - scatter3D.setLabel('3D Scatter') - # Add a group - group = items.GroupItem() - self.sceneWidget.addItem(group) - # 3D scalar field - data = numpy.arange(64**3).reshape(64, 64, 64) - scalarField = items.ScalarField3D() - scalarField.setData(data, copy=False) - scalarField.setLabel('3D Scalar field') - group.addItem(scalarField) - - statsTable = self.statsWidget._getStatsTable() - - # Test selection only - self.statsWidget.setDisplayOnlyActiveItem(True) - self.assertEqual(statsTable.rowCount(), 0) - - self.sceneWidget.selection().setCurrentItem(group) - self.assertEqual(statsTable.rowCount(), 0) - - for item in (image, scatter2D, scatter3D, scalarField): - with self.subTest('selection only', item=item.getLabel()): - self.sceneWidget.selection().setCurrentItem(item) - self.assertEqual(statsTable.rowCount(), 1) - self._checkItem(item) - - # Test all data - self.statsWidget.setDisplayOnlyActiveItem(False) - self.assertEqual(statsTable.rowCount(), 4) - - for item in (image, scatter2D, scatter3D, scalarField): - with self.subTest('all items', item=item.getLabel()): - self._checkItem(item) - - def _checkItem(self, item): - """Check that item is in StatsTable and that stats are OK - - :param silx.gui.plot3d.items.Item3D item: - """ - if isinstance(item, (items.Scatter2D, items.Scatter3D)): - data = item.getValueData(copy=False) - else: - data = item.getData(copy=False) - - statsTable = self.statsWidget._getStatsTable() - tableItems = statsTable._itemToTableItems(item) - self.assertTrue(len(tableItems) > 0) - self.assertEqual(tableItems['legend'].text(), item.getLabel()) - self.assertEqual(float(tableItems['min'].text()), numpy.min(data)) - self.assertEqual(float(tableItems['max'].text()), numpy.max(data)) - # TODO - - -class TestScalarFieldView(TestCaseQt): - """Tests StatsWidget combined with ScalarFieldView""" - - def setUp(self): - super(TestScalarFieldView, self).setUp() - self.scalarFieldView = ScalarFieldView() - self.scalarFieldView.resize(300, 300) - self.scalarFieldView.show() - self.statsWidget = BasicStatsWidget() - self.statsWidget.setPlot(self.scalarFieldView) - # self.qWaitForWindowExposed(self.sceneWidget) - - def tearDown(self): - Stats._getContext.cache_clear() - self.qapp.processEvents() - self.scalarFieldView.setAttribute(qt.Qt.WA_DeleteOnClose) - self.scalarFieldView.close() - del self.scalarFieldView - self.statsWidget.setAttribute(qt.Qt.WA_DeleteOnClose) - self.statsWidget.close() - del self.statsWidget - super(TestScalarFieldView, self).tearDown() - - def _getTextFor(self, row, name): - """Returns text in table at given row for column name - - :param int row: Row number in the table - :param str name: Column id - :rtype: Union[str,None] - """ - statsTable = self.statsWidget._getStatsTable() - - for column in range(statsTable.columnCount()): - headerItem = statsTable.horizontalHeaderItem(column) - if headerItem.data(qt.Qt.UserRole) == name: - tableItem = statsTable.item(row, column) - return tableItem.text() - - return None - - def test(self): - """Test StatsWidget with ScalarFieldView""" - data = numpy.arange(64**3, dtype=numpy.float64).reshape(64, 64, 64) - self.scalarFieldView.setData(data) - - statsTable = self.statsWidget._getStatsTable() - - # Test selection only - self.statsWidget.setDisplayOnlyActiveItem(True) - self.assertEqual(statsTable.rowCount(), 1) - - # Test all data - self.statsWidget.setDisplayOnlyActiveItem(False) - self.assertEqual(statsTable.rowCount(), 1) - - for column in range(statsTable.columnCount()): - self.assertEqual(float(self._getTextFor(0, 'min')), numpy.min(data)) - self.assertEqual(float(self._getTextFor(0, 'max')), numpy.max(data)) - sum_ = numpy.sum(data) - comz = numpy.sum(numpy.arange(data.shape[0]) * numpy.sum(data, axis=(1, 2))) / sum_ - comy = numpy.sum(numpy.arange(data.shape[1]) * numpy.sum(data, axis=(0, 2))) / sum_ - comx = numpy.sum(numpy.arange(data.shape[2]) * numpy.sum(data, axis=(0, 1))) / sum_ - self.assertEqual(self._getTextFor(0, 'COM'), str((comx, comy, comz))) - - -def suite(): - testsuite = unittest.TestSuite() - testsuite.addTest( - unittest.defaultTestLoader.loadTestsFromTestCase( - TestSceneWidget)) - testsuite.addTest( - unittest.defaultTestLoader.loadTestsFromTestCase( - TestScalarFieldView)) - return testsuite - - -if __name__ == '__main__': - unittest.main(defaultTest='suite') |