summaryrefslogtreecommitdiff
path: root/silx/gui/plot3d/test
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot3d/test')
-rw-r--r--silx/gui/plot3d/test/__init__.py75
-rw-r--r--silx/gui/plot3d/test/testGL.py84
-rw-r--r--silx/gui/plot3d/test/testScalarFieldView.py139
-rw-r--r--silx/gui/plot3d/test/testSceneWidget.py84
-rw-r--r--silx/gui/plot3d/test/testSceneWidgetPicking.py326
-rw-r--r--silx/gui/plot3d/test/testSceneWindow.py245
-rw-r--r--silx/gui/plot3d/test/testStatsWidget.py216
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')