summaryrefslogtreecommitdiff
path: root/silx/gui/plot/test
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/test')
-rw-r--r--silx/gui/plot/test/__init__.py92
-rw-r--r--silx/gui/plot/test/testAlphaSlider.py218
-rw-r--r--silx/gui/plot/test/testColorBar.py354
-rw-r--r--silx/gui/plot/test/testCompareImages.py117
-rw-r--r--silx/gui/plot/test/testComplexImageView.py95
-rw-r--r--silx/gui/plot/test/testCurvesROIWidget.py469
-rw-r--r--silx/gui/plot/test/testImageStack.py197
-rw-r--r--silx/gui/plot/test/testImageView.py136
-rw-r--r--silx/gui/plot/test/testInteraction.py89
-rw-r--r--silx/gui/plot/test/testItem.py340
-rw-r--r--silx/gui/plot/test/testLegendSelector.py142
-rw-r--r--silx/gui/plot/test/testLimitConstraints.py125
-rw-r--r--silx/gui/plot/test/testMaskToolsWidget.py316
-rw-r--r--silx/gui/plot/test/testPixelIntensityHistoAction.py157
-rw-r--r--silx/gui/plot/test/testPlotInteraction.py172
-rwxr-xr-xsilx/gui/plot/test/testPlotWidget.py2072
-rw-r--r--silx/gui/plot/test/testPlotWidgetNoBackend.py631
-rw-r--r--silx/gui/plot/test/testPlotWindow.py185
-rw-r--r--silx/gui/plot/test/testRoiStatsWidget.py290
-rw-r--r--silx/gui/plot/test/testSaveAction.py143
-rw-r--r--silx/gui/plot/test/testScatterMaskToolsWidget.py318
-rw-r--r--silx/gui/plot/test/testScatterView.py134
-rw-r--r--silx/gui/plot/test/testStackView.py261
-rw-r--r--silx/gui/plot/test/testStats.py1058
-rw-r--r--silx/gui/plot/test/testUtilsAxis.py214
-rw-r--r--silx/gui/plot/test/utils.py94
26 files changed, 0 insertions, 8419 deletions
diff --git a/silx/gui/plot/test/__init__.py b/silx/gui/plot/test/__init__.py
deleted file mode 100644
index dfb7c2e..0000000
--- a/silx/gui/plot/test/__init__.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# 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.
-#
-# ###########################################################################*/
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "23/07/2018"
-
-
-import unittest
-
-from .._utils import test
-from . import testColorBar
-from . import testCurvesROIWidget
-from . import testStats
-from . import testAlphaSlider
-from . import testInteraction
-from . import testLegendSelector
-from . import testMaskToolsWidget
-from . import testScatterMaskToolsWidget
-from . import testPlotInteraction
-from . import testPlotWidgetNoBackend
-from . import testPlotWidget
-from . import testPlotWindow
-from . import testStackView
-from . import testImageStack
-from . import testItem
-from . import testUtilsAxis
-from . import testLimitConstraints
-from . import testComplexImageView
-from . import testImageView
-from . import testSaveAction
-from . import testScatterView
-from . import testPixelIntensityHistoAction
-from . import testCompareImages
-from . import testRoiStatsWidget
-
-
-def suite():
- # Lazy-loading to avoid cyclic reference
- from ..tools import test as testTools
-
- test_suite = unittest.TestSuite()
- test_suite.addTests(
- [test.suite(),
- testTools.suite(),
- testColorBar.suite(),
- testCurvesROIWidget.suite(),
- testStats.suite(),
- testAlphaSlider.suite(),
- testInteraction.suite(),
- testLegendSelector.suite(),
- testMaskToolsWidget.suite(),
- testScatterMaskToolsWidget.suite(),
- testPlotInteraction.suite(),
- testPlotWidgetNoBackend.suite(),
- testPlotWidget.suite(),
- testPlotWindow.suite(),
- testStackView.suite(),
- testImageStack.suite(),
- testItem.suite(),
- testUtilsAxis.suite(),
- testLimitConstraints.suite(),
- testComplexImageView.suite(),
- testImageView.suite(),
- testSaveAction.suite(),
- testScatterView.suite(),
- testPixelIntensityHistoAction.suite(),
- testCompareImages.suite(),
- testRoiStatsWidget.suite(),
- ])
- return test_suite
diff --git a/silx/gui/plot/test/testAlphaSlider.py b/silx/gui/plot/test/testAlphaSlider.py
deleted file mode 100644
index 01e6969..0000000
--- a/silx/gui/plot/test/testAlphaSlider.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2017-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.
-#
-# ###########################################################################*/
-"""Tests for ImageAlphaSlider"""
-
-
-__authors__ = ["P. Knobel"]
-__license__ = "MIT"
-__date__ = "28/03/2017"
-
-import numpy
-import unittest
-
-from silx.gui import qt
-from silx.gui.utils.testutils import TestCaseQt
-from silx.gui.plot import PlotWidget
-from silx.gui.plot import AlphaSlider
-
-
-class TestActiveImageAlphaSlider(TestCaseQt):
- def setUp(self):
- super(TestActiveImageAlphaSlider, self).setUp()
- self.plot = PlotWidget()
- self.aslider = AlphaSlider.ActiveImageAlphaSlider(plot=self.plot)
- self.aslider.setOrientation(qt.Qt.Horizontal)
-
- toolbar = qt.QToolBar("plot", self.plot)
- toolbar.addWidget(self.aslider)
- self.plot.addToolBar(toolbar)
-
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- self.mouseMove(self.plot) # Move to center
- self.qapp.processEvents()
-
- def tearDown(self):
- self.qapp.processEvents()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- del self.aslider
-
- super(TestActiveImageAlphaSlider, self).tearDown()
-
- def testWidgetEnabled(self):
- # no active image initially, slider must be deactivate
- self.assertFalse(self.aslider.isEnabled())
-
- self.plot.addImage(numpy.array([[0, 1, 2], [3, 4, 5]]))
- # now we have an active image
- self.assertTrue(self.aslider.isEnabled())
-
- self.plot.setActiveImage(None)
- self.assertFalse(self.aslider.isEnabled())
-
- def testGetImage(self):
- self.plot.addImage(numpy.array([[0, 1, 2], [3, 4, 5]]))
- self.assertEqual(self.plot.getActiveImage(),
- self.aslider.getItem())
-
- self.plot.addImage(numpy.array([[0, 1, 3], [2, 4, 6]]), legend="2")
- self.plot.setActiveImage("2")
- self.assertEqual(self.plot.getImage("2"),
- self.aslider.getItem())
-
- def testGetAlpha(self):
- self.plot.addImage(numpy.array([[0, 1, 2], [3, 4, 5]]), legend="1")
- self.aslider.setValue(137)
- self.assertAlmostEqual(self.aslider.getAlpha(),
- 137. / 255)
-
-
-class TestNamedImageAlphaSlider(TestCaseQt):
- def setUp(self):
- super(TestNamedImageAlphaSlider, self).setUp()
- self.plot = PlotWidget()
- self.aslider = AlphaSlider.NamedImageAlphaSlider(plot=self.plot)
- self.aslider.setOrientation(qt.Qt.Horizontal)
-
- toolbar = qt.QToolBar("plot", self.plot)
- toolbar.addWidget(self.aslider)
- self.plot.addToolBar(toolbar)
-
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- self.mouseMove(self.plot) # Move to center
- self.qapp.processEvents()
-
- def tearDown(self):
- self.qapp.processEvents()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- del self.aslider
-
- super(TestNamedImageAlphaSlider, self).tearDown()
-
- def testWidgetEnabled(self):
- # no image set initially, slider must be deactivate
- self.assertFalse(self.aslider.isEnabled())
-
- self.plot.addImage(numpy.array([[0, 1, 2], [3, 4, 5]]), legend="1")
- self.aslider.setLegend("1")
- # now we have an image set
- self.assertTrue(self.aslider.isEnabled())
-
- def testGetImage(self):
- self.plot.addImage(numpy.array([[0, 1, 2], [3, 4, 5]]), legend="1")
- self.plot.addImage(numpy.array([[0, 1, 3], [2, 4, 6]]), legend="2")
- self.aslider.setLegend("1")
- self.assertEqual(self.plot.getImage("1"),
- self.aslider.getItem())
-
- self.aslider.setLegend("2")
- self.assertEqual(self.plot.getImage("2"),
- self.aslider.getItem())
-
- def testGetAlpha(self):
- self.plot.addImage(numpy.array([[0, 1, 2], [3, 4, 5]]), legend="1")
- self.aslider.setLegend("1")
- self.aslider.setValue(128)
- self.assertAlmostEqual(self.aslider.getAlpha(),
- 128. / 255)
-
-
-class TestNamedScatterAlphaSlider(TestCaseQt):
- def setUp(self):
- super(TestNamedScatterAlphaSlider, self).setUp()
- self.plot = PlotWidget()
- self.aslider = AlphaSlider.NamedScatterAlphaSlider(plot=self.plot)
- self.aslider.setOrientation(qt.Qt.Horizontal)
-
- toolbar = qt.QToolBar("plot", self.plot)
- toolbar.addWidget(self.aslider)
- self.plot.addToolBar(toolbar)
-
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- self.mouseMove(self.plot) # Move to center
- self.qapp.processEvents()
-
- def tearDown(self):
- self.qapp.processEvents()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- del self.aslider
-
- super(TestNamedScatterAlphaSlider, self).tearDown()
-
- def testWidgetEnabled(self):
- # no Scatter set initially, slider must be deactivate
- self.assertFalse(self.aslider.isEnabled())
-
- self.plot.addScatter([0, 1, 2], [2, 3, 4], [5, 6, 7],
- legend="1")
- self.aslider.setLegend("1")
- # now we have an image set
- self.assertTrue(self.aslider.isEnabled())
-
- def testGetScatter(self):
- self.plot.addScatter([0, 1, 2], [2, 3, 4], [5, 6, 7],
- legend="1")
- self.plot.addScatter([0, 10, 20], [20, 30, 40], [50, 60, 70],
- legend="2")
- self.aslider.setLegend("1")
- self.assertEqual(self.plot.getScatter("1"),
- self.aslider.getItem())
-
- self.aslider.setLegend("2")
- self.assertEqual(self.plot.getScatter("2"),
- self.aslider.getItem())
-
- def testGetAlpha(self):
- self.plot.addScatter([0, 10, 20], [20, 30, 40], [50, 60, 70],
- legend="1")
- self.aslider.setLegend("1")
- self.aslider.setValue(128)
- self.assertAlmostEqual(self.aslider.getAlpha(),
- 128. / 255)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- # test_suite.addTest(positionInfoTestSuite)
- for testClass in (TestActiveImageAlphaSlider, TestNamedImageAlphaSlider,
- TestNamedScatterAlphaSlider):
- test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(
- testClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testColorBar.py b/silx/gui/plot/test/testColorBar.py
deleted file mode 100644
index a6f141c..0000000
--- a/silx/gui/plot/test/testColorBar.py
+++ /dev/null
@@ -1,354 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2020 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 tests for ColorBar featues and sub widgets of Colorbar module"""
-
-__authors__ = ["H. Payno"]
-__license__ = "MIT"
-__date__ = "24/04/2018"
-
-import unittest
-from silx.gui.utils.testutils import TestCaseQt
-from silx.gui.plot.ColorBar import _ColorScale
-from silx.gui.plot.ColorBar import ColorBarWidget
-from silx.gui.colors import Colormap
-from silx.gui import colors
-from silx.gui.plot import Plot2D
-from silx.gui import qt
-import numpy
-
-
-class TestColorScale(TestCaseQt):
- """Test that interaction with the colorScale is correct"""
- def setUp(self):
- super(TestColorScale, self).setUp()
- self.colorScaleWidget = _ColorScale(colormap=None, parent=None)
- self.colorScaleWidget.show()
- self.qWaitForWindowExposed(self.colorScaleWidget)
-
- def tearDown(self):
- self.qapp.processEvents()
- self.colorScaleWidget.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.colorScaleWidget.close()
- del self.colorScaleWidget
- super(TestColorScale, self).tearDown()
-
- def testNoColormap(self):
- """Test _ColorScale without a colormap"""
- colormap = self.colorScaleWidget.getColormap()
- self.assertIsNone(colormap)
-
- def testRelativePositionLinear(self):
- self.colorMapLin1 = Colormap(name='gray',
- normalization=Colormap.LINEAR,
- vmin=0.0,
- vmax=1.0)
- self.colorScaleWidget.setColormap(self.colorMapLin1)
-
- self.assertTrue(
- self.colorScaleWidget.getValueFromRelativePosition(0.25) == 0.25)
- self.assertTrue(
- self.colorScaleWidget.getValueFromRelativePosition(0.5) == 0.5)
- self.assertTrue(
- self.colorScaleWidget.getValueFromRelativePosition(1.0) == 1.0)
-
- self.colorMapLin2 = Colormap(name='viridis',
- normalization=Colormap.LINEAR,
- vmin=-10,
- vmax=0)
- self.colorScaleWidget.setColormap(self.colorMapLin2)
-
- self.assertTrue(
- self.colorScaleWidget.getValueFromRelativePosition(0.25) == -7.5)
- self.assertTrue(
- self.colorScaleWidget.getValueFromRelativePosition(0.5) == -5.0)
- self.assertTrue(
- self.colorScaleWidget.getValueFromRelativePosition(1.0) == 0.0)
-
- def testRelativePositionLog(self):
- self.colorMapLog1 = Colormap(name='temperature',
- normalization=Colormap.LOGARITHM,
- vmin=1.0,
- vmax=100.0)
-
- self.colorScaleWidget.setColormap(self.colorMapLog1)
-
- val = self.colorScaleWidget.getValueFromRelativePosition(1.0)
- self.assertAlmostEqual(val, 100.0)
-
- val = self.colorScaleWidget.getValueFromRelativePosition(0.5)
- self.assertAlmostEqual(val, 10.0)
-
- val = self.colorScaleWidget.getValueFromRelativePosition(0.0)
- self.assertTrue(val == 1.0)
-
-
-class TestNoAutoscale(TestCaseQt):
- """Test that ticks and color displayed are correct in the case of a colormap
- with no autoscale
- """
-
- def setUp(self):
- super(TestNoAutoscale, self).setUp()
- self.plot = Plot2D()
- self.colorBar = self.plot.getColorBarWidget()
- self.colorBar.setVisible(True) # Makes sure the colormap is visible
- self.tickBar = self.colorBar.getColorScaleBar().getTickBar()
- self.colorScale = self.colorBar.getColorScaleBar().getColorScale()
-
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- def tearDown(self):
- self.qapp.processEvents()
- self.tickBar = None
- self.colorScale = None
- del self.colorBar
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- super(TestNoAutoscale, self).tearDown()
-
- def testLogNormNoAutoscale(self):
- colormapLog = Colormap(name='gray',
- normalization=Colormap.LOGARITHM,
- vmin=1.0,
- vmax=100.0)
-
- data = numpy.linspace(10, 1e10, 9).reshape(3, 3)
- self.plot.addImage(data=data, colormap=colormapLog, legend='toto')
- self.plot.setActiveImage('toto')
-
- # test Ticks
- self.tickBar.setTicksNumber(10)
- self.tickBar.computeTicks()
-
- ticksTh = numpy.linspace(1.0, 100.0, 10)
- ticksTh = 10**ticksTh
- numpy.array_equal(self.tickBar.ticks, ticksTh)
-
- # test ColorScale
- val = self.colorScale.getValueFromRelativePosition(1.0)
- self.assertAlmostEqual(val, 100.0)
-
- val = self.colorScale.getValueFromRelativePosition(0.0)
- self.assertTrue(val == 1.0)
-
- def testLinearNormNoAutoscale(self):
- colormapLog = Colormap(name='gray',
- normalization=Colormap.LINEAR,
- vmin=-4,
- vmax=5)
-
- data = numpy.linspace(1, 9, 9).reshape(3, 3)
- self.plot.addImage(data=data, colormap=colormapLog, legend='toto')
- self.plot.setActiveImage('toto')
-
- # test Ticks
- self.tickBar.setTicksNumber(10)
- self.tickBar.computeTicks()
-
- numpy.array_equal(self.tickBar.ticks, numpy.linspace(-4, 5, 10))
-
- # test ColorScale
- val = self.colorScale.getValueFromRelativePosition(1.0)
- self.assertTrue(val == 5.0)
-
- val = self.colorScale.getValueFromRelativePosition(0.0)
- self.assertTrue(val == -4.0)
-
-
-class TestColorBarWidget(TestCaseQt):
- """Test interaction with the ColorBarWidget"""
-
- def setUp(self):
- super(TestColorBarWidget, self).setUp()
- self.plot = Plot2D()
- self.colorBar = self.plot.getColorBarWidget()
- self.colorBar.setVisible(True) # Makes sure the colormap is visible
-
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- def tearDown(self):
- self.qapp.processEvents()
- del self.colorBar
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- super(TestColorBarWidget, self).tearDown()
-
- def testEmptyColorBar(self):
- colorBar = ColorBarWidget(parent=None)
- colorBar.show()
- self.qWaitForWindowExposed(colorBar)
-
- def testNegativeColormaps(self):
- """test the behavior of the ColorBarWidget in the case of negative
- values
-
- Note : colorbar is modified by the Plot directly not ColorBarWidget
- """
- colormapLog = Colormap(name='gray',
- normalization=Colormap.LOGARITHM,
- vmin=None,
- vmax=None)
-
- data = numpy.array([-5, -4, 0, 2, 3, 5, 10, 20, 30])
- data = data.reshape(3, 3)
- self.plot.addImage(data=data, colormap=colormapLog, legend='toto')
- self.plot.setActiveImage('toto')
-
- # default behavior when with log and negative values: should set vmin
- # to 1 and vmax to 10
- self.assertTrue(self.colorBar.getColorScaleBar().minVal == 2)
- self.assertTrue(self.colorBar.getColorScaleBar().maxVal == 30)
-
- # if data is positive
- data[data < 1] = data.max()
- self.plot.addImage(data=data,
- colormap=colormapLog,
- legend='toto',
- replace=True)
- self.plot.setActiveImage('toto')
-
- self.assertTrue(self.colorBar.getColorScaleBar().minVal == data.min())
- self.assertTrue(self.colorBar.getColorScaleBar().maxVal == data.max())
-
- def testPlotAssocation(self):
- """Make sure the ColorBarWidget is properly connected with the plot"""
- colormap = Colormap(name='gray',
- normalization=Colormap.LINEAR,
- vmin=None,
- vmax=None)
-
- # make sure that default settings are the same (but a copy of the
- self.colorBar.setPlot(self.plot)
- self.assertTrue(
- self.colorBar.getColormap() is self.plot.getDefaultColormap())
-
- data = numpy.linspace(0, 10, 100).reshape(10, 10)
- self.plot.addImage(data=data, colormap=colormap, legend='toto')
- self.plot.setActiveImage('toto')
-
- # make sure the modification of the colormap has been done
- self.assertFalse(
- self.colorBar.getColormap() is self.plot.getDefaultColormap())
- self.assertTrue(
- self.colorBar.getColormap() is colormap)
-
- # test that colorbar is updated when default plot colormap changes
- self.plot.clear()
- plotColormap = Colormap(name='gray',
- normalization=Colormap.LOGARITHM,
- vmin=None,
- vmax=None)
- self.plot.setDefaultColormap(plotColormap)
- self.assertTrue(self.colorBar.getColormap() is plotColormap)
-
- def testColormapWithoutRange(self):
- """Test with a colormap with vmin==vmax"""
- colormap = Colormap(name='gray',
- normalization=Colormap.LINEAR,
- vmin=1.0,
- vmax=1.0)
- self.colorBar.setColormap(colormap)
-
-
-class TestColorBarUpdate(TestCaseQt):
- """Test that the ColorBar is correctly updated when the signal 'sigChanged'
- of the colormap is emitted
- """
-
- def setUp(self):
- super(TestColorBarUpdate, self).setUp()
- self.plot = Plot2D()
- self.colorBar = self.plot.getColorBarWidget()
- self.colorBar.setVisible(True) # Makes sure the colormap is visible
- self.colorBar.setPlot(self.plot)
-
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
- self.data = numpy.random.rand(9).reshape(3, 3)
-
- def tearDown(self):
- self.qapp.processEvents()
- del self.colorBar
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- super(TestColorBarUpdate, self).tearDown()
-
- def testUpdateColorMap(self):
- colormap = Colormap(name='gray',
- normalization='linear',
- vmin=0,
- vmax=1)
-
- # check inital state
- self.plot.addImage(data=self.data, colormap=colormap, legend='toto')
- self.plot.setActiveImage('toto')
-
- self.assertTrue(self.colorBar.getColorScaleBar().minVal == 0)
- self.assertTrue(self.colorBar.getColorScaleBar().maxVal == 1)
- self.assertTrue(
- self.colorBar.getColorScaleBar().getTickBar()._vmin == 0)
- self.assertTrue(
- self.colorBar.getColorScaleBar().getTickBar()._vmax == 1)
- self.assertIsInstance(
- self.colorBar.getColorScaleBar().getTickBar()._normalizer,
- colors._LinearNormalization)
-
- # update colormap
- colormap.setVMin(0.5)
- self.assertTrue(self.colorBar.getColorScaleBar().minVal == 0.5)
- self.assertTrue(
- self.colorBar.getColorScaleBar().getTickBar()._vmin == 0.5)
-
- colormap.setVMax(0.8)
- self.assertTrue(self.colorBar.getColorScaleBar().maxVal == 0.8)
- self.assertTrue(
- self.colorBar.getColorScaleBar().getTickBar()._vmax == 0.8)
-
- colormap.setNormalization('log')
- self.assertIsInstance(
- self.colorBar.getColorScaleBar().getTickBar()._normalizer,
- colors._LogarithmicNormalization)
-
- # TODO : should also check that if the colormap is changing then values (especially in log scale)
- # should be coherent if in autoscale
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for ui in (TestColorScale, TestNoAutoscale, TestColorBarWidget,
- TestColorBarUpdate):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(ui))
-
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testCompareImages.py b/silx/gui/plot/test/testCompareImages.py
deleted file mode 100644
index ed6942a..0000000
--- a/silx/gui/plot/test/testCompareImages.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-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.
-#
-# ###########################################################################*/
-"""Tests for CompareImages widget"""
-
-__authors__ = ["H. Payno"]
-__license__ = "MIT"
-__date__ = "23/07/2018"
-
-import unittest
-import numpy
-import weakref
-
-from silx.gui.utils.testutils import TestCaseQt
-from silx.gui.plot.CompareImages import CompareImages
-
-
-class TestCompareImages(TestCaseQt):
- """Test that CompareImages widget is working in some cases"""
-
- def setUp(self):
- super(TestCompareImages, self).setUp()
- self.widget = CompareImages()
-
- def tearDown(self):
- ref = weakref.ref(self.widget)
- self.widget = None
- self.qWaitForDestroy(ref)
- super(TestCompareImages, self).tearDown()
-
- def testIntensityImage(self):
- image1 = numpy.random.rand(10, 10)
- image2 = numpy.random.rand(10, 10)
- self.widget.setData(image1, image2)
-
- def testRgbImage(self):
- image1 = numpy.random.randint(0, 255, size=(10, 10, 3))
- image2 = numpy.random.randint(0, 255, size=(10, 10, 3))
- self.widget.setData(image1, image2)
-
- def testRgbaImage(self):
- image1 = numpy.random.randint(0, 255, size=(10, 10, 4))
- image2 = numpy.random.randint(0, 255, size=(10, 10, 4))
- self.widget.setData(image1, image2)
-
- def testVizualisations(self):
- image1 = numpy.random.rand(10, 10)
- image2 = numpy.random.rand(10, 10)
- self.widget.setData(image1, image2)
- for mode in CompareImages.VisualizationMode:
- self.widget.setVisualizationMode(mode)
-
- def testAlignemnt(self):
- image1 = numpy.random.rand(10, 10)
- image2 = numpy.random.rand(5, 5)
- self.widget.setData(image1, image2)
- for mode in CompareImages.AlignmentMode:
- self.widget.setAlignmentMode(mode)
-
- def testGetPixel(self):
- image1 = numpy.random.rand(11, 11)
- image2 = numpy.random.rand(5, 5)
- image1[5, 5] = 111.111
- image2[2, 2] = 222.222
- self.widget.setData(image1, image2)
- expectedValue = {}
- expectedValue[CompareImages.AlignmentMode.CENTER] = 222.222
- expectedValue[CompareImages.AlignmentMode.STRETCH] = 222.222
- expectedValue[CompareImages.AlignmentMode.ORIGIN] = None
- for mode in expectedValue.keys():
- self.widget.setAlignmentMode(mode)
- data = self.widget.getRawPixelData(11 / 2.0, 11 / 2.0)
- data1, data2 = data
- self.assertEqual(data1, 111.111)
- self.assertEqual(data2, expectedValue[mode])
-
- def testImageEmpty(self):
- self.widget.setData(image1=None, image2=None)
- self.assertTrue(self.widget.getRawPixelData(11 / 2.0, 11 / 2.0) == (None, None))
-
- def testSetImageSeparately(self):
- self.widget.setImage1(numpy.random.rand(10, 10))
- self.widget.setImage2(numpy.random.rand(10, 10))
- for mode in CompareImages.VisualizationMode:
- self.widget.setVisualizationMode(mode)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
- test_suite.addTest(loadTests(TestCompareImages))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testComplexImageView.py b/silx/gui/plot/test/testComplexImageView.py
deleted file mode 100644
index 4ac3488..0000000
--- a/silx/gui/plot/test/testComplexImageView.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2017-2020 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 suite for :class:`ComplexImageView`"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "17/01/2018"
-
-
-import unittest
-import logging
-import numpy
-
-from silx.utils.testutils import ParametricTestCase
-from silx.gui.plot import ComplexImageView
-
-from .utils import PlotWidgetTestCase
-
-
-logger = logging.getLogger(__name__)
-
-
-class TestComplexImageView(PlotWidgetTestCase, ParametricTestCase):
- """Test suite of ComplexImageView widget"""
-
- def _createPlot(self):
- return ComplexImageView.ComplexImageView()
-
- def testPlot2DComplex(self):
- """Test API of ComplexImageView widget"""
- data = numpy.array(((0, 1j), (1, 1 + 1j)), dtype=numpy.complex64)
- self.plot.setData(data)
- self.plot.setKeepDataAspectRatio(True)
- self.plot.getPlot().resetZoom()
- self.qWait(100)
-
- # Test colormap API
- colormap = self.plot.getColormap().copy()
- colormap.setName('magma')
- self.plot.setColormap(colormap)
- self.qWait(100)
-
- # Test all modes
- modes = self.plot.supportedComplexModes()
- for mode in modes:
- with self.subTest(mode=mode):
- self.plot.setComplexMode(mode)
- self.qWait(100)
-
- # Test origin and scale API
- self.plot.setScale((2, 1))
- self.qWait(100)
- self.plot.setOrigin((1, 1))
- self.qWait(100)
-
- # Test no data
- self.plot.setData(numpy.zeros((0, 0), dtype=numpy.complex64))
- self.qWait(100)
-
- # Test float data
- self.plot.setData(numpy.arange(100, dtype=numpy.float64).reshape(10, 10))
- self.qWait(100)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(
- TestComplexImageView))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testCurvesROIWidget.py b/silx/gui/plot/test/testCurvesROIWidget.py
deleted file mode 100644
index 6a0ab8c..0000000
--- a/silx/gui/plot/test/testCurvesROIWidget.py
+++ /dev/null
@@ -1,469 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2020 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 tests for CurvesROIWidget"""
-
-__authors__ = ["T. Vincent", "P. Knobel", "H. Payno"]
-__license__ = "MIT"
-__date__ = "16/11/2017"
-
-
-import logging
-import os.path
-import unittest
-from collections import OrderedDict
-import numpy
-
-from silx.gui import qt
-from silx.gui.plot import items
-from silx.gui.plot import Plot1D
-from silx.test.utils import temp_dir
-from silx.gui.utils.testutils import TestCaseQt, SignalListener
-from silx.gui.plot import PlotWindow, CurvesROIWidget
-from silx.gui.plot.CurvesROIWidget import ROITable
-from silx.gui.utils.testutils import getQToolButtonFromAction
-from silx.gui.plot.PlotInteraction import ItemsInteraction
-
-_logger = logging.getLogger(__name__)
-
-
-class TestCurvesROIWidget(TestCaseQt):
- """Basic test for CurvesROIWidget"""
-
- def setUp(self):
- super(TestCurvesROIWidget, self).setUp()
- self.plot = PlotWindow()
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- self.widget = self.plot.getCurvesRoiDockWidget()
-
- self.widget.show()
- self.qWaitForWindowExposed(self.widget)
-
- def tearDown(self):
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
-
- self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.widget.close()
- del self.widget
-
- super(TestCurvesROIWidget, self).tearDown()
-
- def testDummyAPI(self):
- """Simple test of the getRois and setRois API"""
- roi_neg = CurvesROIWidget.ROI(name='negative', fromdata=-20,
- todata=-10, type_='X')
- roi_pos = CurvesROIWidget.ROI(name='positive', fromdata=10,
- todata=20, type_='X')
-
- self.widget.roiWidget.setRois((roi_pos, roi_neg))
-
- rois_defs = self.widget.roiWidget.getRois()
- self.widget.roiWidget.setRois(rois=rois_defs)
-
- def testWithCurves(self):
- """Plot with curves: test all ROI widget buttons"""
- for offset in range(2):
- self.plot.addCurve(numpy.arange(1000),
- offset + numpy.random.random(1000),
- legend=str(offset))
-
- # Add two ROI
- self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton)
- self.qWait(200)
- self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton)
- self.qWait(200)
-
- # Change active curve
- self.plot.setActiveCurve(str(1))
-
- # Delete a ROI
- self.mouseClick(self.widget.roiWidget.delButton, qt.Qt.LeftButton)
- self.qWait(200)
-
- with temp_dir() as tmpDir:
- self.tmpFile = os.path.join(tmpDir, 'test.ini')
-
- # Save ROIs
- self.widget.roiWidget.save(self.tmpFile)
- self.assertTrue(os.path.isfile(self.tmpFile))
- self.assertEqual(len(self.widget.getRois()), 2)
-
- # Reset ROIs
- self.mouseClick(self.widget.roiWidget.resetButton,
- qt.Qt.LeftButton)
- self.qWait(200)
- rois = self.widget.getRois()
- self.assertEqual(len(rois), 1)
- roiID = list(rois.keys())[0]
- self.assertEqual(rois[roiID].getName(), 'ICR')
-
- # Load ROIs
- self.widget.roiWidget.load(self.tmpFile)
- self.assertEqual(len(self.widget.getRois()), 2)
-
- del self.tmpFile
-
- def testMiddleMarker(self):
- """Test with middle marker enabled"""
- self.widget.roiWidget.roiTable.setMiddleROIMarkerFlag(True)
-
- # Add a ROI
- self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton)
-
- for roiID in self.widget.roiWidget.roiTable._markersHandler._roiMarkerHandlers:
- handler = self.widget.roiWidget.roiTable._markersHandler._roiMarkerHandlers[roiID]
- assert handler.getMarker('min')
- xleftMarker = handler.getMarker('min').getXPosition()
- xMiddleMarker = handler.getMarker('middle').getXPosition()
- xRightMarker = handler.getMarker('max').getXPosition()
- thValue = xleftMarker + (xRightMarker - xleftMarker) / 2.
- self.assertAlmostEqual(xMiddleMarker, thValue)
-
- def testAreaCalculation(self):
- """Test result of area calculation"""
- x = numpy.arange(100.)
- y = numpy.arange(100.)
-
- # Add two curves
- self.plot.addCurve(x, y, legend="positive")
- self.plot.addCurve(-x, y, legend="negative")
-
- # Make sure there is an active curve and it is the positive one
- self.plot.setActiveCurve("positive")
-
- # Add two ROIs
- roi_neg = CurvesROIWidget.ROI(name='negative', fromdata=-20,
- todata=-10, type_='X')
- roi_pos = CurvesROIWidget.ROI(name='positive', fromdata=10,
- todata=20, type_='X')
-
- self.widget.roiWidget.setRois((roi_pos, roi_neg))
-
- posCurve = self.plot.getCurve('positive')
- negCurve = self.plot.getCurve('negative')
-
- self.assertEqual(roi_pos.computeRawAndNetArea(posCurve),
- (numpy.trapz(y=[10, 20], x=[10, 20]),
- 0.0))
- self.assertEqual(roi_pos.computeRawAndNetArea(negCurve),
- (0.0, 0.0))
- self.assertEqual(roi_neg.computeRawAndNetArea(posCurve),
- ((0.0), 0.0))
- self.assertEqual(roi_neg.computeRawAndNetArea(negCurve),
- ((-150.0), 0.0))
-
- def testCountsCalculation(self):
- """Test result of count calculation"""
- x = numpy.arange(100.)
- y = numpy.arange(100.)
-
- # Add two curves
- self.plot.addCurve(x, y, legend="positive")
- self.plot.addCurve(-x, y, legend="negative")
-
- # Make sure there is an active curve and it is the positive one
- self.plot.setActiveCurve("positive")
-
- # Add two ROIs
- roi_neg = CurvesROIWidget.ROI(name='negative', fromdata=-20,
- todata=-10, type_='X')
- roi_pos = CurvesROIWidget.ROI(name='positive', fromdata=10,
- todata=20, type_='X')
-
- self.widget.roiWidget.setRois((roi_pos, roi_neg))
-
- posCurve = self.plot.getCurve('positive')
- negCurve = self.plot.getCurve('negative')
-
- self.assertEqual(roi_pos.computeRawAndNetCounts(posCurve),
- (y[10:21].sum(), 0.0))
- self.assertEqual(roi_pos.computeRawAndNetCounts(negCurve),
- (0.0, 0.0))
- self.assertEqual(roi_neg.computeRawAndNetCounts(posCurve),
- ((0.0), 0.0))
- self.assertEqual(roi_neg.computeRawAndNetCounts(negCurve),
- (y[10:21].sum(), 0.0))
-
- def testDeferedInit(self):
- """Test behavior of the deferedInit"""
- x = numpy.arange(100.)
- y = numpy.arange(100.)
- self.plot.addCurve(x=x, y=y, legend="name", replace="True")
- roisDefs = OrderedDict([
- ["range1",
- OrderedDict([["from", 20], ["to", 200], ["type", "energy"]])],
- ["range2",
- OrderedDict([["from", 300], ["to", 500], ["type", "energy"]])]
- ])
-
- roiWidget = self.plot.getCurvesRoiDockWidget().roiWidget
- self.plot.getCurvesRoiDockWidget().setRois(roisDefs)
- self.assertEqual(len(roiWidget.getRois()), len(roisDefs))
- self.plot.getCurvesRoiDockWidget().setVisible(True)
- self.assertEqual(len(roiWidget.getRois()), len(roisDefs))
-
- def testDictCompatibility(self):
- """Test that ROI api is valid with dict and not information is lost"""
- roiDict = {'from': 20, 'to': 200, 'type': 'energy', 'comment': 'no',
- 'name': 'myROI', 'calibration': [1, 2, 3]}
- roi = CurvesROIWidget.ROI._fromDict(roiDict)
- self.assertEqual(roi.toDict(), roiDict)
-
- def testShowAllROI(self):
- """Test the show allROI action"""
- x = numpy.arange(100.)
- y = numpy.arange(100.)
- self.plot.addCurve(x=x, y=y, legend="name", replace="True")
-
- roisDefsDict = {
- "range1": {"from": 20, "to": 200,"type": "energy"},
- "range2": {"from": 300, "to": 500, "type": "energy"}
- }
-
- roisDefsObj = (
- CurvesROIWidget.ROI(name='range3', fromdata=20, todata=200,
- type_='energy'),
- CurvesROIWidget.ROI(name='range4', fromdata=300, todata=500,
- type_='energy')
- )
- self.widget.roiWidget.showAllMarkers(True)
- roiWidget = self.plot.getCurvesRoiDockWidget().roiWidget
- roiWidget.setRois(roisDefsDict)
- markers = [item for item in self.plot.getItems()
- if isinstance(item, items.MarkerBase)]
- self.assertEqual(len(markers), 2*3)
-
- markersHandler = self.widget.roiWidget.roiTable._markersHandler
- roiWidget.showAllMarkers(True)
- ICRROI = markersHandler.getVisibleRois()
- self.assertEqual(len(ICRROI), 2)
-
- roiWidget.showAllMarkers(False)
- ICRROI = markersHandler.getVisibleRois()
- self.assertEqual(len(ICRROI), 1)
-
- roiWidget.setRois(roisDefsObj)
- self.qapp.processEvents()
- markers = [item for item in self.plot.getItems()
- if isinstance(item, items.MarkerBase)]
- self.assertEqual(len(markers), 2*3)
-
- markersHandler = self.widget.roiWidget.roiTable._markersHandler
- roiWidget.showAllMarkers(True)
- ICRROI = markersHandler.getVisibleRois()
- self.assertEqual(len(ICRROI), 2)
-
- roiWidget.showAllMarkers(False)
- ICRROI = markersHandler.getVisibleRois()
- self.assertEqual(len(ICRROI), 1)
-
- def testRoiEdition(self):
- """Make sure if the ROI object is edited the ROITable will be updated
- """
- roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5)
- self.widget.roiWidget.setRois((roi, ))
-
- x = (0, 1, 1, 2, 2, 3)
- y = (1, 1, 2, 2, 1, 1)
- self.plot.addCurve(x=x, y=y, legend='linearCurve')
- self.plot.setActiveCurve(legend='linearCurve')
- self.widget.calculateROIs()
-
- roiTable = self.widget.roiWidget.roiTable
- indexesColumns = CurvesROIWidget.ROITable.COLUMNS_INDEX
- itemRawCounts = roiTable.item(0, indexesColumns['Raw Counts'])
- itemNetCounts = roiTable.item(0, indexesColumns['Net Counts'])
-
- self.assertTrue(itemRawCounts.text() == '8.0')
- self.assertTrue(itemNetCounts.text() == '2.0')
-
- itemRawArea = roiTable.item(0, indexesColumns['Raw Area'])
- itemNetArea = roiTable.item(0, indexesColumns['Net Area'])
-
- self.assertTrue(itemRawArea.text() == '4.0')
- self.assertTrue(itemNetArea.text() == '1.0')
-
- roi.setTo(2)
- itemRawArea = roiTable.item(0, indexesColumns['Raw Area'])
- self.assertTrue(itemRawArea.text() == '3.0')
- roi.setFrom(1)
- itemRawArea = roiTable.item(0, indexesColumns['Raw Area'])
- self.assertTrue(itemRawArea.text() == '2.0')
-
- def testRemoveActiveROI(self):
- """Test widget behavior when removing the active ROI"""
- roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5)
- self.widget.roiWidget.setRois((roi,))
-
- self.widget.roiWidget.roiTable.setActiveRoi(None)
- self.assertEqual(len(self.widget.roiWidget.roiTable.selectedItems()), 0)
- self.widget.roiWidget.setRois((roi,))
- self.plot.setActiveCurve(legend='linearCurve')
- self.widget.calculateROIs()
-
- def testEmitCurrentROI(self):
- """Test behavior of the CurvesROIWidget.sigROISignal"""
- roi = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5)
- self.widget.roiWidget.setRois((roi,))
- signalListener = SignalListener()
- self.widget.roiWidget.sigROISignal.connect(signalListener.partial())
- self.widget.show()
- self.qapp.processEvents()
- self.assertEqual(signalListener.callCount(), 0)
- self.assertIs(self.widget.roiWidget.roiTable.activeRoi, roi)
- roi.setFrom(0.0)
- self.qapp.processEvents()
- self.assertEqual(signalListener.callCount(), 0)
- roi.setFrom(0.3)
- self.qapp.processEvents()
- self.assertEqual(signalListener.callCount(), 1)
-
-
-class TestRoiWidgetSignals(TestCaseQt):
- """Test Signals emitted by the RoiWidgetSignals"""
-
- def setUp(self):
- self.plot = Plot1D()
- x = range(20)
- y = range(20)
- self.plot.addCurve(x, y, legend='curve0')
- self.listener = SignalListener()
- self.curves_roi_widget = self.plot.getCurvesRoiWidget()
- self.curves_roi_widget.sigROISignal.connect(self.listener)
- assert self.curves_roi_widget.isVisible() is False
- assert self.listener.callCount() == 0
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- toolButton = getQToolButtonFromAction(self.plot.getRoiAction())
- self.mouseClick(widget=toolButton, button=qt.Qt.LeftButton)
-
- self.curves_roi_widget.show()
- self.qWaitForWindowExposed(self.curves_roi_widget)
-
- def tearDown(self):
- self.plot = None
-
- def testSigROISignalAddRmRois(self):
- """Test SigROISignal when adding and removing ROIS"""
- self.assertEqual(self.listener.callCount(), 1)
- self.listener.clear()
-
- roi1 = CurvesROIWidget.ROI(name='linear', fromdata=0, todata=5)
- self.curves_roi_widget.roiTable.registerROI(roi1)
- self.assertEqual(self.listener.callCount(), 1)
- self.assertTrue(self.listener.arguments()[0][0]['current'] == 'linear')
- self.listener.clear()
-
- roi2 = CurvesROIWidget.ROI(name='linear2', fromdata=0, todata=5)
- self.curves_roi_widget.roiTable.registerROI(roi2)
- self.assertEqual(self.listener.callCount(), 1)
- self.assertTrue(self.listener.arguments()[0][0]['current'] == 'linear2')
- self.listener.clear()
-
- self.curves_roi_widget.roiTable.removeROI(roi2)
- self.assertEqual(self.listener.callCount(), 1)
- self.assertTrue(self.curves_roi_widget.roiTable.activeRoi == roi1)
- self.assertTrue(self.listener.arguments()[0][0]['current'] == 'linear')
- self.listener.clear()
-
- self.curves_roi_widget.roiTable.deleteActiveRoi()
- self.assertEqual(self.listener.callCount(), 1)
- self.assertTrue(self.curves_roi_widget.roiTable.activeRoi is None)
- self.assertTrue(self.listener.arguments()[0][0]['current'] is None)
- self.listener.clear()
-
- self.curves_roi_widget.roiTable.registerROI(roi1)
- self.assertEqual(self.listener.callCount(), 1)
- self.assertTrue(self.listener.arguments()[0][0]['current'] == 'linear')
- self.assertTrue(self.curves_roi_widget.roiTable.activeRoi == roi1)
- self.listener.clear()
- self.qapp.processEvents()
-
- self.curves_roi_widget.roiTable.removeROI(roi1)
- self.qapp.processEvents()
- self.assertEqual(self.listener.callCount(), 1)
- self.assertTrue(self.listener.arguments()[0][0]['current'] == 'ICR')
- self.listener.clear()
-
- def testSigROISignalModifyROI(self):
- """Test SigROISignal when modifying it"""
- self.curves_roi_widget.roiTable.setMiddleROIMarkerFlag(True)
- roi1 = CurvesROIWidget.ROI(name='linear', fromdata=2, todata=5)
- self.curves_roi_widget.roiTable.registerROI(roi1)
- self.curves_roi_widget.roiTable.setActiveRoi(roi1)
-
- # test modify the roi2 object
- self.listener.clear()
- roi1.setFrom(0.56)
- self.assertEqual(self.listener.callCount(), 1)
- self.listener.clear()
- roi1.setTo(2.56)
- self.assertEqual(self.listener.callCount(), 1)
- self.listener.clear()
- roi1.setName('linear2')
- self.assertEqual(self.listener.callCount(), 1)
- self.listener.clear()
- roi1.setType('new type')
- self.assertEqual(self.listener.callCount(), 1)
-
- # modify roi limits (from the gui)
- roi_marker_handler = self.curves_roi_widget.roiTable._markersHandler.getMarkerHandler(roi1.getID())
- for marker_type in ('min', 'max', 'middle'):
- with self.subTest(marker_type=marker_type):
- self.listener.clear()
- marker = roi_marker_handler.getMarker(marker_type)
- self.qapp.processEvents()
- items_interaction = ItemsInteraction(plot=self.plot)
- x_pix, y_pix = self.plot.dataToPixel(marker.getXPosition(), 1)
- items_interaction.beginDrag(x_pix, y_pix)
- self.qapp.processEvents()
- items_interaction.endDrag(x_pix+10, y_pix)
- self.qapp.processEvents()
- self.assertEqual(self.listener.callCount(), 1)
-
- def testSetActiveCurve(self):
- """Test sigRoiSignal when set an active curve"""
- roi1 = CurvesROIWidget.ROI(name='linear', fromdata=2, todata=5)
- self.curves_roi_widget.roiTable.registerROI(roi1)
- self.curves_roi_widget.roiTable.setActiveRoi(roi1)
- self.listener.clear()
- self.plot.setActiveCurve('curve0')
- self.assertEqual(self.listener.callCount(), 0)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for TestClass in (TestCurvesROIWidget,):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testImageStack.py b/silx/gui/plot/test/testImageStack.py
deleted file mode 100644
index 9c21469..0000000
--- a/silx/gui/plot/test/testImageStack.py
+++ /dev/null
@@ -1,197 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2020 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 tests for ImageStack"""
-
-__authors__ = ["H. Payno"]
-__license__ = "MIT"
-__date__ = "15/01/2020"
-
-
-import unittest
-import tempfile
-import numpy
-import h5py
-
-from silx.gui import qt
-from silx.gui.utils.testutils import TestCaseQt
-from silx.io.url import DataUrl
-from silx.gui.plot.ImageStack import ImageStack
-from silx.gui.utils.testutils import SignalListener
-from collections import OrderedDict
-import os
-import time
-import shutil
-
-
-class TestImageStack(TestCaseQt):
- """Simple test of the Image stack"""
-
- def setUp(self):
- TestCaseQt.setUp(self)
- self.urls = OrderedDict()
- self._raw_data = {}
- self._folder = tempfile.mkdtemp()
- self._n_urls = 10
- file_name = os.path.join(self._folder, 'test_inage_stack_file.h5')
- with h5py.File(file_name, 'w') as h5f:
- for i in range(self._n_urls):
- width = numpy.random.randint(10, 40)
- height = numpy.random.randint(10, 40)
- raw_data = numpy.random.random((width, height))
- self._raw_data[i] = raw_data
- h5f[str(i)] = raw_data
- self.urls[i] = DataUrl(file_path=file_name,
- data_path=str(i),
- scheme='silx')
- self.widget = ImageStack()
-
- self.urlLoadedListener = SignalListener()
- self.widget.sigLoaded.connect(self.urlLoadedListener)
-
- self.currentUrlChangedListener = SignalListener()
- self.widget.sigCurrentUrlChanged.connect(self.currentUrlChangedListener)
-
- def tearDown(self):
- shutil.rmtree(self._folder)
- self.widget.setAttribute(qt.Qt.WA_DeleteOnClose, True)
- self.widget.close()
- TestCaseQt.setUp(self)
-
- def testControls(self):
- """Test that selection using the url table and the slider are working
- """
- self.widget.show()
- self.assertEqual(self.widget.getCurrentUrl(), None)
- self.assertEqual(self.widget.getCurrentUrlIndex(), None)
- self.widget.setUrls(list(self.urls.values()))
-
- # wait for image to be loaded
- self._waitUntilUrlLoaded()
-
- self.assertEqual(self.widget.getCurrentUrl(), self.urls[0])
-
- # make sure all image are loaded
- self.assertEqual(self.urlLoadedListener.callCount(), self._n_urls)
- numpy.testing.assert_array_equal(
- self.widget.getPlotWidget().getActiveImage(just_legend=False).getData(),
- self._raw_data[0])
- self.assertEqual(self.widget._slider.value(), 0)
-
- self.widget._urlsTable.setUrl(self.urls[4])
- numpy.testing.assert_array_equal(
- self.widget.getPlotWidget().getActiveImage(just_legend=False).getData(),
- self._raw_data[4])
- self.assertEqual(self.widget._slider.value(), 4)
- self.assertEqual(self.widget.getCurrentUrl(), self.urls[4])
- self.assertEqual(self.widget.getCurrentUrlIndex(), 4)
-
- self.widget._slider.setUrlIndex(6)
- numpy.testing.assert_array_equal(
- self.widget.getPlotWidget().getActiveImage(just_legend=False).getData(),
- self._raw_data[6])
- self.assertEqual(self.widget._urlsTable.currentItem().text(),
- self.urls[6].path())
-
- def testCurrentUrlSignals(self):
- """Test emission of 'currentUrlChangedListener'"""
- # check initialization
- self.assertEqual(self.currentUrlChangedListener.callCount(), 0)
- self.widget.setUrls(list(self.urls.values()))
- self.qapp.processEvents()
- time.sleep(0.5)
- self.qapp.processEvents()
- # once loaded the two signals should have been sended
- self.assertEqual(self.currentUrlChangedListener.callCount(), 1)
- # if the slider is stuck to the same position no signal should be
- # emitted
- self.qapp.processEvents()
- time.sleep(0.5)
- self.qapp.processEvents()
- self.assertEqual(self.widget._slider.value(), 0)
- self.assertEqual(self.currentUrlChangedListener.callCount(), 1)
- # if slider position is changed, one of each signal should have been
- # emitted
- self.widget._urlsTable.setUrl(self.urls[4])
- self.qapp.processEvents()
- time.sleep(1.5)
- self.qapp.processEvents()
- self.assertEqual(self.currentUrlChangedListener.callCount(), 2)
-
- def testUtils(self):
- """Test that some utils functions are working"""
- self.widget.show()
- self.widget.setUrls(list(self.urls.values()))
- self.assertEqual(len(self.widget.getUrls()), len(self.urls))
-
- # wait for image to be loaded
- self._waitUntilUrlLoaded()
-
- urls_values = list(self.urls.values())
- self.assertEqual(urls_values[0], self.urls[0])
- self.assertEqual(urls_values[7], self.urls[7])
-
- self.assertEqual(self.widget._getNextUrl(urls_values[2]).path(),
- urls_values[3].path())
- self.assertEqual(self.widget._getPreviousUrl(urls_values[0]), None)
- self.assertEqual(self.widget._getPreviousUrl(urls_values[6]).path(),
- urls_values[5].path())
-
- self.assertEqual(self.widget._getNNextUrls(2, urls_values[0]),
- urls_values[1:3])
- self.assertEqual(self.widget._getNNextUrls(5, urls_values[7]),
- urls_values[8:])
- self.assertEqual(self.widget._getNPreviousUrls(3, urls_values[2]),
- urls_values[:2])
- self.assertEqual(self.widget._getNPreviousUrls(5, urls_values[8]),
- urls_values[3:8])
-
- def _waitUntilUrlLoaded(self, timeout=2.0):
- """Wait until all image urls are loaded"""
- loop_duration = 0.2
- remaining_duration = timeout
- while(len(self.widget._loadingThreads) > 0 and remaining_duration > 0):
- remaining_duration -= loop_duration
- time.sleep(loop_duration)
- self.qapp.processEvents()
-
- if remaining_duration <= 0.0:
- remaining_urls = []
- for thread_ in self.widget._loadingThreads:
- remaining_urls.append(thread_.url.path())
- mess = 'All images are not loaded after the time out. ' \
- 'Remaining urls are: ' + str(remaining_urls)
- raise TimeoutError(mess)
- return True
-
-
-def suite():
- test_suite = unittest.TestSuite()
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestImageStack))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testImageView.py b/silx/gui/plot/test/testImageView.py
deleted file mode 100644
index 3c8d84c..0000000
--- a/silx/gui/plot/test/testImageView.py
+++ /dev/null
@@ -1,136 +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.
-#
-# ###########################################################################*/
-"""Basic tests for PlotWindow"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "24/04/2018"
-
-
-import unittest
-import numpy
-
-from silx.gui import qt
-from silx.gui.utils.testutils import TestCaseQt
-
-from silx.gui.plot import ImageView
-from silx.gui.colors import Colormap
-
-
-class TestImageView(TestCaseQt):
- """Tests of ImageView widget."""
-
- def setUp(self):
- super(TestImageView, self).setUp()
- self.plot = ImageView()
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- def tearDown(self):
- self.qapp.processEvents()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- self.qapp.processEvents()
- super(TestImageView, self).tearDown()
-
- def testSetImage(self):
- """Test setImage"""
- image = numpy.arange(100).reshape(10, 10)
-
- self.plot.setImage(image, reset=True)
- self.qWait(100)
- self.assertEqual(self.plot.getXAxis().getLimits(), (0, 10))
- self.assertEqual(self.plot.getYAxis().getLimits(), (0, 10))
-
- # With reset=False
- self.plot.setImage(image[::2, ::2], reset=False)
- self.qWait(100)
- self.assertEqual(self.plot.getXAxis().getLimits(), (0, 10))
- self.assertEqual(self.plot.getYAxis().getLimits(), (0, 10))
-
- self.plot.setImage(image, origin=(10, 20), scale=(2, 4), reset=False)
- self.qWait(100)
- self.assertEqual(self.plot.getXAxis().getLimits(), (0, 10))
- self.assertEqual(self.plot.getYAxis().getLimits(), (0, 10))
-
- # With reset=True
- self.plot.setImage(image, origin=(1, 2), scale=(1, 0.5), reset=True)
- self.qWait(100)
- self.assertEqual(self.plot.getXAxis().getLimits(), (1, 11))
- self.assertEqual(self.plot.getYAxis().getLimits(), (2, 7))
-
- self.plot.setImage(image[::2, ::2], reset=True)
- self.qWait(100)
- self.assertEqual(self.plot.getXAxis().getLimits(), (0, 5))
- self.assertEqual(self.plot.getYAxis().getLimits(), (0, 5))
-
- def testColormap(self):
- """Test get|setColormap"""
- image = numpy.arange(100).reshape(10, 10)
- self.plot.setImage(image)
-
- # Colormap as dict
- self.plot.setColormap({'name': 'viridis',
- 'normalization': 'log',
- 'autoscale': False,
- 'vmin': 0,
- 'vmax': 1})
- colormap = self.plot.getColormap()
- self.assertEqual(colormap.getName(), 'viridis')
- self.assertEqual(colormap.getNormalization(), 'log')
- self.assertEqual(colormap.getVMin(), 0)
- self.assertEqual(colormap.getVMax(), 1)
-
- # Colormap as keyword arguments
- self.plot.setColormap(colormap='magma',
- normalization='linear',
- autoscale=True,
- vmin=1,
- vmax=2)
- self.assertEqual(colormap.getName(), 'magma')
- self.assertEqual(colormap.getNormalization(), 'linear')
- self.assertEqual(colormap.getVMin(), None)
- self.assertEqual(colormap.getVMax(), None)
-
- # Update colormap with keyword argument
- self.plot.setColormap(normalization='log')
- self.assertEqual(colormap.getNormalization(), 'log')
-
- # Colormap as Colormap object
- cmap = Colormap()
- self.plot.setColormap(cmap)
- self.assertIs(self.plot.getColormap(), cmap)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestImageView))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testInteraction.py b/silx/gui/plot/test/testInteraction.py
deleted file mode 100644
index a47337e..0000000
--- a/silx/gui/plot/test/testInteraction.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2020 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.
-#
-# ###########################################################################*/
-"""Tests from interaction state machines"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "18/02/2016"
-
-
-import unittest
-
-from silx.gui.plot import Interaction
-
-
-class TestInteraction(unittest.TestCase):
- def testClickOrDrag(self):
- """Minimalistic test for click or drag state machine."""
- events = []
-
- class TestClickOrDrag(Interaction.ClickOrDrag):
- def click(self, x, y, btn):
- events.append(('click', x, y, btn))
-
- def beginDrag(self, x, y, btn):
- events.append(('beginDrag', x, y, btn))
-
- def drag(self, x, y, btn):
- events.append(('drag', x, y, btn))
-
- def endDrag(self, start, end, btn):
- events.append(('endDrag', start, end, btn))
-
- clickOrDrag = TestClickOrDrag()
-
- # click
- clickOrDrag.handleEvent('press', 10, 10, Interaction.LEFT_BTN)
- self.assertEqual(len(events), 0)
-
- clickOrDrag.handleEvent('release', 10, 10, Interaction.LEFT_BTN)
- self.assertEqual(len(events), 1)
- self.assertEqual(events[0], ('click', 10, 10, Interaction.LEFT_BTN))
-
- # drag
- events = []
- clickOrDrag.handleEvent('press', 10, 10, Interaction.LEFT_BTN)
- self.assertEqual(len(events), 0)
- clickOrDrag.handleEvent('move', 15, 10)
- self.assertEqual(len(events), 2) # Received beginDrag and drag
- self.assertEqual(events[0], ('beginDrag', 10, 10, Interaction.LEFT_BTN))
- self.assertEqual(events[1], ('drag', 15, 10, Interaction.LEFT_BTN))
- clickOrDrag.handleEvent('move', 20, 10)
- self.assertEqual(len(events), 3)
- self.assertEqual(events[-1], ('drag', 20, 10, Interaction.LEFT_BTN))
- clickOrDrag.handleEvent('release', 20, 10, Interaction.LEFT_BTN)
- self.assertEqual(len(events), 4)
- self.assertEqual(events[-1], ('endDrag', (10, 10), (20, 10), Interaction.LEFT_BTN))
-
-
-def suite():
- test_suite = unittest.TestSuite()
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestInteraction))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testItem.py b/silx/gui/plot/test/testItem.py
deleted file mode 100644
index 8dacdea..0000000
--- a/silx/gui/plot/test/testItem.py
+++ /dev/null
@@ -1,340 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2017-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.
-#
-# ###########################################################################*/
-"""Tests for PlotWidget items."""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "01/09/2017"
-
-
-import unittest
-
-import numpy
-
-from silx.gui.utils.testutils import SignalListener
-from silx.gui.plot.items import ItemChangedType
-from silx.gui.plot import items
-from .utils import PlotWidgetTestCase
-
-
-class TestSigItemChangedSignal(PlotWidgetTestCase):
- """Test item's sigItemChanged signal"""
-
- def testCurveChanged(self):
- """Test sigItemChanged for curve"""
- self.plot.addCurve(numpy.arange(10), numpy.arange(10), legend='test')
- curve = self.plot.getCurve('test')
-
- listener = SignalListener()
- curve.sigItemChanged.connect(listener)
-
- # Test for signal in Item class
- curve.setVisible(False)
- curve.setVisible(True)
- curve.setZValue(100)
-
- # Test for signals in PointsBase class
- curve.setData(numpy.arange(100), numpy.arange(100))
-
- # SymbolMixIn
- curve.setSymbol('Circle')
- curve.setSymbol('d')
- curve.setSymbolSize(20)
-
- # AlphaMixIn
- curve.setAlpha(0.5)
-
- # Test for signals in Curve class
- # ColorMixIn
- curve.setColor('yellow')
- # YAxisMixIn
- curve.setYAxis('right')
- # FillMixIn
- curve.setFill(True)
- # LineMixIn
- curve.setLineStyle(':')
- curve.setLineStyle(':') # Not sending event
- curve.setLineWidth(2)
-
- self.assertEqual(listener.arguments(argumentIndex=0),
- [ItemChangedType.VISIBLE,
- ItemChangedType.VISIBLE,
- ItemChangedType.ZVALUE,
- ItemChangedType.DATA,
- ItemChangedType.SYMBOL,
- ItemChangedType.SYMBOL,
- ItemChangedType.SYMBOL_SIZE,
- ItemChangedType.ALPHA,
- ItemChangedType.COLOR,
- ItemChangedType.YAXIS,
- ItemChangedType.FILL,
- ItemChangedType.LINE_STYLE,
- ItemChangedType.LINE_WIDTH])
-
- def testHistogramChanged(self):
- """Test sigItemChanged for Histogram"""
- self.plot.addHistogram(
- numpy.arange(10), edges=numpy.arange(11), legend='test')
- histogram = self.plot.getHistogram('test')
- listener = SignalListener()
- histogram.sigItemChanged.connect(listener)
-
- # Test signals in Histogram class
- histogram.setData(numpy.zeros(10), numpy.arange(11))
-
- self.assertEqual(listener.arguments(argumentIndex=0),
- [ItemChangedType.DATA])
-
- def testImageDataChanged(self):
- """Test sigItemChanged for ImageData"""
- self.plot.addImage(numpy.arange(100).reshape(10, 10), legend='test')
- image = self.plot.getImage('test')
-
- listener = SignalListener()
- image.sigItemChanged.connect(listener)
-
- # ColormapMixIn
- colormap = self.plot.getDefaultColormap().copy()
- image.setColormap(colormap)
- image.getColormap().setName('viridis')
-
- # Test of signals in ImageBase class
- image.setOrigin(10)
- image.setScale(2)
-
- # Test of signals in ImageData class
- image.setData(numpy.ones((10, 10)))
-
- self.assertEqual(listener.arguments(argumentIndex=0),
- [ItemChangedType.COLORMAP,
- ItemChangedType.COLORMAP,
- ItemChangedType.POSITION,
- ItemChangedType.SCALE,
- ItemChangedType.COLORMAP,
- ItemChangedType.DATA])
-
- def testImageRgbaChanged(self):
- """Test sigItemChanged for ImageRgba"""
- self.plot.addImage(numpy.ones((10, 10, 3)), legend='rgb')
- image = self.plot.getImage('rgb')
-
- listener = SignalListener()
- image.sigItemChanged.connect(listener)
-
- # Test of signals in ImageRgba class
- image.setData(numpy.zeros((10, 10, 3)))
-
- self.assertEqual(listener.arguments(argumentIndex=0),
- [ItemChangedType.DATA])
-
- def testMarkerChanged(self):
- """Test sigItemChanged for markers"""
- self.plot.addMarker(10, 20, legend='test')
- marker = self.plot._getMarker('test')
-
- listener = SignalListener()
- marker.sigItemChanged.connect(listener)
-
- # Test signals in _BaseMarker
- marker.setPosition(10, 10)
- marker.setPosition(10, 10) # Not sending event
- marker.setText('toto')
- self.assertEqual(listener.arguments(argumentIndex=0),
- [ItemChangedType.POSITION,
- ItemChangedType.TEXT])
-
- # XMarker
- self.plot.addXMarker(10, legend='x')
- marker = self.plot._getMarker('x')
-
- listener = SignalListener()
- marker.sigItemChanged.connect(listener)
- marker.setPosition(20, 20)
- self.assertEqual(listener.arguments(argumentIndex=0),
- [ItemChangedType.POSITION])
-
- # YMarker
- self.plot.addYMarker(10, legend='x')
- marker = self.plot._getMarker('x')
-
- listener = SignalListener()
- marker.sigItemChanged.connect(listener)
- marker.setPosition(20, 20)
- self.assertEqual(listener.arguments(argumentIndex=0),
- [ItemChangedType.POSITION])
-
- def testScatterChanged(self):
- """Test sigItemChanged for scatter"""
- data = numpy.arange(10)
- self.plot.addScatter(data, data, data, legend='test')
- scatter = self.plot.getScatter('test')
-
- listener = SignalListener()
- scatter.sigItemChanged.connect(listener)
-
- # ColormapMixIn
- scatter.getColormap().setName('viridis')
-
- # Test of signals in Scatter class
- scatter.setData((0, 1, 2), (1, 0, 2), (0, 1, 2))
-
- # Visualization mode changed
- scatter.setVisualization(scatter.Visualization.SOLID)
-
- self.assertEqual(listener.arguments(),
- [(ItemChangedType.COLORMAP,),
- (ItemChangedType.COLORMAP,),
- (ItemChangedType.DATA,),
- (ItemChangedType.VISUALIZATION_MODE,)])
-
- def testShapeChanged(self):
- """Test sigItemChanged for shape"""
- data = numpy.array((1., 10.))
- self.plot.addShape(data, data, legend='test', shape='rectangle')
- shape = self.plot._getItem(kind='item', legend='test')
-
- listener = SignalListener()
- shape.sigItemChanged.connect(listener)
-
- shape.setOverlay(True)
- shape.setPoints(((2., 2.), (3., 3.)))
-
- self.assertEqual(listener.arguments(),
- [(ItemChangedType.OVERLAY,),
- (ItemChangedType.DATA,)])
-
-
-class TestSymbol(PlotWidgetTestCase):
- """Test item's symbol """
-
- def test(self):
- """Test sigItemChanged for curve"""
- self.plot.addCurve(numpy.arange(10), numpy.arange(10), legend='test')
- curve = self.plot.getCurve('test')
-
- # SymbolMixIn
- curve.setSymbol('o')
- name = curve.getSymbolName()
- self.assertEqual('Circle', name)
-
- name = curve.getSymbolName('d')
- self.assertEqual('Diamond', name)
-
-
-class TestVisibleExtent(PlotWidgetTestCase):
- """Test item's visible extent feature"""
-
- def testGetVisibleBounds(self):
- """Test Item.getVisibleBounds"""
-
- # Create test items (with a bounding box of x: [1,3], y: [0,2])
- curve = items.Curve()
- curve.setData((1, 2, 3), (0, 1, 2))
-
- histogram = items.Histogram()
- histogram.setData((0, 1, 2), (1, 5/3, 7/3, 3))
-
- image = items.ImageData()
- image.setOrigin((1, 0))
- image.setData(numpy.arange(4).reshape(2, 2))
-
- scatter = items.Scatter()
- scatter.setData((1, 2, 3), (0, 1, 2), (1, 2, 3))
-
- bbox = items.BoundingRect()
- bbox.setBounds((1, 3, 0, 2))
-
- xaxis, yaxis = self.plot.getXAxis(), self.plot.getYAxis()
- for item in (curve, histogram, image, scatter, bbox):
- with self.subTest(item=item):
- xaxis.setLimits(0, 100)
- yaxis.setLimits(0, 100)
- self.plot.addItem(item)
- self.assertEqual(item.getVisibleBounds(), (1., 3., 0., 2.))
-
- xaxis.setLimits(0.5, 2.5)
- self.assertEqual(item.getVisibleBounds(), (1, 2.5, 0., 2.))
-
- yaxis.setLimits(0.5, 1.5)
- self.assertEqual(item.getVisibleBounds(), (1, 2.5, 0.5, 1.5))
-
- item.setVisible(False)
- self.assertIsNone(item.getVisibleBounds())
-
- self.plot.clear()
-
- def testVisibleExtentTracking(self):
- """Test Item's visible extent tracking"""
- image = items.ImageData()
- image.setData(numpy.arange(6).reshape(2, 3))
-
- listener = SignalListener()
- image._sigVisibleBoundsChanged.connect(listener)
- image._setVisibleBoundsTracking(True)
- self.assertTrue(image._isVisibleBoundsTracking())
-
- self.plot.addItem(image)
- self.assertEqual(listener.callCount(), 1)
-
- self.plot.getXAxis().setLimits(0, 1)
- self.assertEqual(listener.callCount(), 2)
-
- self.plot.hide()
- self.qapp.processEvents()
- # No event here
- self.assertEqual(listener.callCount(), 2)
-
- self.plot.getXAxis().setLimits(1, 2)
- # No event since PlotWidget is hidden, delayed to PlotWidget show
- self.assertEqual(listener.callCount(), 2)
-
- self.plot.show()
- self.qapp.processEvents()
- # Receives delayed event now
- self.assertEqual(listener.callCount(), 3)
-
- image.setOrigin((-1, -1))
- self.assertEqual(listener.callCount(), 4)
-
- image.setVisible(False)
- image.setOrigin((0, 0))
- # No event since item is not visible
- self.assertEqual(listener.callCount(), 4)
-
- image.setVisible(True)
- # Receives delayed event now
- self.assertEqual(listener.callCount(), 5)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
- for klass in (TestSigItemChangedSignal, TestSymbol, TestVisibleExtent):
- test_suite.addTest(loadTests(klass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testLegendSelector.py b/silx/gui/plot/test/testLegendSelector.py
deleted file mode 100644
index de5ffde..0000000
--- a/silx/gui/plot/test/testLegendSelector.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2004-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 tests for PlotWidget"""
-
-__authors__ = ["T. Rueter", "T. Vincent"]
-__license__ = "MIT"
-__date__ = "15/05/2017"
-
-
-import logging
-import unittest
-
-from silx.gui import qt
-from silx.gui.utils.testutils import TestCaseQt
-from silx.gui.plot import LegendSelector
-
-
-_logger = logging.getLogger(__name__)
-
-
-class TestLegendSelector(TestCaseQt):
- """Basic test for LegendSelector"""
-
- def testLegendSelector(self):
- """Test copied from __main__ of LegendSelector in PyMca"""
- class Notifier(qt.QObject):
- def __init__(self):
- qt.QObject.__init__(self)
- self.chk = True
-
- def signalReceived(self, **kw):
- obj = self.sender()
- _logger.info('NOTIFIER -- signal received\n\tsender: %s',
- str(obj))
-
- notifier = Notifier()
-
- legends = ['Legend0',
- 'Legend1',
- 'Long Legend 2',
- 'Foo Legend 3',
- 'Even Longer Legend 4',
- 'Short Leg 5',
- 'Dot symbol 6',
- 'Comma symbol 7']
- colors = [qt.Qt.darkRed, qt.Qt.green, qt.Qt.yellow, qt.Qt.darkCyan,
- qt.Qt.blue, qt.Qt.darkBlue, qt.Qt.red, qt.Qt.darkYellow]
- symbols = ['o', 't', '+', 'x', 's', 'd', '.', ',']
-
- win = LegendSelector.LegendListView()
- # win = LegendListContextMenu()
- # win = qt.QWidget()
- # layout = qt.QVBoxLayout()
- # layout.setContentsMargins(0,0,0,0)
- llist = []
-
- for _idx, (l, c, s) in enumerate(zip(legends, colors, symbols)):
- ddict = {
- 'color': qt.QColor(c),
- 'linewidth': 4,
- 'symbol': s,
- }
- legend = l
- llist.append((legend, ddict))
- # item = qt.QListWidgetItem(win)
- # legendWidget = LegendListItemWidget(l)
- # legendWidget.icon.setSymbol(s)
- # legendWidget.icon.setColor(qt.QColor(c))
- # layout.addWidget(legendWidget)
- # win.setItemWidget(item, legendWidget)
-
- # win = LegendListItemWidget('Some Legend 1')
- # print(llist)
- model = LegendSelector.LegendModel(legendList=llist)
- win.setModel(model)
- win.setSelectionModel(qt.QItemSelectionModel(model))
- win.setContextMenu()
- # print('Edit triggers: %d'%win.editTriggers())
-
- # win = LegendListWidget(None, legends)
- # win[0].updateItem(ddict)
- # win.setLayout(layout)
- win.sigLegendSignal.connect(notifier.signalReceived)
- win.show()
-
- win.clear()
- win.setLegendList(llist)
-
- self.qWaitForWindowExposed(win)
-
-
-class TestRenameCurveDialog(TestCaseQt):
- """Basic test for RenameCurveDialog"""
-
- def testDialog(self):
- """Create dialog, change name and press OK"""
- self.dialog = LegendSelector.RenameCurveDialog(
- None, 'curve1', ['curve1', 'curve2', 'curve3'])
- self.dialog.open()
- self.qWaitForWindowExposed(self.dialog)
- self.keyClicks(self.dialog.lineEdit, 'changed')
- self.mouseClick(self.dialog.okButton, qt.Qt.LeftButton)
- self.qapp.processEvents()
- ret = self.dialog.result()
- self.assertEqual(ret, qt.QDialog.Accepted)
- newName = self.dialog.getText()
- self.assertEqual(newName, 'curve1changed')
- del self.dialog
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for TestClass in (TestLegendSelector, TestRenameCurveDialog):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testLimitConstraints.py b/silx/gui/plot/test/testLimitConstraints.py
deleted file mode 100644
index 5e7e0b1..0000000
--- a/silx/gui/plot/test/testLimitConstraints.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# 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 setLimitConstaints on the PlotWidget"""
-
-__authors__ = ["V. Valls"]
-__license__ = "MIT"
-__date__ = "30/08/2017"
-
-
-import unittest
-from silx.gui.plot import PlotWidget
-
-
-class TestLimitConstaints(unittest.TestCase):
- """Tests setLimitConstaints class"""
-
- def setUp(self):
- self.plot = PlotWidget()
-
- def tearDown(self):
- self.plot = None
-
- def testApi(self):
- """Test availability of the API"""
- self.plot.getXAxis().setLimitsConstraints(minPos=1, maxPos=10)
- self.plot.getXAxis().setRangeConstraints(minRange=1, maxRange=1)
- self.plot.getYAxis().setLimitsConstraints(minPos=1, maxPos=10)
- self.plot.getYAxis().setRangeConstraints(minRange=1, maxRange=1)
-
- def testXMinMax(self):
- """Test limit constains on x-axis"""
- self.plot.getXAxis().setLimitsConstraints(minPos=0, maxPos=100)
- self.plot.setLimits(xmin=-1, xmax=101, ymin=-1, ymax=101)
- self.assertEqual(self.plot.getXAxis().getLimits(), (0, 100))
- self.assertEqual(self.plot.getYAxis().getLimits(), (-1, 101))
-
- def testYMinMax(self):
- """Test limit constains on y-axis"""
- self.plot.getYAxis().setLimitsConstraints(minPos=0, maxPos=100)
- self.plot.setLimits(xmin=-1, xmax=101, ymin=-1, ymax=101)
- self.assertEqual(self.plot.getXAxis().getLimits(), (-1, 101))
- self.assertEqual(self.plot.getYAxis().getLimits(), (0, 100))
-
- def testMinXRange(self):
- """Test min range constains on x-axis"""
- self.plot.getXAxis().setRangeConstraints(minRange=100)
- self.plot.setLimits(xmin=1, xmax=99, ymin=1, ymax=99)
- limits = self.plot.getXAxis().getLimits()
- self.assertEqual(limits[1] - limits[0], 100)
- limits = self.plot.getYAxis().getLimits()
- self.assertNotEqual(limits[1] - limits[0], 100)
-
- def testMaxXRange(self):
- """Test max range constains on x-axis"""
- self.plot.getXAxis().setRangeConstraints(maxRange=100)
- self.plot.setLimits(xmin=-1, xmax=101, ymin=-1, ymax=101)
- limits = self.plot.getXAxis().getLimits()
- self.assertEqual(limits[1] - limits[0], 100)
- limits = self.plot.getYAxis().getLimits()
- self.assertNotEqual(limits[1] - limits[0], 100)
-
- def testMinYRange(self):
- """Test min range constains on y-axis"""
- self.plot.getYAxis().setRangeConstraints(minRange=100)
- self.plot.setLimits(xmin=1, xmax=99, ymin=1, ymax=99)
- limits = self.plot.getXAxis().getLimits()
- self.assertNotEqual(limits[1] - limits[0], 100)
- limits = self.plot.getYAxis().getLimits()
- self.assertEqual(limits[1] - limits[0], 100)
-
- def testMaxYRange(self):
- """Test max range constains on y-axis"""
- self.plot.getYAxis().setRangeConstraints(maxRange=100)
- self.plot.setLimits(xmin=-1, xmax=101, ymin=-1, ymax=101)
- limits = self.plot.getXAxis().getLimits()
- self.assertNotEqual(limits[1] - limits[0], 100)
- limits = self.plot.getYAxis().getLimits()
- self.assertEqual(limits[1] - limits[0], 100)
-
- def testChangeOfConstraints(self):
- """Test changing of the constraints"""
- self.plot.getXAxis().setRangeConstraints(minRange=10, maxRange=10)
- # There is no more constraints on the range
- self.plot.getXAxis().setRangeConstraints(minRange=None, maxRange=None)
- self.plot.setLimits(xmin=-1, xmax=101, ymin=-1, ymax=101)
- self.assertEqual(self.plot.getXAxis().getLimits(), (-1, 101))
-
- def testSettingConstraints(self):
- """Test setting a constaint (setLimits first then the constaint)"""
- self.plot.setLimits(xmin=-1, xmax=101, ymin=-1, ymax=101)
- self.plot.getXAxis().setLimitsConstraints(minPos=0, maxPos=100)
- self.assertEqual(self.plot.getXAxis().getLimits(), (0, 100))
-
-
-def suite():
- test_suite = unittest.TestSuite()
- loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
- test_suite.addTest(loadTests(TestLimitConstaints))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testMaskToolsWidget.py b/silx/gui/plot/test/testMaskToolsWidget.py
deleted file mode 100644
index c22975f..0000000
--- a/silx/gui/plot/test/testMaskToolsWidget.py
+++ /dev/null
@@ -1,316 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-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.
-#
-# ###########################################################################*/
-"""Basic tests for MaskToolsWidget"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "17/01/2018"
-
-
-import logging
-import os.path
-import unittest
-
-import numpy
-
-from silx.gui import qt
-from silx.test.utils import temp_dir
-from silx.utils.testutils import ParametricTestCase
-from silx.gui.utils.testutils import getQToolButtonFromAction
-from silx.gui.plot import PlotWindow, MaskToolsWidget
-from .utils import PlotWidgetTestCase
-
-import fabio
-
-
-_logger = logging.getLogger(__name__)
-
-
-class TestMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase):
- """Basic test for MaskToolsWidget"""
-
- def _createPlot(self):
- return PlotWindow()
-
- def setUp(self):
- super(TestMaskToolsWidget, self).setUp()
- self.widget = MaskToolsWidget.MaskToolsDockWidget(plot=self.plot, name='TEST')
- self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, self.widget)
- self.maskWidget = self.widget.widget()
-
- def tearDown(self):
- del self.maskWidget
- del self.widget
- super(TestMaskToolsWidget, self).tearDown()
-
- def testEmptyPlot(self):
- """Empty plot, display MaskToolsDockWidget, toggle multiple masks"""
- self.maskWidget.setMultipleMasks('single')
- self.qapp.processEvents()
-
- self.maskWidget.setMultipleMasks('exclusive')
- self.qapp.processEvents()
-
- def _drag(self):
- """Drag from plot center to offset position"""
- plot = self.plot.getWidgetHandle()
- xCenter, yCenter = plot.width() // 2, plot.height() // 2
- offset = min(plot.width(), plot.height()) // 10
-
- pos0 = xCenter, yCenter
- pos1 = xCenter + offset, yCenter + offset
-
- self.mouseMove(plot, pos=(0, 0))
- self.mouseMove(plot, pos=pos0)
- self.qapp.processEvents()
- self.mousePress(plot, qt.Qt.LeftButton, pos=pos0)
- self.qapp.processEvents()
- self.mouseMove(plot, pos=(pos0[0] + offset // 2, pos0[1] + offset // 2))
- self.mouseMove(plot, pos=pos1)
- self.qapp.processEvents()
- self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos1)
- self.qapp.processEvents()
- self.mouseMove(plot, pos=(0, 0))
-
- def _drawPolygon(self):
- """Draw a star polygon in the plot"""
- plot = self.plot.getWidgetHandle()
- x, y = plot.width() // 2, plot.height() // 2
- offset = min(plot.width(), plot.height()) // 10
-
- star = [(x, y + offset),
- (x - offset, y - offset),
- (x + offset, y),
- (x - offset, y),
- (x + offset, y - offset),
- (x, y + offset)] # Close polygon
-
- self.mouseMove(plot, pos=(0, 0))
- for pos in star:
- self.mouseMove(plot, pos=pos)
- self.qapp.processEvents()
- self.mousePress(plot, qt.Qt.LeftButton, pos=pos)
- self.qapp.processEvents()
- self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos)
- self.qapp.processEvents()
-
- def _drawPencil(self):
- """Draw a star polygon in the plot"""
- plot = self.plot.getWidgetHandle()
- x, y = plot.width() // 2, plot.height() // 2
- offset = min(plot.width(), plot.height()) // 10
-
- star = [(x, y + offset),
- (x - offset, y - offset),
- (x + offset, y),
- (x - offset, y),
- (x + offset, y - offset)]
-
- self.mouseMove(plot, pos=(0, 0))
- self.mouseMove(plot, pos=star[0])
- self.mousePress(plot, qt.Qt.LeftButton, pos=star[0])
- for pos in star[1:]:
- self.mouseMove(plot, pos=pos)
- self.mouseRelease(
- plot, qt.Qt.LeftButton, pos=star[-1])
-
- def _isMaskItemSync(self):
- """Check if masks from item and tools are sync or not"""
- if self.maskWidget.isItemMaskUpdated():
- return numpy.all(numpy.equal(
- self.maskWidget.getSelectionMask(),
- self.plot.getActiveImage().getMaskData(copy=False)))
- else:
- return True
-
- def testWithAnImage(self):
- """Plot with an image: test MaskToolsWidget interactions"""
-
- # Add and remove a image (this should enable/disable GUI + change mask)
- self.plot.addImage(numpy.random.random(1024**2).reshape(1024, 1024),
- legend='test')
- self.qapp.processEvents()
-
- self.plot.remove('test', kind='image')
- self.qapp.processEvents()
-
- tests = [((0, 0), (1, 1)),
- ((1000, 1000), (1, 1)),
- ((0, 0), (-1, -1)),
- ((1000, 1000), (-1, -1))]
-
- for itemMaskUpdated in (False, True):
- for origin, scale in tests:
- with self.subTest(origin=origin, scale=scale):
- self.maskWidget.setItemMaskUpdated(itemMaskUpdated)
- self.plot.addImage(numpy.arange(1024**2).reshape(1024, 1024),
- legend='test',
- origin=origin,
- scale=scale)
- self.qapp.processEvents()
-
- self.assertEqual(
- self.maskWidget.isItemMaskUpdated(), itemMaskUpdated)
-
- # Test draw rectangle #
- toolButton = getQToolButtonFromAction(self.maskWidget.rectAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- # mask
- self.maskWidget.maskStateGroup.button(1).click()
- self.qapp.processEvents()
- self._drag()
- self.assertFalse(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
- self.assertTrue(self._isMaskItemSync())
-
- # unmask same region
- self.maskWidget.maskStateGroup.button(0).click()
- self.qapp.processEvents()
- self._drag()
- self.assertTrue(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
- self.assertTrue(self._isMaskItemSync())
-
- # Test draw polygon #
- toolButton = getQToolButtonFromAction(self.maskWidget.polygonAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- # mask
- self.maskWidget.maskStateGroup.button(1).click()
- self.qapp.processEvents()
- self._drawPolygon()
- self.assertFalse(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
- self.assertTrue(self._isMaskItemSync())
-
- # unmask same region
- self.maskWidget.maskStateGroup.button(0).click()
- self.qapp.processEvents()
- self._drawPolygon()
- self.assertTrue(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
- self.assertTrue(self._isMaskItemSync())
-
- # Test draw pencil #
- toolButton = getQToolButtonFromAction(self.maskWidget.pencilAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- self.maskWidget.pencilSpinBox.setValue(30)
- self.qapp.processEvents()
-
- # mask
- self.maskWidget.maskStateGroup.button(1).click()
- self.qapp.processEvents()
- self._drawPencil()
- self.assertFalse(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
- self.assertTrue(self._isMaskItemSync())
-
- # unmask same region
- self.maskWidget.maskStateGroup.button(0).click()
- self.qapp.processEvents()
- self._drawPencil()
- self.assertTrue(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
- self.assertTrue(self._isMaskItemSync())
-
- # Test no draw tool #
- toolButton = getQToolButtonFromAction(self.maskWidget.browseAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- self.plot.clear()
-
- def __loadSave(self, file_format):
- """Plot with an image: test MaskToolsWidget operations"""
- self.plot.addImage(numpy.arange(1024**2).reshape(1024, 1024),
- legend='test')
- self.qapp.processEvents()
-
- # Draw a polygon mask
- toolButton = getQToolButtonFromAction(self.maskWidget.polygonAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
- self._drawPolygon()
-
- ref_mask = self.maskWidget.getSelectionMask()
- self.assertFalse(numpy.all(numpy.equal(ref_mask, 0)))
-
- with temp_dir() as tmp:
- mask_filename = os.path.join(tmp, 'mask.' + file_format)
- self.maskWidget.save(mask_filename, file_format)
-
- self.maskWidget.resetSelectionMask()
- self.assertTrue(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
-
- self.maskWidget.load(mask_filename)
- self.assertTrue(numpy.all(numpy.equal(
- self.maskWidget.getSelectionMask(), ref_mask)))
-
- def testLoadSaveNpy(self):
- self.__loadSave("npy")
-
- def testLoadSaveFit2D(self):
- self.__loadSave("msk")
-
- def testSigMaskChangedEmitted(self):
- self.plot.addImage(numpy.arange(512**2).reshape(512, 512),
- legend='test')
- self.plot.resetZoom()
- self.qapp.processEvents()
-
- l = []
-
- def slot():
- l.append(1)
-
- self.maskWidget.sigMaskChanged.connect(slot)
-
- # rectangle mask
- toolButton = getQToolButtonFromAction(self.maskWidget.rectAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
- self.maskWidget.maskStateGroup.button(1).click()
- self.qapp.processEvents()
- self._drag()
-
- self.assertGreater(len(l), 0)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for TestClass in (TestMaskToolsWidget,):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testPixelIntensityHistoAction.py b/silx/gui/plot/test/testPixelIntensityHistoAction.py
deleted file mode 100644
index ac29952..0000000
--- a/silx/gui/plot/test/testPixelIntensityHistoAction.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# 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.
-#
-# ###########################################################################*/
-"""Basic tests for PixelIntensitiesHistoAction"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "02/03/2018"
-
-
-import numpy
-import unittest
-
-from silx.utils.testutils import ParametricTestCase
-from silx.gui.utils.testutils import TestCaseQt, getQToolButtonFromAction
-from silx.gui import qt
-from silx.gui.plot import Plot2D
-
-
-class TestPixelIntensitiesHisto(TestCaseQt, ParametricTestCase):
- """Tests for PixelIntensitiesHistoAction widget."""
-
- def setUp(self):
- super(TestPixelIntensitiesHisto, self).setUp()
- self.image = numpy.random.rand(10, 10)
- self.plotImage = Plot2D()
- self.plotImage.getIntensityHistogramAction().setVisible(True)
-
- def tearDown(self):
- del self.plotImage
- super(TestPixelIntensitiesHisto, self).tearDown()
-
- def testShowAndHide(self):
- """Simple test that the plot is showing and hiding when activating the
- action"""
- self.plotImage.addImage(self.image, origin=(0, 0), legend='sino')
- self.plotImage.show()
-
- histoAction = self.plotImage.getIntensityHistogramAction()
-
- # test the pixel intensity diagram is showing
- button = getQToolButtonFromAction(histoAction)
- self.assertIsNot(button, None)
- self.mouseMove(button)
- self.mouseClick(button, qt.Qt.LeftButton)
- self.qapp.processEvents()
- self.assertTrue(histoAction.getHistogramWidget().isVisible())
-
- # test the pixel intensity diagram is hiding
- self.qapp.setActiveWindow(self.plotImage)
- self.qapp.processEvents()
- self.mouseMove(button)
- self.mouseClick(button, qt.Qt.LeftButton)
- self.qapp.processEvents()
- self.assertFalse(histoAction.getHistogramWidget().isVisible())
-
- def testImageFormatInput(self):
- """Test multiple type as image input"""
- typesToTest = [numpy.uint8, numpy.int8, numpy.int16, numpy.int32,
- numpy.float32, numpy.float64]
- self.plotImage.addImage(self.image, origin=(0, 0), legend='sino')
- self.plotImage.show()
- button = getQToolButtonFromAction(
- self.plotImage.getIntensityHistogramAction())
- self.mouseMove(button)
- self.mouseClick(button, qt.Qt.LeftButton)
- self.qapp.processEvents()
- for typeToTest in typesToTest:
- with self.subTest(typeToTest=typeToTest):
- self.plotImage.addImage(self.image.astype(typeToTest),
- origin=(0, 0), legend='sino')
-
- def testScatter(self):
- """Test that an histogram from a scatter is displayed"""
- xx = numpy.arange(10)
- yy = numpy.arange(10)
- value = numpy.sin(xx)
- self.plotImage.addScatter(xx, yy, value)
- self.plotImage.show()
-
- histoAction = self.plotImage.getIntensityHistogramAction()
-
- # test the pixel intensity diagram is showing
- button = getQToolButtonFromAction(histoAction)
- self.assertIsNot(button, None)
- self.mouseMove(button)
- self.mouseClick(button, qt.Qt.LeftButton)
- self.qapp.processEvents()
-
- widget = histoAction.getHistogramWidget()
- self.assertTrue(widget.isVisible())
- items = widget.getPlotWidget().getItems()
- self.assertEqual(len(items), 1)
-
- def testChangeItem(self):
- """Test that histogram changes it the item changes"""
- xx = numpy.arange(10)
- yy = numpy.arange(10)
- value = numpy.sin(xx)
- self.plotImage.addScatter(xx, yy, value)
- self.plotImage.show()
-
- histoAction = self.plotImage.getIntensityHistogramAction()
-
- # test the pixel intensity diagram is showing
- button = getQToolButtonFromAction(histoAction)
- self.assertIsNot(button, None)
- self.mouseMove(button)
- self.mouseClick(button, qt.Qt.LeftButton)
- self.qapp.processEvents()
-
- # Reach histogram from the first item
- widget = histoAction.getHistogramWidget()
- self.assertTrue(widget.isVisible())
- items = widget.getPlotWidget().getItems()
- data1 = items[0].getValueData(copy=False)
-
- # Set another item to the plot
- self.plotImage.addImage(self.image, origin=(0, 0), legend='sino')
- self.qapp.processEvents()
- data2 = items[0].getValueData(copy=False)
-
- # Histogram is not the same
- self.assertFalse(numpy.array_equal(data1, data2))
-
-
-def suite():
- test_suite = unittest.TestSuite()
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(
- TestPixelIntensitiesHisto))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testPlotInteraction.py b/silx/gui/plot/test/testPlotInteraction.py
deleted file mode 100644
index 7a30434..0000000
--- a/silx/gui/plot/test/testPlotInteraction.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016=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.
-#
-# ###########################################################################*/
-"""Tests of plot interaction, through a PlotWidget"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "01/09/2017"
-
-
-import unittest
-from silx.gui import qt
-from .utils import PlotWidgetTestCase
-
-
-class _SignalDump(object):
- """Callable object that store passed arguments in a list"""
-
- def __init__(self):
- self._received = []
-
- def __call__(self, *args):
- self._received.append(args)
-
- @property
- def received(self):
- """Return a shallow copy of the list of received arguments"""
- return list(self._received)
-
-
-class TestSelectPolygon(PlotWidgetTestCase):
- """Test polygon selection interaction"""
-
- def _interactionModeChanged(self, source):
- """Check that source received in event is the correct one"""
- self.assertEqual(source, self)
-
- def _draw(self, polygon):
- """Draw a polygon in the plot
-
- :param polygon: List of points (x, y) of the polygon (closed)
- """
- plot = self.plot.getWidgetHandle()
-
- dump = _SignalDump()
- self.plot.sigPlotSignal.connect(dump)
-
- for pos in polygon:
- self.mouseMove(plot, pos=pos)
- self.qapp.processEvents()
- self.mousePress(plot, qt.Qt.LeftButton, pos=pos)
- self.qapp.processEvents()
- self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos)
- self.qapp.processEvents()
-
- self.plot.sigPlotSignal.disconnect(dump)
- return [args[0] for args in dump.received]
-
- def test(self):
- """Test draw polygons + events"""
- self.plot.sigInteractiveModeChanged.connect(
- self._interactionModeChanged)
-
- self.plot.setInteractiveMode(
- 'draw', shape='polygon', label='test', source=self)
- interaction = self.plot.getInteractiveMode()
-
- self.assertEqual(interaction['mode'], 'draw')
- self.assertEqual(interaction['shape'], 'polygon')
-
- self.plot.sigInteractiveModeChanged.disconnect(
- self._interactionModeChanged)
-
- plot = self.plot.getWidgetHandle()
- xCenter, yCenter = plot.width() // 2, plot.height() // 2
- offset = min(plot.width(), plot.height()) // 10
-
- # Star polygon
- star = [(xCenter, yCenter + offset),
- (xCenter - offset, yCenter - offset),
- (xCenter + offset, yCenter),
- (xCenter - offset, yCenter),
- (xCenter + offset, yCenter - offset),
- (xCenter, yCenter + offset)] # Close polygon
-
- # Draw while dumping signals
- events = self._draw(star)
-
- # Test last event
- drawEvents = [event for event in events
- if event['event'].startswith('drawing')]
- self.assertEqual(drawEvents[-1]['event'], 'drawingFinished')
- self.assertEqual(len(drawEvents[-1]['points']), 6)
-
- # Large square
- largeSquare = [(xCenter - offset, yCenter - offset),
- (xCenter + offset, yCenter - offset),
- (xCenter + offset, yCenter + offset),
- (xCenter - offset, yCenter + offset),
- (xCenter - offset, yCenter - offset)] # Close polygon
-
- # Draw while dumping signals
- events = self._draw(largeSquare)
-
- # Test last event
- drawEvents = [event for event in events
- if event['event'].startswith('drawing')]
- self.assertEqual(drawEvents[-1]['event'], 'drawingFinished')
- self.assertEqual(len(drawEvents[-1]['points']), 5)
-
- # Rectangle too thin along X: Some points are ignored
- thinRectX = [(xCenter, yCenter - offset),
- (xCenter, yCenter + offset),
- (xCenter + 1, yCenter + offset),
- (xCenter + 1, yCenter - offset)] # Close polygon
-
- # Draw while dumping signals
- events = self._draw(thinRectX)
-
- # Test last event
- drawEvents = [event for event in events
- if event['event'].startswith('drawing')]
- self.assertEqual(drawEvents[-1]['event'], 'drawingFinished')
- self.assertEqual(len(drawEvents[-1]['points']), 3)
-
- # Rectangle too thin along Y: Some points are ignored
- thinRectY = [(xCenter - offset, yCenter),
- (xCenter + offset, yCenter),
- (xCenter + offset, yCenter + 1),
- (xCenter - offset, yCenter + 1)] # Close polygon
-
- # Draw while dumping signals
- events = self._draw(thinRectY)
-
- # Test last event
- drawEvents = [event for event in events
- if event['event'].startswith('drawing')]
- self.assertEqual(drawEvents[-1]['event'], 'drawingFinished')
- self.assertEqual(len(drawEvents[-1]['points']), 3)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for TestClass in (TestSelectPolygon,):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testPlotWidget.py b/silx/gui/plot/test/testPlotWidget.py
deleted file mode 100755
index b55260e..0000000
--- a/silx/gui/plot/test/testPlotWidget.py
+++ /dev/null
@@ -1,2072 +0,0 @@
-# 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.
-#
-# ###########################################################################*/
-"""Basic tests for PlotWidget"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "03/01/2019"
-
-
-import unittest
-import logging
-import numpy
-import sys
-
-from silx.utils.testutils import ParametricTestCase, parameterize
-from silx.gui.utils.testutils import SignalListener
-from silx.gui.utils.testutils import TestCaseQt
-
-from silx.test.utils import test_options
-
-from silx.gui import qt
-from silx.gui.plot import PlotWidget
-from silx.gui.plot.items.curve import CurveStyle
-from silx.gui.plot.items import BoundingRect, XAxisExtent, YAxisExtent, Axis
-from silx.gui.colors import Colormap
-
-from .utils import PlotWidgetTestCase
-
-
-SIZE = 1024
-"""Size of the test image"""
-
-DATA_2D = numpy.arange(SIZE ** 2).reshape(SIZE, SIZE)
-"""Image data set"""
-
-
-logger = logging.getLogger(__name__)
-
-
-class TestSpecialBackend(PlotWidgetTestCase, ParametricTestCase):
-
- def __init__(self, methodName='runTest', backend=None):
- TestCaseQt.__init__(self, methodName=methodName)
- self.__backend = backend
-
- def _createPlot(self):
- return PlotWidget(backend=self.__backend)
-
- def testPlot(self):
- self.assertIsNotNone(self.plot)
-
-
-class TestPlotWidget(PlotWidgetTestCase, ParametricTestCase):
- """Basic tests for PlotWidget"""
-
- def testShow(self):
- """Most basic test"""
- pass
-
- def testSetTitleLabels(self):
- """Set title and axes labels"""
-
- title, xlabel, ylabel = 'the title', 'x label', 'y label'
- self.plot.setGraphTitle(title)
- self.plot.getXAxis().setLabel(xlabel)
- self.plot.getYAxis().setLabel(ylabel)
- self.qapp.processEvents()
-
- self.assertEqual(self.plot.getGraphTitle(), title)
- self.assertEqual(self.plot.getXAxis().getLabel(), xlabel)
- self.assertEqual(self.plot.getYAxis().getLabel(), ylabel)
-
- def _checkLimits(self,
- expectedXLim=None,
- expectedYLim=None,
- expectedRatio=None):
- """Assert that limits are as expected"""
- xlim = self.plot.getXAxis().getLimits()
- ylim = self.plot.getYAxis().getLimits()
- ratio = abs(xlim[1] - xlim[0]) / abs(ylim[1] - ylim[0])
-
- if expectedXLim is not None:
- self.assertEqual(expectedXLim, xlim)
-
- if expectedYLim is not None:
- self.assertEqual(expectedYLim, ylim)
-
- if expectedRatio is not None:
- self.assertTrue(
- numpy.allclose(expectedRatio, ratio, atol=0.01))
-
- def testChangeLimitsWithAspectRatio(self):
- self.plot.setKeepDataAspectRatio()
- self.qapp.processEvents()
- xlim = self.plot.getXAxis().getLimits()
- ylim = self.plot.getYAxis().getLimits()
- defaultRatio = abs(xlim[1] - xlim[0]) / abs(ylim[1] - ylim[0])
-
- self.plot.getXAxis().setLimits(1., 10.)
- self._checkLimits(expectedXLim=(1., 10.), expectedRatio=defaultRatio)
- self.qapp.processEvents()
- self._checkLimits(expectedXLim=(1., 10.), expectedRatio=defaultRatio)
-
- self.plot.getYAxis().setLimits(1., 10.)
- self._checkLimits(expectedYLim=(1., 10.), expectedRatio=defaultRatio)
- self.qapp.processEvents()
- self._checkLimits(expectedYLim=(1., 10.), expectedRatio=defaultRatio)
-
- def testResizeWidget(self):
- """Test resizing the widget and receiving limitsChanged events"""
- self.plot.resize(200, 200)
- self.qapp.processEvents()
- self.qWait(100)
-
- xlim = self.plot.getXAxis().getLimits()
- ylim = self.plot.getYAxis().getLimits()
-
- listener = SignalListener()
- self.plot.getXAxis().sigLimitsChanged.connect(listener.partial('x'))
- self.plot.getYAxis().sigLimitsChanged.connect(listener.partial('y'))
-
- # Resize without aspect ratio
- self.plot.resize(200, 300)
- self.qapp.processEvents()
- self.qWait(100)
- self._checkLimits(expectedXLim=xlim, expectedYLim=ylim)
- self.assertEqual(listener.callCount(), 0)
-
- # Resize with aspect ratio
- self.plot.setKeepDataAspectRatio(True)
- self.qapp.processEvents()
- self.qWait(1000)
- listener.clear() # Clean-up received signal
-
- self.plot.resize(200, 200)
- self.qapp.processEvents()
- self.qWait(100)
- self.assertNotEqual(listener.callCount(), 0)
-
- def testAddRemoveItemSignals(self):
- """Test sigItemAdded and sigItemAboutToBeRemoved"""
- listener = SignalListener()
- self.plot.sigItemAdded.connect(listener.partial('add'))
- self.plot.sigItemAboutToBeRemoved.connect(listener.partial('remove'))
-
- self.plot.addCurve((1, 2, 3), (3, 2, 1), legend='curve')
- self.assertEqual(listener.callCount(), 1)
-
- curve = self.plot.getCurve('curve')
- self.plot.remove('curve')
- self.assertEqual(listener.callCount(), 2)
- self.assertEqual(listener.arguments(callIndex=0), ('add', curve))
- self.assertEqual(listener.arguments(callIndex=1), ('remove', curve))
-
- def testGetItems(self):
- """Test getItems method"""
- curve_x = 1, 2
- self.plot.addCurve(curve_x, (3, 4))
- image = (0, 1), (2, 3)
- self.plot.addImage(image)
- scatter_x = 10, 11
- self.plot.addScatter(scatter_x, (12, 13), (0, 1))
- marker_pos = 5, 5
- self.plot.addMarker(*marker_pos)
- marker_x = 6
- self.plot.addXMarker(marker_x)
- self.plot.addShape((0, 5), (2, 10), shape='rectangle')
-
- items = self.plot.getItems()
- self.assertEqual(len(items), 6)
- self.assertTrue(numpy.all(numpy.equal(items[0].getXData(), curve_x)))
- self.assertTrue(numpy.all(numpy.equal(items[1].getData(), image)))
- self.assertTrue(numpy.all(numpy.equal(items[2].getXData(), scatter_x)))
- self.assertTrue(numpy.all(numpy.equal(items[3].getPosition(), marker_pos)))
- self.assertTrue(numpy.all(numpy.equal(items[4].getPosition()[0], marker_x)))
- self.assertEqual(items[5].getType(), 'rectangle')
-
- def testRemoveDiscardItem(self):
- """Test removeItem and discardItem"""
- self.plot.addCurve((1, 2, 3), (1, 2, 3))
- curve = self.plot.getItems()[0]
- self.plot.removeItem(curve)
- with self.assertRaises(ValueError):
- self.plot.removeItem(curve)
-
- self.plot.addCurve((1, 2, 3), (1, 2, 3))
- curve = self.plot.getItems()[0]
- result = self.plot.discardItem(curve)
- self.assertTrue(result)
- result = self.plot.discardItem(curve)
- self.assertFalse(result)
-
- def testBackGroundColors(self):
- self.plot.setVisible(True)
- self.qWaitForWindowExposed(self.plot)
- self.qapp.processEvents()
-
- # Custom the full background
- color = self.plot.getBackgroundColor()
- self.assertTrue(color.isValid())
- self.assertEqual(color, qt.QColor(255, 255, 255))
- self.plot.setBackgroundColor("red")
- color = self.plot.getBackgroundColor()
- self.assertTrue(color.isValid())
- self.qapp.processEvents()
-
- # Custom the data background
- color = self.plot.getDataBackgroundColor()
- self.assertFalse(color.isValid())
- self.plot.setDataBackgroundColor("red")
- color = self.plot.getDataBackgroundColor()
- self.assertTrue(color.isValid())
- self.qapp.processEvents()
-
- # Back to default
- self.plot.setBackgroundColor('white')
- self.plot.setDataBackgroundColor(None)
- color = self.plot.getBackgroundColor()
- self.assertTrue(color.isValid())
- self.assertEqual(color, qt.QColor(255, 255, 255))
- color = self.plot.getDataBackgroundColor()
- self.assertFalse(color.isValid())
- self.qapp.processEvents()
-
-
-class TestPlotImage(PlotWidgetTestCase, ParametricTestCase):
- """Basic tests for addImage"""
-
- def setUp(self):
- super(TestPlotImage, self).setUp()
-
- self.plot.getYAxis().setLabel('Rows')
- self.plot.getXAxis().setLabel('Columns')
-
- def testPlotColormapTemperature(self):
- self.plot.setGraphTitle('Temp. Linear')
-
- colormap = Colormap(name='temperature',
- normalization='linear',
- vmin=None,
- vmax=None)
- self.plot.addImage(DATA_2D, legend="image 1", colormap=colormap)
-
- def testPlotColormapGray(self):
- self.plot.setKeepDataAspectRatio(False)
- self.plot.setGraphTitle('Gray Linear')
-
- colormap = Colormap(name='gray',
- normalization='linear',
- vmin=None,
- vmax=None)
- self.plot.addImage(DATA_2D, legend="image 1", colormap=colormap)
-
- def testPlotColormapTemperatureLog(self):
- self.plot.setGraphTitle('Temp. Log')
-
- colormap = Colormap(name='temperature',
- normalization=Colormap.LOGARITHM,
- vmin=None,
- vmax=None)
- self.plot.addImage(DATA_2D, legend="image 1", colormap=colormap)
-
- def testPlotRgbRgba(self):
- self.plot.setKeepDataAspectRatio(False)
- self.plot.setGraphTitle('RGB + RGBA')
-
- rgb = numpy.array(
- (((0, 0, 0), (128, 0, 0), (255, 0, 0)),
- ((0, 128, 0), (0, 128, 128), (0, 128, 255))),
- dtype=numpy.uint8)
-
- self.plot.addImage(rgb, legend="rgb_uint8",
- origin=(0, 0), scale=(1, 1),
- resetzoom=False)
-
- rgb = numpy.array(
- (((0, 0, 0), (32768, 0, 0), (65535, 0, 0)),
- ((0, 32768, 0), (0, 32768, 32768), (0, 32768, 65535))),
- dtype=numpy.uint16)
-
- self.plot.addImage(rgb, legend="rgb_uint16",
- origin=(3, 2), scale=(2, 2),
- resetzoom=False)
-
- rgba = numpy.array(
- (((0, 0, 0, .5), (.5, 0, 0, 1), (1, 0, 0, .5)),
- ((0, .5, 0, 1), (0, .5, .5, 1), (0, 1, 1, .5))),
- dtype=numpy.float32)
-
- self.plot.addImage(rgba, legend="rgba_float32",
- origin=(9, 6), scale=(1, 1),
- resetzoom=False)
-
- self.plot.resetZoom()
-
- def testPlotColormapCustom(self):
- self.plot.setKeepDataAspectRatio(False)
- self.plot.setGraphTitle('Custom colormap')
-
- colormap = Colormap(name=None,
- normalization=Colormap.LINEAR,
- vmin=None,
- vmax=None,
- colors=((0., 0., 0.), (1., 0., 0.),
- (0., 1., 0.), (0., 0., 1.)))
- self.plot.addImage(DATA_2D, legend="image 1", colormap=colormap,
- resetzoom=False)
-
- colormap = Colormap(name=None,
- normalization=Colormap.LINEAR,
- vmin=None,
- vmax=None,
- colors=numpy.array(
- ((0, 0, 0, 0), (0, 0, 0, 128),
- (128, 128, 128, 128), (255, 255, 255, 255)),
- dtype=numpy.uint8))
- self.plot.addImage(DATA_2D, legend="image 2", colormap=colormap,
- origin=(DATA_2D.shape[0], 0),
- resetzoom=False)
- self.plot.resetZoom()
-
- def testPlotColormapNaNColor(self):
- self.plot.setKeepDataAspectRatio(False)
- self.plot.setGraphTitle('Colormap with NaN color')
-
- colormap = Colormap()
- colormap.setNaNColor('red')
- self.assertEqual(colormap.getNaNColor(), qt.QColor(255, 0, 0))
- data = DATA_2D.astype(numpy.float32)
- data[len(data)//2:] = numpy.nan
- self.plot.addImage(data, legend="image 1", colormap=colormap,
- resetzoom=False)
- self.plot.resetZoom()
-
- colormap.setNaNColor((0., 1., 0., 1.))
- self.assertEqual(colormap.getNaNColor(), qt.QColor(0, 255, 0))
- self.qapp.processEvents()
-
- def testImageOriginScale(self):
- """Test of image with different origin and scale"""
- self.plot.setGraphTitle('origin and scale')
-
- tests = [ # (origin, scale)
- ((10, 20), (1, 1)),
- ((10, 20), (-1, -1)),
- ((-10, 20), (2, 1)),
- ((10, -20), (-1, -2)),
- (100, 2),
- (-100, (1, 1)),
- ((10, 20), 2),
- ]
-
- for origin, scale in tests:
- with self.subTest(origin=origin, scale=scale):
- self.plot.addImage(DATA_2D, origin=origin, scale=scale)
-
- try:
- ox, oy = origin
- except TypeError:
- ox, oy = origin, origin
- try:
- sx, sy = scale
- except TypeError:
- sx, sy = scale, scale
- xbounds = ox, ox + DATA_2D.shape[1] * sx
- ybounds = oy, oy + DATA_2D.shape[0] * sy
-
- # Check limits without aspect ratio
- xmin, xmax = self.plot.getXAxis().getLimits()
- ymin, ymax = self.plot.getYAxis().getLimits()
- self.assertEqual(xmin, min(xbounds))
- self.assertEqual(xmax, max(xbounds))
- self.assertEqual(ymin, min(ybounds))
- self.assertEqual(ymax, max(ybounds))
-
- # Check limits with aspect ratio
- self.plot.setKeepDataAspectRatio(True)
- xmin, xmax = self.plot.getXAxis().getLimits()
- ymin, ymax = self.plot.getYAxis().getLimits()
- self.assertTrue(round(xmin, 7) <= min(xbounds))
- self.assertTrue(round(xmax, 7) >= max(xbounds))
- self.assertTrue(round(ymin, 7) <= min(ybounds))
- self.assertTrue(round(ymax, 7) >= max(ybounds))
-
- self.plot.setKeepDataAspectRatio(False) # Reset aspect ratio
- self.plot.clear()
- self.plot.resetZoom()
-
- def testPlotColormapDictAPI(self):
- """Test that the addImage API using a colormap dictionary is still
- working"""
- self.plot.setGraphTitle('Temp. Log')
-
- colormap = {
- 'name': 'temperature',
- 'normalization': 'log',
- 'vmin': None,
- 'vmax': None
- }
- self.plot.addImage(DATA_2D, legend="image 1", colormap=colormap)
-
- def testPlotComplexImage(self):
- """Test that a complex image is displayed as its absolute value."""
- data = numpy.linspace(1, 1j, 100).reshape(10, 10)
- self.plot.addImage(data, legend='complex')
-
- image = self.plot.getActiveImage()
- retrievedData = image.getData(copy=False)
- self.assertTrue(
- numpy.all(numpy.equal(retrievedData, numpy.absolute(data))))
-
- def testPlotBooleanImage(self):
- """Test that a boolean image is displayed and converted to int8."""
- data = numpy.zeros((10, 10), dtype=bool)
- data[::2, ::2] = True
- self.plot.addImage(data, legend='boolean')
-
- image = self.plot.getActiveImage()
- retrievedData = image.getData(copy=False)
- self.assertTrue(numpy.all(numpy.equal(retrievedData, data)))
- self.assertIs(retrievedData.dtype.type, numpy.int8)
-
- def testPlotAlphaImage(self):
- """Test with an alpha image layer"""
- data = numpy.random.random((10, 10))
- alpha = numpy.linspace(0, 1, 100).reshape(10, 10)
- self.plot.addImage(data, legend='image')
- image = self.plot.getActiveImage()
- image.setData(data, alpha=alpha)
- self.qapp.processEvents()
- self.assertTrue(numpy.array_equal(alpha, image.getAlphaData()))
-
-
-class TestPlotCurve(PlotWidgetTestCase):
- """Basic tests for addCurve."""
-
- # Test data sets
- xData = numpy.arange(1000)
- yData = -500 + 100 * numpy.sin(xData)
- xData2 = xData + 1000
- yData2 = xData - 1000 + 200 * numpy.random.random(1000)
-
- def setUp(self):
- super(TestPlotCurve, self).setUp()
- self.plot.setGraphTitle('Curve')
- self.plot.getYAxis().setLabel('Rows')
- self.plot.getXAxis().setLabel('Columns')
-
- self.plot.setActiveCurveHandling(False)
-
- def testPlotCurveInfinite(self):
- """Test plot curves with not finite data"""
- tests = {
- 'y all not finite': ([0, 1, 2], [numpy.inf, numpy.nan, -numpy.inf]),
- 'x all not finite': ([numpy.inf, numpy.nan, -numpy.inf], [0, 1, 2]),
- 'x some inf': ([0, numpy.inf, 2], [0, 1, 2]),
- 'y some inf': ([0, 1, 2], [0, numpy.inf, 2])
- }
- for name, args in tests.items():
- with self.subTest(name):
- self.plot.addCurve(*args)
- self.plot.resetZoom()
- self.qapp.processEvents()
- self.plot.clear()
-
- def testPlotCurveColorFloat(self):
- color = numpy.array(numpy.random.random(3 * 1000),
- dtype=numpy.float32).reshape(1000, 3)
-
- self.plot.addCurve(self.xData, self.yData,
- legend="curve 1",
- replace=False, resetzoom=False,
- color=color,
- linestyle="", symbol="s")
- self.plot.addCurve(self.xData2, self.yData2,
- legend="curve 2",
- replace=False, resetzoom=False,
- color='green', linestyle="-", symbol='o')
- self.plot.resetZoom()
-
- def testPlotCurveColorByte(self):
- color = numpy.array(255 * numpy.random.random(3 * 1000),
- dtype=numpy.uint8).reshape(1000, 3)
-
- self.plot.addCurve(self.xData, self.yData,
- legend="curve 1",
- replace=False, resetzoom=False,
- color=color,
- linestyle="", symbol="s")
- self.plot.addCurve(self.xData2, self.yData2,
- legend="curve 2",
- replace=False, resetzoom=False,
- color='green', linestyle="-", symbol='o')
- self.plot.resetZoom()
-
- def testPlotCurveColors(self):
- color = numpy.array(numpy.random.random(3 * 1000),
- dtype=numpy.float32).reshape(1000, 3)
-
- self.plot.addCurve(self.xData, self.yData,
- legend="curve 2",
- replace=False, resetzoom=False,
- color=color, linestyle="-", symbol='o')
- self.plot.resetZoom()
-
- # Test updating color array
-
- # From array to array
- newColors = numpy.ones((len(self.xData), 3), dtype=numpy.float32)
- self.plot.addCurve(self.xData, self.yData,
- legend="curve 2",
- replace=False, resetzoom=False,
- color=newColors, symbol='o')
-
- # Array to single color
- self.plot.addCurve(self.xData, self.yData,
- legend="curve 2",
- replace=False, resetzoom=False,
- color='green', symbol='o')
-
- # single color to array
- self.plot.addCurve(self.xData, self.yData,
- legend="curve 2",
- replace=False, resetzoom=False,
- color=color, symbol='o')
-
- def testPlotBaselineNumpyArray(self):
- """simple test of the API with baseline as a numpy array"""
- x = numpy.arange(0, 10, step=0.1)
- my_sin = numpy.sin(x)
- y = numpy.arange(-4, 6, step=0.1) + my_sin
- baseline = y - 1.0
-
- self.plot.addCurve(x=x, y=y, color='grey', legend='curve1', fill=True,
- baseline=baseline)
-
- def testPlotBaselineScalar(self):
- """simple test of the API with baseline as an int"""
- x = numpy.arange(0, 10, step=0.1)
- my_sin = numpy.sin(x)
- y = numpy.arange(-4, 6, step=0.1) + my_sin
-
- self.plot.addCurve(x=x, y=y, color='grey', legend='curve1', fill=True,
- baseline=0)
-
- def testPlotBaselineList(self):
- """simple test of the API with baseline as an int"""
- x = numpy.arange(0, 10, step=0.1)
- my_sin = numpy.sin(x)
- y = numpy.arange(-4, 6, step=0.1) + my_sin
-
- self.plot.addCurve(x=x, y=y, color='grey', legend='curve1', fill=True,
- baseline=list(range(0, 100, 1)))
-
- def testPlotCurveComplexData(self):
- """Test curve with complex data"""
- data = numpy.arange(100.) + 1j
- self.plot.addCurve(x=data, y=data, xerror=data, yerror=data)
-
-
-class TestPlotHistogram(PlotWidgetTestCase):
- """Basic tests for add Histogram"""
- def setUp(self):
- super(TestPlotHistogram, self).setUp()
- self.edges = numpy.arange(0, 10, step=1)
- self.histogram = numpy.random.random(len(self.edges))
-
- def testPlot(self):
- self.plot.addHistogram(histogram=self.histogram,
- edges=self.edges,
- legend='histogram1')
-
- def testPlotBaseline(self):
- self.plot.addHistogram(histogram=self.histogram,
- edges=self.edges,
- legend='histogram1',
- color='blue',
- baseline=-2,
- z=2,
- fill=True)
-
-
-class TestPlotScatter(PlotWidgetTestCase, ParametricTestCase):
- """Basic tests for addScatter"""
-
- def testScatter(self):
- x = numpy.arange(100)
- y = numpy.arange(100)
- value = numpy.arange(100)
- self.plot.addScatter(x, y, value)
- self.plot.resetZoom()
-
- def testScatterComplexData(self):
- """Test scatter item with complex data"""
- data = numpy.arange(100.) + 1j
- self.plot.addScatter(
- x=data, y=data, value=data, xerror=data, yerror=data)
- self.plot.resetZoom()
-
- def testScatterVisualization(self):
- self.plot.addScatter((0, 1, 0, 1), (0, 0, 2, 2), (0, 1, 2, 3))
- self.plot.resetZoom()
- self.qapp.processEvents()
-
- scatter = self.plot.getItems()[0]
-
- for visualization in ('solid',
- 'points',
- 'regular_grid',
- 'irregular_grid',
- 'binned_statistic',
- scatter.Visualization.SOLID,
- scatter.Visualization.POINTS,
- scatter.Visualization.REGULAR_GRID,
- scatter.Visualization.IRREGULAR_GRID,
- scatter.Visualization.BINNED_STATISTIC):
- with self.subTest(visualization=visualization):
- scatter.setVisualization(visualization)
- self.qapp.processEvents()
-
- def testGridVisualization(self):
- """Test regular and irregular grid mode with different points"""
- points = { # name: (x, y, order)
- 'single point': ((1.,), (1.,), 'row'),
- 'horizontal line': ((0, 1, 2), (0, 0, 0), 'row'),
- 'horizontal line backward': ((2, 1, 0), (0, 0, 0), 'row'),
- 'vertical line': ((0, 0, 0), (0, 1, 2), 'row'),
- 'vertical line backward': ((0, 0, 0), (2, 1, 0), 'row'),
- 'grid fast x, +x +y': ((0, 1, 2, 0, 1, 2), (0, 0, 0, 1, 1, 1), 'row'),
- 'grid fast x, +x -y': ((0, 1, 2, 0, 1, 2), (1, 1, 1, 0, 0, 0), 'row'),
- 'grid fast x, -x -y': ((2, 1, 0, 2, 1, 0), (1, 1, 1, 0, 0, 0), 'row'),
- 'grid fast x, -x +y': ((2, 1, 0, 2, 1, 0), (0, 0, 0, 1, 1, 1), 'row'),
- 'grid fast y, +x +y': ((0, 0, 0, 1, 1, 1), (0, 1, 2, 0, 1, 2), 'column'),
- 'grid fast y, +x -y': ((0, 0, 0, 1, 1, 1), (2, 1, 0, 2, 1, 0), 'column'),
- 'grid fast y, -x -y': ((1, 1, 1, 0, 0, 0), (2, 1, 0, 2, 1, 0), 'column'),
- 'grid fast y, -x +y': ((1, 1, 1, 0, 0, 0), (0, 1, 2, 0, 1, 2), 'column'),
- }
-
- self.plot.addScatter((), (), ())
- scatter = self.plot.getItems()[0]
-
- self.qapp.processEvents()
-
- for visualization in (scatter.Visualization.REGULAR_GRID,
- scatter.Visualization.IRREGULAR_GRID):
- scatter.setVisualization(visualization)
- self.assertIs(scatter.getVisualization(), visualization)
-
- for name, (x, y, ref_order) in points.items():
- with self.subTest(name=name, visualization=visualization.name):
- scatter.setData(x, y, numpy.arange(len(x)))
- self.plot.setGraphTitle(name)
- self.plot.resetZoom()
- self.qapp.processEvents()
-
- order = scatter.getCurrentVisualizationParameter(
- scatter.VisualizationParameter.GRID_MAJOR_ORDER)
- self.assertEqual(ref_order, order)
-
- ref_bounds = (x[0], y[0]), (x[-1], y[-1])
- bounds = scatter.getCurrentVisualizationParameter(
- scatter.VisualizationParameter.GRID_BOUNDS)
- self.assertEqual(ref_bounds, bounds)
-
- shape = scatter.getCurrentVisualizationParameter(
- scatter.VisualizationParameter.GRID_SHAPE)
-
- self.plot.getXAxis().setLimits(numpy.min(x) - 1, numpy.max(x) + 1)
- self.plot.getYAxis().setLimits(numpy.min(y) - 1, numpy.max(y) + 1)
- self.qapp.processEvents()
-
- for index, position in enumerate(zip(x, y)):
- xpixel, ypixel = self.plot.dataToPixel(*position)
- result = scatter.pick(xpixel, ypixel)
- self.assertIsNotNone(result)
- self.assertIs(result.getItem(), scatter)
- self.assertEqual(result.getIndices(), (index,))
-
- def testBinnedStatisticVisualization(self):
- """Test binned display"""
- self.plot.addScatter((), (), ())
- scatter = self.plot.getItems()[0]
- scatter.setVisualization(scatter.Visualization.BINNED_STATISTIC)
- self.assertIs(scatter.getVisualization(),
- scatter.Visualization.BINNED_STATISTIC)
- self.assertEqual(
- scatter.getVisualizationParameter(
- scatter.VisualizationParameter.BINNED_STATISTIC_FUNCTION),
- 'mean')
-
- self.qapp.processEvents()
-
- scatter.setData(*numpy.random.random(3000).reshape(3, -1))
-
- for reduction in ('count', 'sum', 'mean'):
- with self.subTest(reduction=reduction):
- scatter.setVisualizationParameter(
- scatter.VisualizationParameter.BINNED_STATISTIC_FUNCTION,
- reduction)
- self.assertEqual(
- scatter.getVisualizationParameter(
- scatter.VisualizationParameter.BINNED_STATISTIC_FUNCTION),
- reduction)
-
- self.qapp.processEvents()
-
-
-class TestPlotMarker(PlotWidgetTestCase):
- """Basic tests for add*Marker"""
-
- def setUp(self):
- super(TestPlotMarker, self).setUp()
- self.plot.getYAxis().setLabel('Rows')
- self.plot.getXAxis().setLabel('Columns')
-
- self.plot.getXAxis().setAutoScale(False)
- self.plot.getYAxis().setAutoScale(False)
- self.plot.setKeepDataAspectRatio(False)
- self.plot.setLimits(0., 100., -100., 100.)
-
- def testPlotMarkerX(self):
- self.plot.setGraphTitle('Markers X')
-
- markers = [
- (10., 'blue', False, False),
- (20., 'red', False, False),
- (40., 'green', True, False),
- (60., 'gray', True, True),
- (80., 'black', False, True),
- ]
-
- for x, color, select, drag in markers:
- name = str(x)
- if select:
- name += " sel."
- if drag:
- name += " drag"
- self.plot.addXMarker(x, name, name, color, select, drag)
- self.plot.resetZoom()
-
- def testPlotMarkerY(self):
- self.plot.setGraphTitle('Markers Y')
-
- markers = [
- (-50., 'blue', False, False),
- (-30., 'red', False, False),
- (0., 'green', True, False),
- (10., 'gray', True, True),
- (80., 'black', False, True),
- ]
-
- for y, color, select, drag in markers:
- name = str(y)
- if select:
- name += " sel."
- if drag:
- name += " drag"
- self.plot.addYMarker(y, name, name, color, select, drag)
- self.plot.resetZoom()
-
- def testPlotMarkerPt(self):
- self.plot.setGraphTitle('Markers Pt')
-
- markers = [
- (10., -50., 'blue', False, False),
- (40., -30., 'red', False, False),
- (50., 0., 'green', True, False),
- (50., 20., 'gray', True, True),
- (70., 50., 'black', False, True),
- ]
- for x, y, color, select, drag in markers:
- name = "{0},{1}".format(x, y)
- if select:
- name += " sel."
- if drag:
- name += " drag"
- self.plot.addMarker(x, y, name, name, color, select, drag)
-
- self.plot.resetZoom()
-
- def testPlotMarkerWithoutLegend(self):
- self.plot.setGraphTitle('Markers without legend')
- self.plot.getYAxis().setInverted(True)
-
- # Markers without legend
- self.plot.addMarker(10, 10)
- self.plot.addMarker(10, 20)
- self.plot.addMarker(40, 50, text='test', symbol=None)
- self.plot.addMarker(40, 50, text='test', symbol='+')
- self.plot.addXMarker(25)
- self.plot.addXMarker(35)
- self.plot.addXMarker(45, text='test')
- self.plot.addYMarker(55)
- self.plot.addYMarker(65)
- self.plot.addYMarker(75, text='test')
-
- self.plot.resetZoom()
-
- def testPlotMarkerYAxis(self):
- # Check only the API
-
- legend = self.plot.addMarker(10, 10)
- item = self.plot._getMarker(legend)
- self.assertEqual(item.getYAxis(), "left")
-
- legend = self.plot.addMarker(10, 10, yaxis="right")
- item = self.plot._getMarker(legend)
- self.assertEqual(item.getYAxis(), "right")
-
- legend = self.plot.addMarker(10, 10, yaxis="left")
- item = self.plot._getMarker(legend)
- self.assertEqual(item.getYAxis(), "left")
-
- legend = self.plot.addXMarker(10, yaxis="right")
- item = self.plot._getMarker(legend)
- self.assertEqual(item.getYAxis(), "right")
-
- legend = self.plot.addXMarker(10, yaxis="left")
- item = self.plot._getMarker(legend)
- self.assertEqual(item.getYAxis(), "left")
-
- legend = self.plot.addYMarker(10, yaxis="right")
- item = self.plot._getMarker(legend)
- self.assertEqual(item.getYAxis(), "right")
-
- legend = self.plot.addYMarker(10, yaxis="left")
- item = self.plot._getMarker(legend)
- self.assertEqual(item.getYAxis(), "left")
-
- self.plot.resetZoom()
-
-
-# TestPlotItem ################################################################
-
-class TestPlotItem(PlotWidgetTestCase):
- """Basic tests for addItem."""
-
- # Polygon coordinates and color
- POLYGONS = [ # legend, x coords, y coords, color
- ('triangle', numpy.array((10, 30, 50)),
- numpy.array((55, 70, 55)), 'red'),
- ('square', numpy.array((10, 10, 50, 50)),
- numpy.array((10, 50, 50, 10)), 'green'),
- ('star', numpy.array((60, 70, 80, 60, 80)),
- numpy.array((25, 50, 25, 40, 40)), 'blue'),
- ('2 triangles-simple',
- numpy.array((90., 95., 100., numpy.nan, 90., 95., 100.)),
- numpy.array((25., 5., 25., numpy.nan, 30., 50., 30.)),
- 'pink'),
- ('2 triangles-extra NaN',
- numpy.array((numpy.nan, 90., 95., 100., numpy.nan, 0., 90., 95., 100., numpy.nan)),
- numpy.array((0., 55., 70., 55., numpy.nan, numpy.nan, 75., 90., 75., numpy.nan)),
- 'black'),
- ]
-
- # Rectangle coordinantes and color
- RECTANGLES = [ # legend, x coords, y coords, color
- ('square 1', numpy.array((1., 10.)),
- numpy.array((1., 10.)), 'red'),
- ('square 2', numpy.array((10., 20.)),
- numpy.array((10., 20.)), 'green'),
- ('square 3', numpy.array((20., 30.)),
- numpy.array((20., 30.)), 'blue'),
- ('rect 1', numpy.array((1., 30.)),
- numpy.array((35., 40.)), 'black'),
- ('line h', numpy.array((1., 30.)),
- numpy.array((45., 45.)), 'darkRed'),
- ]
-
- SCALES = Axis.LINEAR, Axis.LOGARITHMIC
-
- def setUp(self):
- super(TestPlotItem, self).setUp()
-
- self.plot.getYAxis().setLabel('Rows')
- self.plot.getXAxis().setLabel('Columns')
- self.plot.getXAxis().setAutoScale(False)
- self.plot.getYAxis().setAutoScale(False)
- self.plot.setKeepDataAspectRatio(False)
- self.plot.setLimits(0., 100., -100., 100.)
-
- def testPlotItemPolygonFill(self):
- for scale in self.SCALES:
- with self.subTest(scale=scale):
- self.plot.clear()
- self.plot.getXAxis().setScale(scale)
- self.plot.getYAxis().setScale(scale)
- self.plot.setGraphTitle('Item Fill %s' % scale)
-
- for legend, xList, yList, color in self.POLYGONS:
- self.plot.addShape(xList, yList, legend=legend,
- replace=False, linestyle='--',
- shape="polygon", fill=True, color=color)
- self.plot.resetZoom()
-
- def testPlotItemPolygonNoFill(self):
- for scale in self.SCALES:
- with self.subTest(scale=scale):
- self.plot.clear()
- self.plot.getXAxis().setScale(scale)
- self.plot.getYAxis().setScale(scale)
- self.plot.setGraphTitle('Item No Fill %s' % scale)
-
- for legend, xList, yList, color in self.POLYGONS:
- self.plot.addShape(xList, yList, legend=legend,
- replace=False, linestyle='--',
- shape="polygon", fill=False, color=color)
- self.plot.resetZoom()
-
- def testPlotItemRectangleFill(self):
- for scale in self.SCALES:
- with self.subTest(scale=scale):
- self.plot.clear()
- self.plot.getXAxis().setScale(scale)
- self.plot.getYAxis().setScale(scale)
- self.plot.setGraphTitle('Rectangle Fill %s' % scale)
-
- for legend, xList, yList, color in self.RECTANGLES:
- self.plot.addShape(xList, yList, legend=legend,
- replace=False,
- shape="rectangle", fill=True, color=color)
- self.plot.resetZoom()
-
- def testPlotItemRectangleNoFill(self):
- for scale in self.SCALES:
- with self.subTest(scale=scale):
- self.plot.clear()
- self.plot.getXAxis().setScale(scale)
- self.plot.getYAxis().setScale(scale)
- self.plot.setGraphTitle('Rectangle No Fill %s' % scale)
-
- for legend, xList, yList, color in self.RECTANGLES:
- self.plot.addShape(xList, yList, legend=legend,
- replace=False,
- shape="rectangle", fill=False, color=color)
- self.plot.resetZoom()
-
-
-class TestPlotActiveCurveImage(PlotWidgetTestCase):
- """Basic tests for active curve and image handling"""
- xData = numpy.arange(1000)
- yData = -500 + 100 * numpy.sin(xData)
- xData2 = xData + 1000
- yData2 = xData - 1000 + 200 * numpy.random.random(1000)
-
- def tearDown(self):
- self.plot.setActiveCurveHandling(False)
- super(TestPlotActiveCurveImage, self).tearDown()
-
- def testActiveCurveAndLabels(self):
- # Active curve handling off, no label change
- self.plot.setActiveCurveHandling(False)
- self.plot.getXAxis().setLabel('XLabel')
- self.plot.getYAxis().setLabel('YLabel')
- self.plot.addCurve((1, 2), (1, 2))
- self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
-
- self.plot.addCurve((1, 2), (2, 3), xlabel='x1', ylabel='y1')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
-
- self.plot.clear()
- self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
-
- # Active curve handling on, label changes
- self.plot.setActiveCurveHandling(True)
- self.plot.getXAxis().setLabel('XLabel')
- self.plot.getYAxis().setLabel('YLabel')
-
- # labels changed as active curve
- self.plot.addCurve((1, 2), (1, 2), legend='1',
- xlabel='x1', ylabel='y1')
- self.plot.setActiveCurve('1')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
-
- # labels not changed as not active curve
- self.plot.addCurve((1, 2), (2, 3), legend='2')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
-
- # labels changed
- self.plot.setActiveCurve('2')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
-
- self.plot.setActiveCurve('1')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
-
- self.plot.clear()
- self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
-
- def testPlotActiveCurveSelectionMode(self):
- self.plot.clear()
- self.plot.setActiveCurveHandling(True)
- legend = "curve 1"
- self.plot.addCurve(self.xData, self.yData,
- legend=legend,
- color="green")
-
- # active curve should be None
- self.assertEqual(self.plot.getActiveCurve(just_legend=True), None)
-
- # active curve should be None when None is set as active curve
- self.plot.setActiveCurve(legend)
- current = self.plot.getActiveCurve(just_legend=True)
- self.assertEqual(current, legend)
- self.plot.setActiveCurve(None)
- current = self.plot.getActiveCurve(just_legend=True)
- self.assertEqual(current, None)
-
- # testing it automatically toggles if there is only one
- self.plot.setActiveCurveSelectionMode("legacy")
- current = self.plot.getActiveCurve(just_legend=True)
- self.assertEqual(current, legend)
-
- # active curve should not change when None set as active curve
- self.assertEqual(self.plot.getActiveCurveSelectionMode(), "legacy")
- self.plot.setActiveCurve(None)
- current = self.plot.getActiveCurve(just_legend=True)
- self.assertEqual(current, legend)
-
- # situation where no curve is active
- self.plot.clear()
- self.plot.setActiveCurveHandling(True)
- self.assertEqual(self.plot.getActiveCurveSelectionMode(), "atmostone")
- self.plot.addCurve(self.xData, self.yData,
- legend=legend,
- color="green")
- self.assertEqual(self.plot.getActiveCurve(just_legend=True), None)
- self.plot.addCurve(self.xData2, self.yData2,
- legend="curve 2",
- color="red")
- self.assertEqual(self.plot.getActiveCurve(just_legend=True), None)
- self.plot.setActiveCurveSelectionMode("legacy")
- self.assertEqual(self.plot.getActiveCurve(just_legend=True), None)
-
- # the first curve added should be active
- self.plot.clear()
- self.plot.addCurve(self.xData, self.yData,
- legend=legend,
- color="green")
- self.assertEqual(self.plot.getActiveCurve(just_legend=True), legend)
- self.plot.addCurve(self.xData2, self.yData2,
- legend="curve 2",
- color="red")
- self.assertEqual(self.plot.getActiveCurve(just_legend=True), legend)
-
- def testActiveCurveStyle(self):
- """Test change of active curve style"""
- self.plot.setActiveCurveHandling(True)
- self.plot.setActiveCurveStyle(color='black')
- style = self.plot.getActiveCurveStyle()
- self.assertEqual(style.getColor(), (0., 0., 0., 1.))
- self.assertIsNone(style.getLineStyle())
- self.assertIsNone(style.getLineWidth())
- self.assertIsNone(style.getSymbol())
- self.assertIsNone(style.getSymbolSize())
-
- self.plot.addCurve(x=self.xData, y=self.yData, legend="curve1")
- curve = self.plot.getCurve("curve1")
- curve.setColor('blue')
- curve.setLineStyle('-')
- curve.setLineWidth(1)
- curve.setSymbol('o')
- curve.setSymbolSize(5)
-
- # Check default current style
- defaultStyle = curve.getCurrentStyle()
- self.assertEqual(defaultStyle, CurveStyle(color='blue',
- linestyle='-',
- linewidth=1,
- symbol='o',
- symbolsize=5))
-
- # Activate curve with highlight color=black
- self.plot.setActiveCurve("curve1")
- style = curve.getCurrentStyle()
- self.assertEqual(style.getColor(), (0., 0., 0., 1.))
- self.assertEqual(style.getLineStyle(), '-')
- self.assertEqual(style.getLineWidth(), 1)
- self.assertEqual(style.getSymbol(), 'o')
- self.assertEqual(style.getSymbolSize(), 5)
-
- # Change highlight to linewidth=2
- self.plot.setActiveCurveStyle(linewidth=2)
- style = curve.getCurrentStyle()
- self.assertEqual(style.getColor(), (0., 0., 1., 1.))
- self.assertEqual(style.getLineStyle(), '-')
- self.assertEqual(style.getLineWidth(), 2)
- self.assertEqual(style.getSymbol(), 'o')
- self.assertEqual(style.getSymbolSize(), 5)
-
- self.plot.setActiveCurve(None)
- self.assertEqual(curve.getCurrentStyle(), defaultStyle)
-
- def testActiveImageAndLabels(self):
- # Active image handling always on, no API for toggling it
- self.plot.getXAxis().setLabel('XLabel')
- self.plot.getYAxis().setLabel('YLabel')
-
- # labels changed as active curve
- self.plot.addImage(numpy.arange(100).reshape(10, 10),
- legend='1', xlabel='x1', ylabel='y1')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
-
- # labels not changed as not active curve
- self.plot.addImage(numpy.arange(100).reshape(10, 10),
- legend='2')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
-
- # labels changed
- self.plot.setActiveImage('2')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
-
- self.plot.setActiveImage('1')
- self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
-
- self.plot.clear()
- self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
- self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
-
-
-##############################################################################
-# Log
-##############################################################################
-
-class TestPlotEmptyLog(PlotWidgetTestCase):
- """Basic tests for log plot"""
- def testEmptyPlotTitleLabelsLog(self):
- self.plot.setGraphTitle('Empty Log Log')
- self.plot.getXAxis().setLabel('X')
- self.plot.getYAxis().setLabel('Y')
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.getYAxis()._setLogarithmic(True)
- self.plot.resetZoom()
-
-
-class TestPlotAxes(TestCaseQt, ParametricTestCase):
-
- # Test data
- xData = numpy.arange(1, 10)
- yData = xData ** 2
-
- def __init__(self, methodName='runTest', backend=None):
- unittest.TestCase.__init__(self, methodName)
- self.__backend = backend
-
- def setUp(self):
- super(TestPlotAxes, self).setUp()
- self.plot = PlotWidget(backend=self.__backend)
- # It is not needed to display the plot
- # It saves a lot of time
- # self.plot.show()
- # self.qWaitForWindowExposed(self.plot)
-
- def tearDown(self):
- self.qapp.processEvents()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- super(TestPlotAxes, self).tearDown()
-
- def testDefaultAxes(self):
- axis = self.plot.getXAxis()
- self.assertEqual(axis.getScale(), axis.LINEAR)
- axis = self.plot.getYAxis()
- self.assertEqual(axis.getScale(), axis.LINEAR)
- axis = self.plot.getYAxis(axis="right")
- self.assertEqual(axis.getScale(), axis.LINEAR)
-
- def testOldPlotAxis_getterSetter(self):
- """Test silx API prior to silx 0.6"""
- x = self.plot.getXAxis()
- y = self.plot.getYAxis()
- p = self.plot
-
- tests = [
- # setters
- (p.setGraphXLimits, (10, 20), x.getLimits, (10, 20)),
- (p.setGraphYLimits, (10, 20), y.getLimits, (10, 20)),
- (p.setGraphXLabel, "foox", x.getLabel, "foox"),
- (p.setGraphYLabel, "fooy", y.getLabel, "fooy"),
- (p.setYAxisInverted, True, y.isInverted, True),
- (p.setXAxisLogarithmic, True, x.getScale, x.LOGARITHMIC),
- (p.setYAxisLogarithmic, True, y.getScale, y.LOGARITHMIC),
- (p.setXAxisAutoScale, False, x.isAutoScale, False),
- (p.setYAxisAutoScale, False, y.isAutoScale, False),
- # getters
- (x.setLimits, (11, 20), p.getGraphXLimits, (11, 20)),
- (y.setLimits, (11, 20), p.getGraphYLimits, (11, 20)),
- (x.setLabel, "fooxx", p.getGraphXLabel, "fooxx"),
- (y.setLabel, "fooyy", p.getGraphYLabel, "fooyy"),
- (y.setInverted, False, p.isYAxisInverted, False),
- (x.setScale, x.LINEAR, p.isXAxisLogarithmic, False),
- (y.setScale, y.LINEAR, p.isYAxisLogarithmic, False),
- (x.setAutoScale, True, p.isXAxisAutoScale, True),
- (y.setAutoScale, True, p.isYAxisAutoScale, True),
- ]
- for testCase in tests:
- setter, value, getter, expected = testCase
- with self.subTest():
- if setter is not None:
- if not isinstance(value, tuple):
- value = (value, )
- setter(*value)
- if getter is not None:
- self.assertEqual(getter(), expected)
-
- def testOldPlotAxis_Logarithmic(self):
- """Test silx API prior to silx 0.6"""
- x = self.plot.getXAxis()
- y = self.plot.getYAxis()
- yright = self.plot.getYAxis(axis="right")
-
- self.assertEqual(x.getScale(), x.LINEAR)
- self.assertEqual(y.getScale(), x.LINEAR)
- self.assertEqual(yright.getScale(), x.LINEAR)
-
- self.plot.setXAxisLogarithmic(True)
- self.assertEqual(x.getScale(), x.LOGARITHMIC)
- self.assertEqual(y.getScale(), x.LINEAR)
- self.assertEqual(yright.getScale(), x.LINEAR)
- self.assertEqual(self.plot.isXAxisLogarithmic(), True)
- self.assertEqual(self.plot.isYAxisLogarithmic(), False)
-
- self.plot.setYAxisLogarithmic(True)
- self.assertEqual(x.getScale(), x.LOGARITHMIC)
- self.assertEqual(y.getScale(), x.LOGARITHMIC)
- self.assertEqual(yright.getScale(), x.LOGARITHMIC)
- self.assertEqual(self.plot.isXAxisLogarithmic(), True)
- self.assertEqual(self.plot.isYAxisLogarithmic(), True)
-
- yright.setScale(yright.LINEAR)
- self.assertEqual(x.getScale(), x.LOGARITHMIC)
- self.assertEqual(y.getScale(), x.LINEAR)
- self.assertEqual(yright.getScale(), x.LINEAR)
- self.assertEqual(self.plot.isXAxisLogarithmic(), True)
- self.assertEqual(self.plot.isYAxisLogarithmic(), False)
-
- def testOldPlotAxis_AutoScale(self):
- """Test silx API prior to silx 0.6"""
- x = self.plot.getXAxis()
- y = self.plot.getYAxis()
- yright = self.plot.getYAxis(axis="right")
-
- self.assertEqual(x.isAutoScale(), True)
- self.assertEqual(y.isAutoScale(), True)
- self.assertEqual(yright.isAutoScale(), True)
-
- self.plot.setXAxisAutoScale(False)
- self.assertEqual(x.isAutoScale(), False)
- self.assertEqual(y.isAutoScale(), True)
- self.assertEqual(yright.isAutoScale(), True)
- self.assertEqual(self.plot.isXAxisAutoScale(), False)
- self.assertEqual(self.plot.isYAxisAutoScale(), True)
-
- self.plot.setYAxisAutoScale(False)
- self.assertEqual(x.isAutoScale(), False)
- self.assertEqual(y.isAutoScale(), False)
- self.assertEqual(yright.isAutoScale(), False)
- self.assertEqual(self.plot.isXAxisAutoScale(), False)
- self.assertEqual(self.plot.isYAxisAutoScale(), False)
-
- yright.setAutoScale(True)
- self.assertEqual(x.isAutoScale(), False)
- self.assertEqual(y.isAutoScale(), True)
- self.assertEqual(yright.isAutoScale(), True)
- self.assertEqual(self.plot.isXAxisAutoScale(), False)
- self.assertEqual(self.plot.isYAxisAutoScale(), True)
-
- def testOldPlotAxis_Inverted(self):
- """Test silx API prior to silx 0.6"""
- x = self.plot.getXAxis()
- y = self.plot.getYAxis()
- yright = self.plot.getYAxis(axis="right")
-
- self.assertEqual(x.isInverted(), False)
- self.assertEqual(y.isInverted(), False)
- self.assertEqual(yright.isInverted(), False)
-
- self.plot.setYAxisInverted(True)
- self.assertEqual(x.isInverted(), False)
- self.assertEqual(y.isInverted(), True)
- self.assertEqual(yright.isInverted(), True)
- self.assertEqual(self.plot.isYAxisInverted(), True)
-
- yright.setInverted(False)
- self.assertEqual(x.isInverted(), False)
- self.assertEqual(y.isInverted(), False)
- self.assertEqual(yright.isInverted(), False)
- self.assertEqual(self.plot.isYAxisInverted(), False)
-
- def testLogXWithData(self):
- self.plot.setGraphTitle('Curve X: Log Y: Linear')
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=True,
- color='green', linestyle="-", symbol='o')
- axis = self.plot.getXAxis()
- axis.setScale(axis.LOGARITHMIC)
-
- self.assertEqual(axis.getScale(), axis.LOGARITHMIC)
-
- def testLogYWithData(self):
- self.plot.setGraphTitle('Curve X: Linear Y: Log')
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=True,
- color='green', linestyle="-", symbol='o')
- axis = self.plot.getYAxis()
- axis.setScale(axis.LOGARITHMIC)
-
- self.assertEqual(axis.getScale(), axis.LOGARITHMIC)
- axis = self.plot.getYAxis(axis="right")
- self.assertEqual(axis.getScale(), axis.LOGARITHMIC)
-
- def testLogYRightWithData(self):
- self.plot.setGraphTitle('Curve X: Linear Y: Log')
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=True,
- color='green', linestyle="-", symbol='o')
- axis = self.plot.getYAxis(axis="right")
- axis.setScale(axis.LOGARITHMIC)
-
- self.assertEqual(axis.getScale(), axis.LOGARITHMIC)
- axis = self.plot.getYAxis()
- self.assertEqual(axis.getScale(), axis.LOGARITHMIC)
-
- def testLimitsChanged_setLimits(self):
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=False,
- color='green', linestyle="-", symbol='o')
- listener = SignalListener()
- self.plot.getXAxis().sigLimitsChanged.connect(listener.partial(axis="x"))
- self.plot.getYAxis().sigLimitsChanged.connect(listener.partial(axis="y"))
- self.plot.getYAxis(axis="right").sigLimitsChanged.connect(listener.partial(axis="y2"))
- self.plot.setLimits(0, 1, 0, 1, 0, 1)
- # at least one event per axis
- self.assertEqual(len(set(listener.karguments(argumentName="axis"))), 3)
-
- def testLimitsChanged_resetZoom(self):
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=False,
- color='green', linestyle="-", symbol='o')
- listener = SignalListener()
- self.plot.getXAxis().sigLimitsChanged.connect(listener.partial(axis="x"))
- self.plot.getYAxis().sigLimitsChanged.connect(listener.partial(axis="y"))
- self.plot.getYAxis(axis="right").sigLimitsChanged.connect(listener.partial(axis="y2"))
- self.plot.resetZoom()
- # at least one event per axis
- self.assertEqual(len(set(listener.karguments(argumentName="axis"))), 3)
-
- def testLimitsChanged_setXLimit(self):
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=False,
- color='green', linestyle="-", symbol='o')
- listener = SignalListener()
- axis = self.plot.getXAxis()
- axis.sigLimitsChanged.connect(listener)
- axis.setLimits(20, 30)
- # at least one event per axis
- self.assertEqual(listener.arguments(callIndex=-1), (20.0, 30.0))
- self.assertEqual(axis.getLimits(), (20.0, 30.0))
-
- def testLimitsChanged_setYLimit(self):
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=False,
- color='green', linestyle="-", symbol='o')
- listener = SignalListener()
- axis = self.plot.getYAxis()
- axis.sigLimitsChanged.connect(listener)
- axis.setLimits(20, 30)
- # at least one event per axis
- self.assertEqual(listener.arguments(callIndex=-1), (20.0, 30.0))
- self.assertEqual(axis.getLimits(), (20.0, 30.0))
-
- def testLimitsChanged_setYRightLimit(self):
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=False,
- color='green', linestyle="-", symbol='o')
- listener = SignalListener()
- axis = self.plot.getYAxis(axis="right")
- axis.sigLimitsChanged.connect(listener)
- axis.setLimits(20, 30)
- # at least one event per axis
- self.assertEqual(listener.arguments(callIndex=-1), (20.0, 30.0))
- self.assertEqual(axis.getLimits(), (20.0, 30.0))
-
- def testScaleProxy(self):
- listener = SignalListener()
- y = self.plot.getYAxis()
- yright = self.plot.getYAxis(axis="right")
- y.sigScaleChanged.connect(listener.partial("left"))
- yright.sigScaleChanged.connect(listener.partial("right"))
- yright.setScale(yright.LOGARITHMIC)
-
- self.assertEqual(y.getScale(), y.LOGARITHMIC)
- events = listener.arguments()
- self.assertEqual(len(events), 2)
- self.assertIn(("left", y.LOGARITHMIC), events)
- self.assertIn(("right", y.LOGARITHMIC), events)
-
- def testAutoScaleProxy(self):
- listener = SignalListener()
- y = self.plot.getYAxis()
- yright = self.plot.getYAxis(axis="right")
- y.sigAutoScaleChanged.connect(listener.partial("left"))
- yright.sigAutoScaleChanged.connect(listener.partial("right"))
- yright.setAutoScale(False)
-
- self.assertEqual(y.isAutoScale(), False)
- events = listener.arguments()
- self.assertEqual(len(events), 2)
- self.assertIn(("left", False), events)
- self.assertIn(("right", False), events)
-
- def testInvertedProxy(self):
- listener = SignalListener()
- y = self.plot.getYAxis()
- yright = self.plot.getYAxis(axis="right")
- y.sigInvertedChanged.connect(listener.partial("left"))
- yright.sigInvertedChanged.connect(listener.partial("right"))
- yright.setInverted(True)
-
- self.assertEqual(y.isInverted(), True)
- events = listener.arguments()
- self.assertEqual(len(events), 2)
- self.assertIn(("left", True), events)
- self.assertIn(("right", True), events)
-
- def testAxesDisplayedFalse(self):
- """Test coverage on setAxesDisplayed(False)"""
- self.plot.setAxesDisplayed(False)
-
- def testAxesDisplayedTrue(self):
- """Test coverage on setAxesDisplayed(True)"""
- self.plot.setAxesDisplayed(True)
-
- def testAxesMargins(self):
- """Test PlotWidget's getAxesMargins and setAxesMargins"""
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- margins = self.plot.getAxesMargins()
- self.assertEqual(margins, (.15, .1, .1, .15))
-
- for margins in ((0., 0., 0., 0.), (.15, .1, .1, .15)):
- with self.subTest(margins=margins):
- self.plot.setAxesMargins(*margins)
- self.qapp.processEvents()
- self.assertEqual(self.plot.getAxesMargins(), margins)
-
- def testBoundingRectItem(self):
- item = BoundingRect()
- item.setBounds((-1000, 1000, -2000, 2000))
- self.plot.addItem(item)
- self.plot.resetZoom()
- limits = numpy.array(self.plot.getXAxis().getLimits())
- numpy.testing.assert_almost_equal(limits, numpy.array([-1000, 1000]))
- limits = numpy.array(self.plot.getYAxis().getLimits())
- numpy.testing.assert_almost_equal(limits, numpy.array([-2000, 2000]))
-
- def testBoundingRectRightItem(self):
- item = BoundingRect()
- item.setYAxis("right")
- item.setBounds((-1000, 1000, -2000, 2000))
- self.plot.addItem(item)
- self.plot.resetZoom()
- limits = numpy.array(self.plot.getXAxis().getLimits())
- numpy.testing.assert_almost_equal(limits, numpy.array([-1000, 1000]))
- limits = numpy.array(self.plot.getYAxis("right").getLimits())
- numpy.testing.assert_almost_equal(limits, numpy.array([-2000, 2000]))
-
- def testBoundingRectArguments(self):
- item = BoundingRect()
- with self.assertRaises(Exception):
- item.setBounds((1000, -1000, -2000, 2000))
- with self.assertRaises(Exception):
- item.setBounds((-1000, 1000, 2000, -2000))
-
- def testBoundingRectWithLog(self):
- item = BoundingRect()
- self.plot.addItem(item)
-
- item.setBounds((-1000, 1000, -2000, 2000))
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.getYAxis()._setLogarithmic(False)
- self.assertEqual(item.getBounds(), (1000, 1000, -2000, 2000))
-
- item.setBounds((-1000, 1000, -2000, 2000))
- self.plot.getXAxis()._setLogarithmic(False)
- self.plot.getYAxis()._setLogarithmic(True)
- self.assertEqual(item.getBounds(), (-1000, 1000, 2000, 2000))
-
- item.setBounds((-1000, 0, -2000, 2000))
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.getYAxis()._setLogarithmic(False)
- self.assertIsNone(item.getBounds())
-
- def testAxisExtent(self):
- """Test XAxisExtent and yAxisExtent"""
- for cls, axis in ((XAxisExtent, self.plot.getXAxis()),
- (YAxisExtent, self.plot.getYAxis())):
- for range_, logRange in (((2, 3), (2, 3)),
- ((-2, -1), (1, 100)),
- ((-1, 3), (3. * 0.9, 3. * 1.1))):
- extent = cls()
- extent.setRange(*range_)
- self.plot.addItem(extent)
-
- for isLog, plotRange in ((False, range_), (True, logRange)):
- with self.subTest(
- cls=cls.__name__, range=range_, isLog=isLog):
- axis._setLogarithmic(isLog)
- self.plot.resetZoom()
- self.qapp.processEvents()
- self.assertEqual(axis.getLimits(), plotRange)
-
- axis._setLogarithmic(False)
- self.plot.clear()
-
-
-class TestPlotCurveLog(PlotWidgetTestCase, ParametricTestCase):
- """Basic tests for addCurve with log scale axes"""
-
- # Test data
- xData = numpy.arange(1000) + 1
- yData = xData ** 2
-
- def _setLabels(self):
- self.plot.getXAxis().setLabel('X')
- self.plot.getYAxis().setLabel('X * X')
-
- def testPlotCurveLogX(self):
- self._setLabels()
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.setGraphTitle('Curve X: Log Y: Linear')
-
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=True,
- color='green', linestyle="-", symbol='o')
-
- def testPlotCurveLogY(self):
- self._setLabels()
- self.plot.getYAxis()._setLogarithmic(True)
-
- self.plot.setGraphTitle('Curve X: Linear Y: Log')
-
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=True,
- color='green', linestyle="-", symbol='o')
-
- def testPlotCurveLogXY(self):
- self._setLabels()
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.getYAxis()._setLogarithmic(True)
-
- self.plot.setGraphTitle('Curve X: Log Y: Log')
-
- self.plot.addCurve(self.xData, self.yData,
- legend="curve",
- replace=False, resetzoom=True,
- color='green', linestyle="-", symbol='o')
-
- def testPlotCurveErrorLogXY(self):
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.getYAxis()._setLogarithmic(True)
-
- # Every second error leads to negative number
- errors = numpy.ones_like(self.xData)
- errors[::2] = self.xData[::2] + 1
-
- tests = [ # name, xerror, yerror
- ('xerror=3', 3, None),
- ('xerror=N array', errors, None),
- ('xerror=Nx1 array', errors.reshape(len(errors), 1), None),
- ('xerror=2xN array', numpy.array((errors, errors)), None),
- ('yerror=6', None, 6),
- ('yerror=N array', None, errors ** 2),
- ('yerror=Nx1 array', None, (errors ** 2).reshape(len(errors), 1)),
- ('yerror=2xN array', None, numpy.array((errors, errors)) ** 2),
- ]
-
- for name, xError, yError in tests:
- with self.subTest(name):
- self.plot.setGraphTitle(name)
- self.plot.addCurve(self.xData, self.yData,
- legend=name,
- xerror=xError, yerror=yError,
- replace=False, resetzoom=True,
- color='green', linestyle="-", symbol='o')
-
- self.qapp.processEvents()
-
- self.plot.clear()
- self.plot.resetZoom()
- self.qapp.processEvents()
-
- def testPlotCurveToggleLog(self):
- """Add a curve with negative data and toggle log axis"""
- arange = numpy.arange(1000) + 1
- tests = [ # name, xData, yData
- ('x>0, some negative y', arange, arange - 500),
- ('x>0, y<0', arange, -arange),
- ('some negative x, y>0', arange - 500, arange),
- ('x<0, y>0', -arange, arange),
- ('some negative x and y', arange - 500, arange - 500),
- ('x<0, y<0', -arange, -arange),
- ]
-
- for name, xData, yData in tests:
- with self.subTest(name):
- self.plot.addCurve(xData, yData, resetzoom=True)
- self.qapp.processEvents()
-
- # no log axis
- xLim = self.plot.getXAxis().getLimits()
- self.assertEqual(xLim, (min(xData), max(xData)))
- yLim = self.plot.getYAxis().getLimits()
- self.assertEqual(yLim, (min(yData), max(yData)))
-
- # x axis log
- self.plot.getXAxis()._setLogarithmic(True)
- self.qapp.processEvents()
-
- xLim = self.plot.getXAxis().getLimits()
- yLim = self.plot.getYAxis().getLimits()
- positives = xData > 0
- if numpy.any(positives):
- self.assertTrue(numpy.allclose(
- xLim, (min(xData[positives]), max(xData[positives]))))
- self.assertEqual(
- yLim, (min(yData[positives]), max(yData[positives])))
- else: # No positive x in the curve
- self.assertEqual(xLim, (1., 100.))
- self.assertEqual(yLim, (1., 100.))
-
- # x axis and y axis log
- self.plot.getYAxis()._setLogarithmic(True)
- self.qapp.processEvents()
-
- xLim = self.plot.getXAxis().getLimits()
- yLim = self.plot.getYAxis().getLimits()
- positives = numpy.logical_and(xData > 0, yData > 0)
- if numpy.any(positives):
- self.assertTrue(numpy.allclose(
- xLim, (min(xData[positives]), max(xData[positives]))))
- self.assertTrue(numpy.allclose(
- yLim, (min(yData[positives]), max(yData[positives]))))
- else: # No positive x and y in the curve
- self.assertEqual(xLim, (1., 100.))
- self.assertEqual(yLim, (1., 100.))
-
- # y axis log
- self.plot.getXAxis()._setLogarithmic(False)
- self.qapp.processEvents()
-
- xLim = self.plot.getXAxis().getLimits()
- yLim = self.plot.getYAxis().getLimits()
- positives = yData > 0
- if numpy.any(positives):
- self.assertEqual(
- xLim, (min(xData[positives]), max(xData[positives])))
- self.assertTrue(numpy.allclose(
- yLim, (min(yData[positives]), max(yData[positives]))))
- else: # No positive y in the curve
- self.assertEqual(xLim, (1., 100.))
- self.assertEqual(yLim, (1., 100.))
-
- # no log axis
- self.plot.getYAxis()._setLogarithmic(False)
- self.qapp.processEvents()
-
- xLim = self.plot.getXAxis().getLimits()
- self.assertEqual(xLim, (min(xData), max(xData)))
- yLim = self.plot.getYAxis().getLimits()
- self.assertEqual(yLim, (min(yData), max(yData)))
-
- self.plot.clear()
- self.plot.resetZoom()
- self.qapp.processEvents()
-
-
-class TestPlotImageLog(PlotWidgetTestCase):
- """Basic tests for addImage with log scale axes."""
-
- def setUp(self):
- super(TestPlotImageLog, self).setUp()
-
- self.plot.getXAxis().setLabel('Columns')
- self.plot.getYAxis().setLabel('Rows')
-
- def testPlotColormapGrayLogX(self):
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.setGraphTitle('CMap X: Log Y: Linear')
-
- colormap = Colormap(name='gray',
- normalization='linear',
- vmin=None,
- vmax=None)
- self.plot.addImage(DATA_2D, legend="image 1",
- origin=(1., 1.), scale=(1., 1.),
- resetzoom=False, colormap=colormap)
- self.plot.resetZoom()
-
- def testPlotColormapGrayLogY(self):
- self.plot.getYAxis()._setLogarithmic(True)
- self.plot.setGraphTitle('CMap X: Linear Y: Log')
-
- colormap = Colormap(name='gray',
- normalization='linear',
- vmin=None,
- vmax=None)
- self.plot.addImage(DATA_2D, legend="image 1",
- origin=(1., 1.), scale=(1., 1.),
- resetzoom=False, colormap=colormap)
- self.plot.resetZoom()
-
- def testPlotColormapGrayLogXY(self):
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.getYAxis()._setLogarithmic(True)
- self.plot.setGraphTitle('CMap X: Log Y: Log')
-
- colormap = Colormap(name='gray',
- normalization='linear',
- vmin=None,
- vmax=None)
- self.plot.addImage(DATA_2D, legend="image 1",
- origin=(1., 1.), scale=(1., 1.),
- resetzoom=False, colormap=colormap)
- self.plot.resetZoom()
-
- def testPlotRgbRgbaLogXY(self):
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.getYAxis()._setLogarithmic(True)
- self.plot.setGraphTitle('RGB + RGBA X: Log Y: Log')
-
- rgb = numpy.array(
- (((0, 0, 0), (128, 0, 0), (255, 0, 0)),
- ((0, 128, 0), (0, 128, 128), (0, 128, 256))),
- dtype=numpy.uint8)
-
- self.plot.addImage(rgb, legend="rgb",
- origin=(1, 1), scale=(10, 10),
- resetzoom=False)
-
- rgba = numpy.array(
- (((0, 0, 0, .5), (.5, 0, 0, 1), (1, 0, 0, .5)),
- ((0, .5, 0, 1), (0, .5, .5, 1), (0, 1, 1, .5))),
- dtype=numpy.float32)
-
- self.plot.addImage(rgba, legend="rgba",
- origin=(5., 5.), scale=(10., 10.),
- resetzoom=False)
- self.plot.resetZoom()
-
-
-class TestPlotMarkerLog(PlotWidgetTestCase):
- """Basic tests for markers on log scales"""
-
- # Test marker parameters
- markers = [ # x, y, color, selectable, draggable
- (10., 10., 'blue', False, False),
- (20., 20., 'red', False, False),
- (40., 100., 'green', True, False),
- (40., 500., 'gray', True, True),
- (60., 800., 'black', False, True),
- ]
-
- def setUp(self):
- super(TestPlotMarkerLog, self).setUp()
-
- self.plot.getYAxis().setLabel('Rows')
- self.plot.getXAxis().setLabel('Columns')
- self.plot.getXAxis().setAutoScale(False)
- self.plot.getYAxis().setAutoScale(False)
- self.plot.setKeepDataAspectRatio(False)
- self.plot.setLimits(1., 100., 1., 1000.)
- self.plot.getXAxis()._setLogarithmic(True)
- self.plot.getYAxis()._setLogarithmic(True)
-
- def testPlotMarkerXLog(self):
- self.plot.setGraphTitle('Markers X, Log axes')
-
- for x, _, color, select, drag in self.markers:
- name = str(x)
- if select:
- name += " sel."
- if drag:
- name += " drag"
- self.plot.addXMarker(x, name, name, color, select, drag)
- self.plot.resetZoom()
-
- def testPlotMarkerYLog(self):
- self.plot.setGraphTitle('Markers Y, Log axes')
-
- for _, y, color, select, drag in self.markers:
- name = str(y)
- if select:
- name += " sel."
- if drag:
- name += " drag"
- self.plot.addYMarker(y, name, name, color, select, drag)
- self.plot.resetZoom()
-
- def testPlotMarkerPtLog(self):
- self.plot.setGraphTitle('Markers Pt, Log axes')
-
- for x, y, color, select, drag in self.markers:
- name = "{0},{1}".format(x, y)
- if select:
- name += " sel."
- if drag:
- name += " drag"
- self.plot.addMarker(x, y, name, name, color, select, drag)
- self.plot.resetZoom()
-
-
-class TestPlotWidgetSwitchBackend(PlotWidgetTestCase):
- """Test [get|set]Backend to switch backend"""
-
- def testSwitchBackend(self):
- """Test switching a plot with a few items"""
- backends = {'none': 'BackendBase', 'mpl': 'BackendMatplotlibQt'}
- if test_options.WITH_GL_TEST:
- backends['gl'] = 'BackendOpenGL'
-
- self.plot.addImage(numpy.arange(100).reshape(10, 10))
- self.plot.addCurve((-3, -2, -1), (1, 2, 3))
- self.plot.resetZoom()
- xlimits = self.plot.getXAxis().getLimits()
- ylimits = self.plot.getYAxis().getLimits()
- items = self.plot.getItems()
- self.assertEqual(len(items), 2)
-
- for backend, className in backends.items():
- with self.subTest(backend=backend):
- self.plot.setBackend(backend)
- self.plot.replot()
-
- retrievedBackend = self.plot.getBackend()
- self.assertEqual(type(retrievedBackend).__name__, className)
- self.assertEqual(self.plot.getXAxis().getLimits(), xlimits)
- self.assertEqual(self.plot.getYAxis().getLimits(), ylimits)
- self.assertEqual(self.plot.getItems(), items)
-
-
-class TestPlotWidgetSelection(PlotWidgetTestCase):
- """Test PlotWidget.selection and active items handling"""
-
- def _checkSelection(self, selection, current=None, selected=()):
- """Check current item and selected items."""
- self.assertIs(selection.getCurrentItem(), current)
- self.assertEqual(selection.getSelectedItems(), selected)
-
- def testSyncWithActiveItems(self):
- """Test update of PlotWidgetSelection according to active items"""
- listener = SignalListener()
-
- selection = self.plot.selection()
- selection.sigCurrentItemChanged.connect(listener)
- self._checkSelection(selection)
-
- # Active item is current
- self.plot.addImage(((0, 1), (2, 3)), legend='image')
- image = self.plot.getActiveImage()
- self.assertEqual(listener.callCount(), 1)
- self._checkSelection(selection, image, (image,))
-
- # No active = no current
- self.plot.setActiveImage(None)
- self.assertEqual(listener.callCount(), 2)
- self._checkSelection(selection)
-
- # Active item is current
- self.plot.setActiveImage('image')
- self.assertEqual(listener.callCount(), 3)
- self._checkSelection(selection, image, (image,))
-
- # Mosted recently "actived" item is current
- self.plot.addScatter((3, 2, 1), (0, 1, 2), (0, 1, 2), legend='scatter')
- scatter = self.plot.getActiveScatter()
- self.assertEqual(listener.callCount(), 4)
- self._checkSelection(selection, scatter, (scatter, image))
-
- # Previously mosted recently "actived" item is current
- self.plot.setActiveScatter(None)
- self.assertEqual(listener.callCount(), 5)
- self._checkSelection(selection, image, (image,))
-
- # Mosted recently "actived" item is current
- self.plot.setActiveScatter('scatter')
- self.assertEqual(listener.callCount(), 6)
- self._checkSelection(selection, scatter, (scatter, image))
-
- # No active = no current
- self.plot.setActiveImage(None)
- self.plot.setActiveScatter(None)
- self.assertEqual(listener.callCount(), 7)
- self._checkSelection(selection)
-
- # Mosted recently "actived" item is current
- self.plot.setActiveScatter('scatter')
- self.assertEqual(listener.callCount(), 8)
- self.plot.setActiveImage('image')
- self.assertEqual(listener.callCount(), 9)
- self._checkSelection(selection, image, (image, scatter))
-
- # Add a curve which is not active by default
- self.plot.addCurve((0, 1, 2), (0, 1, 2), legend='curve')
- curve = self.plot.getCurve('curve')
- self.assertEqual(listener.callCount(), 9)
- self._checkSelection(selection, image, (image, scatter))
-
- # Mosted recently "actived" item is current
- self.plot.setActiveCurve('curve')
- self.assertEqual(listener.callCount(), 10)
- self._checkSelection(selection, curve, (curve, image, scatter))
-
- # Add a curve which is not active by default
- self.plot.addCurve((0, 1, 2), (0, 1, 2), legend='curve2')
- curve2 = self.plot.getCurve('curve2')
- self.assertEqual(listener.callCount(), 10)
- self._checkSelection(selection, curve, (curve, image, scatter))
-
- # Mosted recently "actived" item is current, previous curve is removed
- self.plot.setActiveCurve('curve2')
- self.assertEqual(listener.callCount(), 11)
- self._checkSelection(selection, curve2, (curve2, image, scatter))
-
- # No items = no current
- self.plot.clear()
- self.assertEqual(listener.callCount(), 12)
- self._checkSelection(selection)
-
- def testPlotWidgetWithItems(self):
- """Test init of selection on a plot with items"""
- self.plot.addImage(((0, 1), (2, 3)), legend='image')
- self.plot.addScatter((3, 2, 1), (0, 1, 2), (0, 1, 2), legend='scatter')
- self.plot.addCurve((0, 1, 2), (0, 1, 2), legend='curve')
- self.plot.setActiveCurve('curve')
-
- selection = self.plot.selection()
- self.assertIsNotNone(selection.getCurrentItem())
- selected = selection.getSelectedItems()
- self.assertEqual(len(selected), 3)
- self.assertIn(self.plot.getActiveCurve(), selected)
- self.assertIn(self.plot.getActiveImage(), selected)
- self.assertIn(self.plot.getActiveScatter(), selected)
-
- def testSetCurrentItem(self):
- """Test setCurrentItem"""
- # Add items to the plot
- self.plot.addImage(((0, 1), (2, 3)), legend='image')
- image = self.plot.getActiveImage()
- self.plot.addScatter((3, 2, 1), (0, 1, 2), (0, 1, 2), legend='scatter')
- scatter = self.plot.getActiveScatter()
- self.plot.addCurve((0, 1, 2), (0, 1, 2), legend='curve')
- self.plot.setActiveCurve('curve')
- curve = self.plot.getActiveCurve()
-
- selection = self.plot.selection()
- self.assertIsNotNone(selection.getCurrentItem())
- self.assertEqual(len(selection.getSelectedItems()), 3)
-
- # Set current to None reset all active items
- selection.setCurrentItem(None)
- self._checkSelection(selection)
- self.assertIsNone(self.plot.getActiveCurve())
- self.assertIsNone(self.plot.getActiveImage())
- self.assertIsNone(self.plot.getActiveScatter())
-
- # Set current to an item makes it active
- selection.setCurrentItem(image)
- self._checkSelection(selection, image, (image,))
- self.assertIsNone(self.plot.getActiveCurve())
- self.assertIs(self.plot.getActiveImage(), image)
- self.assertIsNone(self.plot.getActiveScatter())
-
- # Set current to an item makes it active and keeps other active
- selection.setCurrentItem(curve)
- self._checkSelection(selection, curve, (curve, image))
- self.assertIs(self.plot.getActiveCurve(), curve)
- self.assertIs(self.plot.getActiveImage(), image)
- self.assertIsNone(self.plot.getActiveScatter())
-
- # Set current to an item makes it active and keeps other active
- selection.setCurrentItem(scatter)
- self._checkSelection(selection, scatter, (scatter, curve, image))
- self.assertIs(self.plot.getActiveCurve(), curve)
- self.assertIs(self.plot.getActiveImage(), image)
- self.assertIs(self.plot.getActiveScatter(), scatter)
-
-
-def suite():
- testClasses = (TestPlotWidget,
- TestPlotImage,
- TestPlotCurve,
- TestPlotHistogram,
- TestPlotScatter,
- TestPlotMarker,
- TestPlotItem,
- TestPlotAxes,
- TestPlotActiveCurveImage,
- TestPlotEmptyLog,
- TestPlotCurveLog,
- TestPlotImageLog,
- TestPlotMarkerLog,
- TestPlotWidgetSelection)
-
- test_suite = unittest.TestSuite()
-
- # Tests with matplotlib
- for testClass in testClasses:
- test_suite.addTest(parameterize(testClass, backend=None))
-
- test_suite.addTest(parameterize(TestSpecialBackend, backend=u"mpl"))
- if sys.version_info[0] == 2:
- test_suite.addTest(parameterize(TestSpecialBackend, backend=b"mpl"))
-
- if test_options.WITH_GL_TEST:
- # Tests with OpenGL backend
- for testClass in testClasses:
- test_suite.addTest(parameterize(testClass, backend='gl'))
-
- test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(
- TestPlotWidgetSwitchBackend))
-
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testPlotWidgetNoBackend.py b/silx/gui/plot/test/testPlotWidgetNoBackend.py
deleted file mode 100644
index edd3cd7..0000000
--- a/silx/gui/plot/test/testPlotWidgetNoBackend.py
+++ /dev/null
@@ -1,631 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2020 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 tests for PlotWidget with 'none' backend"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "17/01/2018"
-
-
-import unittest
-from functools import reduce
-from silx.utils.testutils import ParametricTestCase
-
-import numpy
-
-from silx.gui.plot.PlotWidget import PlotWidget
-from silx.gui.plot.items.histogram import _getHistogramCurve, _computeEdges
-
-
-class TestPlot(unittest.TestCase):
- """Basic tests of Plot without backend"""
-
- def testPlotTitleLabels(self):
- """Create a Plot and set the labels"""
-
- plot = PlotWidget(backend='none')
-
- title, xlabel, ylabel = 'the title', 'x label', 'y label'
- plot.setGraphTitle(title)
- plot.getXAxis().setLabel(xlabel)
- plot.getYAxis().setLabel(ylabel)
-
- self.assertEqual(plot.getGraphTitle(), title)
- self.assertEqual(plot.getXAxis().getLabel(), xlabel)
- self.assertEqual(plot.getYAxis().getLabel(), ylabel)
-
- def testAddNoRemove(self):
- """add objects to the Plot"""
-
- plot = PlotWidget(backend='none')
- plot.addCurve(x=(1, 2, 3), y=(3, 2, 1))
- plot.addImage(numpy.arange(100.).reshape(10, -1))
- plot.addShape(numpy.array((1., 10.)),
- numpy.array((10., 10.)),
- shape="rectangle")
- plot.addXMarker(10.)
-
-
-class TestPlotRanges(ParametricTestCase):
- """Basic tests of Plot data ranges without backend"""
-
- _getValidValues = {True: lambda ar: ar > 0,
- False: lambda ar: numpy.ones(shape=ar.shape,
- dtype=bool)}
-
- @staticmethod
- def _getRanges(arrays, are_logs):
- gen = (TestPlotRanges._getValidValues[is_log](ar)
- for (ar, is_log) in zip(arrays, are_logs))
- indices = numpy.where(reduce(numpy.logical_and, gen))[0]
- if len(indices) > 0:
- ranges = [(ar[indices[0]], ar[indices[-1]]) for ar in arrays]
- else:
- ranges = [None] * len(arrays)
-
- return ranges
-
- @staticmethod
- def _getRangesMinmax(ranges):
- # TODO : error if None in ranges.
- rangeMin = numpy.min([rng[0] for rng in ranges])
- rangeMax = numpy.max([rng[1] for rng in ranges])
- return rangeMin, rangeMax
-
- def testDataRangeNoPlot(self):
- """empty plot data range"""
-
- plot = PlotWidget(backend='none')
-
- for logX, logY in ((False, False),
- (True, False),
- (True, True),
- (False, True),
- (False, False)):
- with self.subTest(logX=logX, logY=logY):
- plot.getXAxis()._setLogarithmic(logX)
- plot.getYAxis()._setLogarithmic(logY)
- dataRange = plot.getDataRange()
- self.assertIsNone(dataRange.x)
- self.assertIsNone(dataRange.y)
- self.assertIsNone(dataRange.yright)
-
- def testDataRangeLeft(self):
- """left axis range"""
-
- plot = PlotWidget(backend='none')
-
- xData = numpy.arange(10) - 4.9 # range : -4.9 , 4.1
- yData = numpy.arange(10) - 6.9 # range : -6.9 , 2.1
-
- plot.addCurve(x=xData,
- y=yData,
- legend='plot_0',
- yaxis='left')
-
- for logX, logY in ((False, False),
- (True, False),
- (True, True),
- (False, True),
- (False, False)):
- with self.subTest(logX=logX, logY=logY):
- plot.getXAxis()._setLogarithmic(logX)
- plot.getYAxis()._setLogarithmic(logY)
- dataRange = plot.getDataRange()
- xRange, yRange = self._getRanges([xData, yData],
- [logX, logY])
- self.assertSequenceEqual(dataRange.x, xRange)
- self.assertSequenceEqual(dataRange.y, yRange)
- self.assertIsNone(dataRange.yright)
-
- def testDataRangeRight(self):
- """right axis range"""
-
- plot = PlotWidget(backend='none')
- xData = numpy.arange(10) - 4.9 # range : -4.9 , 4.1
- yData = numpy.arange(10) - 6.9 # range : -6.9 , 2.1
- plot.addCurve(x=xData,
- y=yData,
- legend='plot_0',
- yaxis='right')
-
- for logX, logY in ((False, False),
- (True, False),
- (True, True),
- (False, True),
- (False, False)):
- with self.subTest(logX=logX, logY=logY):
- plot.getXAxis()._setLogarithmic(logX)
- plot.getYAxis()._setLogarithmic(logY)
- dataRange = plot.getDataRange()
- xRange, yRange = self._getRanges([xData, yData],
- [logX, logY])
- self.assertSequenceEqual(dataRange.x, xRange)
- self.assertIsNone(dataRange.y)
- self.assertSequenceEqual(dataRange.yright, yRange)
-
- def testDataRangeImage(self):
- """image data range"""
-
- origin = (-10, 25)
- scale = (3., 8.)
- image = numpy.arange(100.).reshape(20, 5)
-
- plot = PlotWidget(backend='none')
- plot.addImage(image,
- origin=origin, scale=scale)
-
- xRange = numpy.array([0., image.shape[1] * scale[0]]) + origin[0]
- yRange = numpy.array([0., image.shape[0] * scale[1]]) + origin[1]
-
- ranges = {(False, False): (xRange, yRange),
- (True, False): (None, None),
- (True, True): (None, None),
- (False, True): (None, None)}
-
- for logX, logY in ((False, False),
- (True, False),
- (True, True),
- (False, True),
- (False, False)):
- with self.subTest(logX=logX, logY=logY):
- plot.getXAxis()._setLogarithmic(logX)
- plot.getYAxis()._setLogarithmic(logY)
- dataRange = plot.getDataRange()
- xRange, yRange = ranges[logX, logY]
- self.assertTrue(numpy.array_equal(dataRange.x, xRange),
- msg='{0} != {1}'.format(dataRange.x, xRange))
- self.assertTrue(numpy.array_equal(dataRange.y, yRange),
- msg='{0} != {1}'.format(dataRange.y, yRange))
- self.assertIsNone(dataRange.yright)
-
- def testDataRangeLeftRight(self):
- """right+left axis range"""
-
- plot = PlotWidget(backend='none')
-
- xData_l = numpy.arange(10) - 0.9 # range : -0.9 , 8.1
- yData_l = numpy.arange(10) - 1.9 # range : -1.9 , 7.1
- plot.addCurve(x=xData_l,
- y=yData_l,
- legend='plot_l',
- yaxis='left')
-
- xData_r = numpy.arange(10) - 4.9 # range : -4.9 , 4.1
- yData_r = numpy.arange(10) - 6.9 # range : -6.9 , 2.1
- plot.addCurve(x=xData_r,
- y=yData_r,
- legend='plot_r',
- yaxis='right')
-
- for logX, logY in ((False, False),
- (True, False),
- (True, True),
- (False, True),
- (False, False)):
- with self.subTest(logX=logX, logY=logY):
- plot.getXAxis()._setLogarithmic(logX)
- plot.getYAxis()._setLogarithmic(logY)
- dataRange = plot.getDataRange()
- xRangeL, yRangeL = self._getRanges([xData_l, yData_l],
- [logX, logY])
- xRangeR, yRangeR = self._getRanges([xData_r, yData_r],
- [logX, logY])
- xRangeLR = self._getRangesMinmax([xRangeL, xRangeR])
- self.assertSequenceEqual(dataRange.x, xRangeLR)
- self.assertSequenceEqual(dataRange.y, yRangeL)
- self.assertSequenceEqual(dataRange.yright, yRangeR)
-
- def testDataRangeCurveImage(self):
- """right+left+image axis range"""
-
- # overlapping ranges :
- # image sets x min and y max
- # plot_left sets y min
- # plot_right sets x max (and yright)
- plot = PlotWidget(backend='none')
-
- origin = (-10, 5)
- scale = (3., 8.)
- image = numpy.arange(100.).reshape(20, 5)
-
- plot.addImage(image,
- origin=origin, scale=scale, legend='image')
-
- xData_l = numpy.arange(10) - 0.9 # range : -0.9 , 8.1
- yData_l = numpy.arange(10) - 1.9 # range : -1.9 , 7.1
- plot.addCurve(x=xData_l,
- y=yData_l,
- legend='plot_l',
- yaxis='left')
-
- xData_r = numpy.arange(10) + 4.1 # range : 4.1 , 13.1
- yData_r = numpy.arange(10) - 0.9 # range : -0.9 , 8.1
- plot.addCurve(x=xData_r,
- y=yData_r,
- legend='plot_r',
- yaxis='right')
-
- imgXRange = numpy.array([0., image.shape[1] * scale[0]]) + origin[0]
- imgYRange = numpy.array([0., image.shape[0] * scale[1]]) + origin[1]
-
- for logX, logY in ((False, False),
- (True, False),
- (True, True),
- (False, True),
- (False, False)):
- with self.subTest(logX=logX, logY=logY):
- plot.getXAxis()._setLogarithmic(logX)
- plot.getYAxis()._setLogarithmic(logY)
- dataRange = plot.getDataRange()
- xRangeL, yRangeL = self._getRanges([xData_l, yData_l],
- [logX, logY])
- xRangeR, yRangeR = self._getRanges([xData_r, yData_r],
- [logX, logY])
- if logX or logY:
- xRangeLR = self._getRangesMinmax([xRangeL, xRangeR])
- else:
- xRangeLR = self._getRangesMinmax([xRangeL,
- xRangeR,
- imgXRange])
- yRangeL = self._getRangesMinmax([yRangeL, imgYRange])
- self.assertSequenceEqual(dataRange.x, xRangeLR)
- self.assertSequenceEqual(dataRange.y, yRangeL)
- self.assertSequenceEqual(dataRange.yright, yRangeR)
-
- def testDataRangeImageNegativeScaleX(self):
- """image data range, negative scale"""
-
- origin = (-10, 25)
- scale = (-3., 8.)
- image = numpy.arange(100.).reshape(20, 5)
-
- plot = PlotWidget(backend='none')
- plot.addImage(image,
- origin=origin, scale=scale)
-
- xRange = numpy.array([0., image.shape[1] * scale[0]]) + origin[0]
- xRange.sort() # negative scale!
- yRange = numpy.array([0., image.shape[0] * scale[1]]) + origin[1]
-
- ranges = {(False, False): (xRange, yRange),
- (True, False): (None, None),
- (True, True): (None, None),
- (False, True): (None, None)}
-
- for logX, logY in ((False, False),
- (True, False),
- (True, True),
- (False, True),
- (False, False)):
- with self.subTest(logX=logX, logY=logY):
- plot.getXAxis()._setLogarithmic(logX)
- plot.getYAxis()._setLogarithmic(logY)
- dataRange = plot.getDataRange()
- xRange, yRange = ranges[logX, logY]
- self.assertTrue(numpy.array_equal(dataRange.x, xRange),
- msg='{0} != {1}'.format(dataRange.x, xRange))
- self.assertTrue(numpy.array_equal(dataRange.y, yRange),
- msg='{0} != {1}'.format(dataRange.y, yRange))
- self.assertIsNone(dataRange.yright)
-
- def testDataRangeImageNegativeScaleY(self):
- """image data range, negative scale"""
-
- origin = (-10, 25)
- scale = (3., -8.)
- image = numpy.arange(100.).reshape(20, 5)
-
- plot = PlotWidget(backend='none')
- plot.addImage(image,
- origin=origin, scale=scale)
-
- xRange = numpy.array([0., image.shape[1] * scale[0]]) + origin[0]
- yRange = numpy.array([0., image.shape[0] * scale[1]]) + origin[1]
- yRange.sort() # negative scale!
-
- ranges = {(False, False): (xRange, yRange),
- (True, False): (None, None),
- (True, True): (None, None),
- (False, True): (None, None)}
-
- for logX, logY in ((False, False),
- (True, False),
- (True, True),
- (False, True),
- (False, False)):
- with self.subTest(logX=logX, logY=logY):
- plot.getXAxis()._setLogarithmic(logX)
- plot.getYAxis()._setLogarithmic(logY)
- dataRange = plot.getDataRange()
- xRange, yRange = ranges[logX, logY]
- self.assertTrue(numpy.array_equal(dataRange.x, xRange),
- msg='{0} != {1}'.format(dataRange.x, xRange))
- self.assertTrue(numpy.array_equal(dataRange.y, yRange),
- msg='{0} != {1}'.format(dataRange.y, yRange))
- self.assertIsNone(dataRange.yright)
-
- def testDataRangeHiddenCurve(self):
- """curves with a hidden curve"""
- plot = PlotWidget(backend='none')
- plot.addCurve((0, 1), (0, 1), legend='shown')
- plot.addCurve((0, 1, 2), (5, 5, 5), legend='hidden')
- range1 = plot.getDataRange()
- self.assertEqual(range1.x, (0, 2))
- self.assertEqual(range1.y, (0, 5))
- plot.hideCurve('hidden')
- range2 = plot.getDataRange()
- self.assertEqual(range2.x, (0, 1))
- self.assertEqual(range2.y, (0, 1))
-
-
-class TestPlotGetCurveImage(unittest.TestCase):
- """Test of plot getCurve and getImage methods"""
-
- def testGetCurve(self):
- """PlotWidget.getCurve and Plot.getActiveCurve tests"""
-
- plot = PlotWidget(backend='none')
-
- # No curve
- curve = plot.getCurve()
- self.assertIsNone(curve) # No curve
-
- plot.setActiveCurveHandling(True)
- plot.addCurve(x=(0, 1), y=(0, 1), legend='curve 0')
- plot.addCurve(x=(0, 1), y=(0, 1), legend='curve 1')
- plot.addCurve(x=(0, 1), y=(0, 1), legend='curve 2')
- plot.setActiveCurve('curve 0')
-
- # Active curve
- active = plot.getActiveCurve()
- self.assertEqual(active.getName(), 'curve 0')
- curve = plot.getCurve()
- self.assertEqual(curve.getName(), 'curve 0')
-
- # No active curve and curves
- plot.setActiveCurveHandling(False)
- active = plot.getActiveCurve()
- self.assertIsNone(active) # No active curve
- curve = plot.getCurve()
- self.assertEqual(curve.getName(), 'curve 2') # Last added curve
-
- # Last curve hidden
- plot.hideCurve('curve 2', True)
- curve = plot.getCurve()
- self.assertEqual(curve.getName(), 'curve 1') # Last added curve
-
- # All curves hidden
- plot.hideCurve('curve 1', True)
- plot.hideCurve('curve 0', True)
- curve = plot.getCurve()
- self.assertIsNone(curve)
-
- def testGetCurveOldApi(self):
- """old API PlotWidget.getCurve and Plot.getActiveCurve tests"""
-
- plot = PlotWidget(backend='none')
-
- # No curve
- curve = plot.getCurve()
- self.assertIsNone(curve) # No curve
-
- plot.setActiveCurveHandling(True)
- x = numpy.arange(10.).astype(numpy.float32)
- y = x * x
- plot.addCurve(x=x, y=y, legend='curve 0', info=["whatever"])
- plot.addCurve(x=x, y=2*x, legend='curve 1', info="anything")
- plot.setActiveCurve('curve 0')
-
- # Active curve (4 elements)
- xOut, yOut, legend, info = plot.getActiveCurve()[:4]
- self.assertEqual(legend, 'curve 0')
- self.assertTrue(numpy.allclose(xOut, x), 'curve 0 wrong x data')
- self.assertTrue(numpy.allclose(yOut, y), 'curve 0 wrong y data')
-
- # Active curve (5 elements)
- xOut, yOut, legend, info, params = plot.getCurve("curve 1")
- self.assertEqual(legend, 'curve 1')
- self.assertEqual(info, 'anything')
- self.assertTrue(numpy.allclose(xOut, x), 'curve 1 wrong x data')
- self.assertTrue(numpy.allclose(yOut, 2 * x), 'curve 1 wrong y data')
-
- def testGetImage(self):
- """PlotWidget.getImage and PlotWidget.getActiveImage tests"""
-
- plot = PlotWidget(backend='none')
-
- # No image
- image = plot.getImage()
- self.assertIsNone(image)
-
- plot.addImage(((0, 1), (2, 3)), legend='image 0')
- plot.addImage(((0, 1), (2, 3)), legend='image 1')
-
- # Active image
- active = plot.getActiveImage()
- self.assertEqual(active.getName(), 'image 0')
- image = plot.getImage()
- self.assertEqual(image.getName(), 'image 0')
-
- # No active image
- plot.addImage(((0, 1), (2, 3)), legend='image 2')
- plot.setActiveImage(None)
- active = plot.getActiveImage()
- self.assertIsNone(active)
- image = plot.getImage()
- self.assertEqual(image.getName(), 'image 2')
-
- # Active image
- plot.setActiveImage('image 1')
- active = plot.getActiveImage()
- self.assertEqual(active.getName(), 'image 1')
- image = plot.getImage()
- self.assertEqual(image.getName(), 'image 1')
-
- def testGetImageOldApi(self):
- """PlotWidget.getImage and PlotWidget.getActiveImage old API tests"""
-
- plot = PlotWidget(backend='none')
-
- # No image
- image = plot.getImage()
- self.assertIsNone(image)
-
- image = numpy.arange(10).astype(numpy.float32)
- image.shape = 5, 2
-
- plot.addImage(image, legend='image 0', info=["Hi!"])
-
- # Active image
- data, legend, info, something, params = plot.getActiveImage()
- self.assertEqual(legend, 'image 0')
- self.assertEqual(info, ["Hi!"])
- self.assertTrue(numpy.allclose(data, image), "image 0 data not correct")
-
- def testGetAllImages(self):
- """PlotWidget.getAllImages test"""
-
- plot = PlotWidget(backend='none')
-
- # No image
- images = plot.getAllImages()
- self.assertEqual(len(images), 0)
-
- # 2 images
- data = numpy.arange(100).reshape(10, 10)
- plot.addImage(data, legend='1')
- plot.addImage(data, origin=(10, 10), legend='2')
- images = plot.getAllImages(just_legend=True)
- self.assertEqual(list(images), ['1', '2'])
- images = plot.getAllImages(just_legend=False)
- self.assertEqual(len(images), 2)
- self.assertEqual(images[0].getName(), '1')
- self.assertEqual(images[1].getName(), '2')
-
-
-class TestPlotAddScatter(unittest.TestCase):
- """Test of plot addScatter"""
-
- def testAddGetScatter(self):
-
- plot = PlotWidget(backend='none')
-
- # No curve
- scatter = plot._getItem(kind="scatter")
- self.assertIsNone(scatter) # No curve
-
- plot.addScatter(x=(0, 1), y=(0, 1), value=(0, 1), legend='scatter 0')
- plot.addScatter(x=(0, 1), y=(0, 1), value=(0, 1), legend='scatter 1')
- plot.addScatter(x=(0, 1), y=(0, 1), value=(0, 1), legend='scatter 2')
- plot._setActiveItem('scatter', 'scatter 0')
-
- # Active scatter
- active = plot._getActiveItem(kind='scatter')
- self.assertEqual(active.getName(), 'scatter 0')
-
- # check default values
- self.assertAlmostEqual(active.getSymbolSize(), active._DEFAULT_SYMBOL_SIZE)
- self.assertEqual(active.getSymbol(), "o")
- self.assertAlmostEqual(active.getAlpha(), 1.0)
-
- # modify parameters
- active.setSymbolSize(20.5)
- active.setSymbol("d")
- active.setAlpha(0.777)
-
- s0 = plot.getScatter("scatter 0")
-
- self.assertAlmostEqual(s0.getSymbolSize(), 20.5)
- self.assertEqual(s0.getSymbol(), "d")
- self.assertAlmostEqual(s0.getAlpha(), 0.777)
-
- scatter1 = plot._getItem(kind='scatter', legend='scatter 1')
- self.assertEqual(scatter1.getName(), 'scatter 1')
-
- def testGetAllScatters(self):
- """PlotWidget.getAllImages test"""
-
- plot = PlotWidget(backend='none')
-
- items = plot.getItems()
- self.assertEqual(len(items), 0)
-
- plot.addScatter(x=(0, 1), y=(0, 1), value=(0, 1), legend='scatter 0')
- plot.addScatter(x=(0, 1), y=(0, 1), value=(0, 1), legend='scatter 1')
- plot.addScatter(x=(0, 1), y=(0, 1), value=(0, 1), legend='scatter 2')
-
- items = plot.getItems()
- self.assertEqual(len(items), 3)
- self.assertEqual(items[0].getName(), 'scatter 0')
- self.assertEqual(items[1].getName(), 'scatter 1')
- self.assertEqual(items[2].getName(), 'scatter 2')
-
-
-class TestPlotHistogram(unittest.TestCase):
- """Basic tests for histogram."""
-
- def testEdges(self):
- x = numpy.array([0, 1, 2])
- edgesRight = numpy.array([0, 1, 2, 3])
- edgesLeft = numpy.array([-1, 0, 1, 2])
- edgesCenter = numpy.array([-0.5, 0.5, 1.5, 2.5])
-
- # testing x values for right
- edges = _computeEdges(x, 'right')
- numpy.testing.assert_array_equal(edges, edgesRight)
-
- edges = _computeEdges(x, 'center')
- numpy.testing.assert_array_equal(edges, edgesCenter)
-
- edges = _computeEdges(x, 'left')
- numpy.testing.assert_array_equal(edges, edgesLeft)
-
- def testHistogramCurve(self):
- y = numpy.array([3, 2, 5])
- edges = numpy.array([0, 1, 2, 3])
-
- xHisto, yHisto = _getHistogramCurve(y, edges)
- numpy.testing.assert_array_equal(
- yHisto, numpy.array([3, 3, 2, 2, 5, 5]))
-
- y = numpy.array([-3, 2, 5, 0])
- edges = numpy.array([-2, -1, 0, 1, 2])
- xHisto, yHisto = _getHistogramCurve(y, edges)
- numpy.testing.assert_array_equal(
- yHisto, numpy.array([-3, -3, 2, 2, 5, 5, 0, 0]))
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for TestClass in (TestPlot, TestPlotRanges, TestPlotGetCurveImage,
- TestPlotHistogram, TestPlotAddScatter):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testPlotWindow.py b/silx/gui/plot/test/testPlotWindow.py
deleted file mode 100644
index e12b756..0000000
--- a/silx/gui/plot/test/testPlotWindow.py
+++ /dev/null
@@ -1,185 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2020 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 tests for PlotWindow"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "27/06/2017"
-
-
-import unittest
-import numpy
-
-from silx.gui.utils.testutils import TestCaseQt, getQToolButtonFromAction
-from silx.test.utils import test_options
-
-from silx.gui import qt
-from silx.gui.plot import PlotWindow
-from silx.gui.colors import Colormap
-
-class TestPlotWindow(TestCaseQt):
- """Base class for tests of PlotWindow."""
-
- def setUp(self):
- super(TestPlotWindow, self).setUp()
- self.plot = PlotWindow()
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
- def tearDown(self):
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
- super(TestPlotWindow, self).tearDown()
-
- def testActions(self):
- """Test the actions QToolButtons"""
- self.plot.setLimits(1, 100, 1, 100)
-
- checkList = [ # QAction, Plot state getter
- (self.plot.xAxisAutoScaleAction, self.plot.getXAxis().isAutoScale),
- (self.plot.yAxisAutoScaleAction, self.plot.getYAxis().isAutoScale),
- (self.plot.xAxisLogarithmicAction, self.plot.getXAxis()._isLogarithmic),
- (self.plot.yAxisLogarithmicAction, self.plot.getYAxis()._isLogarithmic),
- (self.plot.gridAction, self.plot.getGraphGrid),
- ]
-
- for action, getter in checkList:
- self.mouseMove(self.plot)
- initialState = getter()
- toolButton = getQToolButtonFromAction(action)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
- self.assertNotEqual(getter(), initialState,
- msg='"%s" state not changed' % action.text())
-
- self.mouseClick(toolButton, qt.Qt.LeftButton)
- self.assertEqual(getter(), initialState,
- msg='"%s" state not changed' % action.text())
-
- # Trigger a zoom reset
- self.mouseMove(self.plot)
- resetZoomAction = self.plot.resetZoomAction
- toolButton = getQToolButtonFromAction(resetZoomAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- def testDockWidgets(self):
- """Test add/remove dock widgets"""
- dock1 = qt.QDockWidget('Test 1')
- dock1.setWidget(qt.QLabel('Test 1'))
-
- self.plot.addTabbedDockWidget(dock1)
- self.qapp.processEvents()
-
- self.plot.removeDockWidget(dock1)
- self.qapp.processEvents()
-
- dock2 = qt.QDockWidget('Test 2')
- dock2.setWidget(qt.QLabel('Test 2'))
-
- self.plot.addTabbedDockWidget(dock2)
- self.qapp.processEvents()
-
- if qt.BINDING != 'PySide2':
- # Weird bug with PySide2 later upon gc.collect() when getting the layout
- self.assertNotEqual(self.plot.layout().indexOf(dock2),
- -1,
- "dock2 not properly displayed")
-
- def testToolAspectRatio(self):
- self.plot.toolBar()
- self.plot.keepDataAspectRatioButton.keepDataAspectRatio()
- self.assertTrue(self.plot.isKeepDataAspectRatio())
- self.plot.keepDataAspectRatioButton.dontKeepDataAspectRatio()
- self.assertFalse(self.plot.isKeepDataAspectRatio())
-
- def testToolYAxisOrigin(self):
- self.plot.toolBar()
- self.plot.yAxisInvertedButton.setYAxisUpward()
- self.assertFalse(self.plot.getYAxis().isInverted())
- self.plot.yAxisInvertedButton.setYAxisDownward()
- self.assertTrue(self.plot.getYAxis().isInverted())
-
- def testColormapAutoscaleCache(self):
- # Test that the min/max cache is not computed twice
-
- old = Colormap._computeAutoscaleRange
- self._count = 0
- def _computeAutoscaleRange(colormap, data):
- self._count = self._count + 1
- return 10, 20
- Colormap._computeAutoscaleRange = _computeAutoscaleRange
- try:
- colormap = Colormap(name='red')
- self.plot.setVisible(True)
-
- # Add an image
- data = numpy.arange(8**2).reshape(8, 8)
- self.plot.addImage(data, legend="foo", colormap=colormap)
- self.plot.setActiveImage("foo")
-
- # Use the colorbar
- self.plot.getColorBarWidget().setVisible(True)
- self.qWait(50)
-
- # Remove and add again the same item
- image = self.plot.getImage("foo")
- self.plot.removeImage("foo")
- self.plot.addItem(image)
- self.qWait(50)
- finally:
- Colormap._computeAutoscaleRange = old
- self.assertEqual(self._count, 1)
- del self._count
-
- @unittest.skipUnless(test_options.WITH_GL_TEST,
- test_options.WITH_QT_TEST_REASON)
- def testSwitchBackend(self):
- """Test switching an empty plot"""
- self.plot.resetZoom()
- xlimits = self.plot.getXAxis().getLimits()
- ylimits = self.plot.getYAxis().getLimits()
- isKeepAspectRatio = self.plot.isKeepDataAspectRatio()
-
- for backend in ('gl', 'mpl'):
- with self.subTest():
- self.plot.setBackend(backend)
- self.plot.replot()
- self.assertEqual(self.plot.getXAxis().getLimits(), xlimits)
- self.assertEqual(self.plot.getYAxis().getLimits(), ylimits)
- self.assertEqual(
- self.plot.isKeepDataAspectRatio(), isKeepAspectRatio)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotWindow))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testRoiStatsWidget.py b/silx/gui/plot/test/testRoiStatsWidget.py
deleted file mode 100644
index 378d499..0000000
--- a/silx/gui/plot/test/testRoiStatsWidget.py
+++ /dev/null
@@ -1,290 +0,0 @@
-# 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.
-#
-# ###########################################################################*/
-"""Tests for ROIStatsWidget"""
-
-
-from silx.gui.utils.testutils import TestCaseQt
-from silx.gui import qt
-from silx.gui.plot import PlotWindow
-from silx.gui.plot.stats.stats import Stats
-from silx.gui.plot.ROIStatsWidget import ROIStatsWidget
-from silx.gui.plot.CurvesROIWidget import ROI
-from silx.gui.plot.items.roi import RectangleROI, PolygonROI
-from silx.gui.plot.StatsWidget import UpdateMode
-import unittest
-import numpy
-
-
-
-class _TestRoiStatsBase(TestCaseQt):
- """Base class for several unittest relative to ROIStatsWidget"""
- def setUp(self):
- TestCaseQt.setUp(self)
- # define plot
- self.plot = PlotWindow()
- self.plot.addImage(numpy.arange(10000).reshape(100, 100),
- legend='img1')
- self.img_item = self.plot.getImage('img1')
- self.plot.addCurve(x=numpy.linspace(0, 10, 56), y=numpy.arange(56),
- legend='curve1')
- self.curve_item = self.plot.getCurve('curve1')
- self.plot.addHistogram(edges=numpy.linspace(0, 10, 56),
- histogram=numpy.arange(56), legend='histo1')
- self.histogram_item = self.plot.getHistogram(legend='histo1')
- self.plot.addScatter(x=numpy.linspace(0, 10, 56),
- y=numpy.linspace(0, 10, 56),
- value=numpy.arange(56),
- legend='scatter1')
- self.scatter_item = self.plot.getScatter(legend='scatter1')
-
- # stats widget
- self.statsWidget = ROIStatsWidget(plot=self.plot)
-
- # define stats
- stats = [
- ('sum', numpy.sum),
- ('mean', numpy.mean),
- ]
- self.statsWidget.setStats(stats=stats)
-
- # define rois
- self.roi1D = ROI(name='range1', fromdata=0, todata=4, type_='energy')
- self.rectangle_roi = RectangleROI()
- self.rectangle_roi.setGeometry(origin=(0, 0), size=(20, 20))
- self.rectangle_roi.setName('Initial ROI')
- self.polygon_roi = PolygonROI()
- points = numpy.array([[0, 5], [5, 0], [10, 5], [5, 10]])
- self.polygon_roi.setPoints(points)
-
- def statsTable(self):
- return self.statsWidget._statsROITable
-
- def tearDown(self):
- Stats._getContext.cache_clear()
- self.statsWidget.setAttribute(qt.Qt.WA_DeleteOnClose, True)
- self.statsWidget.close()
- self.statsWidget = None
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose, True)
- self.plot.close()
- self.plot = None
- TestCaseQt.tearDown(self)
-
-
-class TestRoiStatsCouple(_TestRoiStatsBase):
- """
- Test different possible couple (roi, plotItem).
- Check that:
-
- * computation is correct if couple is valid
- * raise an error if couple is invalid
- """
- def testROICurve(self):
- """
- Test that the couple (ROI, curveItem) can be used for stats
- """
- item = self.statsWidget.addItem(roi=self.roi1D,
- plotItem=self.curve_item)
- assert item is not None
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['sum'].text(), '253')
- self.assertEqual(tableItems['mean'].text(), '11.0')
-
- def testRectangleImage(self):
- """
- Test that the couple (RectangleROI, imageItem) can be used for stats
- """
- item = self.statsWidget.addItem(roi=self.rectangle_roi,
- plotItem=self.img_item)
- assert item is not None
- self.plot.addImage(numpy.ones(10000).reshape(100, 100),
- legend='img1')
- self.qapp.processEvents()
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['sum'].text(), str(float(21*21)))
- self.assertEqual(tableItems['mean'].text(), '1.0')
-
- def testPolygonImage(self):
- """
- Test that the couple (PolygonROI, imageItem) can be used for stats
- """
- item = self.statsWidget.addItem(roi=self.polygon_roi,
- plotItem=self.img_item)
- assert item is not None
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['sum'].text(), '22750')
- self.assertEqual(tableItems['mean'].text(), '455.0')
-
- def testROIImage(self):
- """
- Test that the couple (ROI, imageItem) is raising an error
- """
- with self.assertRaises(TypeError):
- self.statsWidget.addItem(roi=self.roi1D,
- plotItem=self.img_item)
-
- def testRectangleCurve(self):
- """
- Test that the couple (rectangleROI, curveItem) is raising an error
- """
- with self.assertRaises(TypeError):
- self.statsWidget.addItem(roi=self.rectangle_roi,
- plotItem=self.curve_item)
-
- def testROIHistogram(self):
- """
- Test that the couple (PolygonROI, imageItem) can be used for stats
- """
- item = self.statsWidget.addItem(roi=self.roi1D,
- plotItem=self.histogram_item)
- assert item is not None
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['sum'].text(), '253')
- self.assertEqual(tableItems['mean'].text(), '11.0')
-
- def testROIScatter(self):
- """
- Test that the couple (PolygonROI, imageItem) can be used for stats
- """
- item = self.statsWidget.addItem(roi=self.roi1D,
- plotItem=self.scatter_item)
- assert item is not None
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['sum'].text(), '253')
- self.assertEqual(tableItems['mean'].text(), '11.0')
-
-
-class TestRoiStatsAddRemoveItem(_TestRoiStatsBase):
- """Test adding and removing (roi, plotItem) items"""
- def testAddRemoveItems(self):
- item1 = self.statsWidget.addItem(roi=self.roi1D,
- plotItem=self.scatter_item)
- self.assertTrue(item1 is not None)
- self.assertEqual(self.statsTable().rowCount(), 1)
- item2 = self.statsWidget.addItem(roi=self.roi1D,
- plotItem=self.histogram_item)
- self.assertTrue(item2 is not None)
- self.assertEqual(self.statsTable().rowCount(), 2)
- # try to add twice the same item
- item3 = self.statsWidget.addItem(roi=self.roi1D,
- plotItem=self.histogram_item)
- self.assertTrue(item3 is None)
- self.assertEqual(self.statsTable().rowCount(), 2)
- item4 = self.statsWidget.addItem(roi=self.roi1D,
- plotItem=self.curve_item)
- self.assertTrue(item4 is not None)
- self.assertEqual(self.statsTable().rowCount(), 3)
-
- self.statsWidget.removeItem(plotItem=item4._plot_item,
- roi=item4._roi)
- self.assertEqual(self.statsTable().rowCount(), 2)
- # try to remove twice the same item
- self.statsWidget.removeItem(plotItem=item4._plot_item,
- roi=item4._roi)
- self.assertEqual(self.statsTable().rowCount(), 2)
- self.statsWidget.removeItem(plotItem=item2._plot_item,
- roi=item2._roi)
- self.statsWidget.removeItem(plotItem=item1._plot_item,
- roi=item1._roi)
- self.assertEqual(self.statsTable().rowCount(), 0)
-
-
-class TestRoiStatsRoiUpdate(_TestRoiStatsBase):
- """Test that the stats will be updated if the roi is updated"""
- def testChangeRoi(self):
- item = self.statsWidget.addItem(roi=self.rectangle_roi,
- plotItem=self.img_item)
- assert item is not None
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['sum'].text(), '445410')
- self.assertEqual(tableItems['mean'].text(), '1010.0')
-
- # update roi
- self.rectangle_roi.setOrigin(position=(10, 10))
- self.assertNotEqual(tableItems['sum'].text(), '445410')
- self.assertNotEqual(tableItems['mean'].text(), '1010.0')
-
- def testUpdateModeScenario(self):
- """Test update according to a simple scenario"""
- self.statsWidget._setUpdateMode(UpdateMode.AUTO)
- item = self.statsWidget.addItem(roi=self.rectangle_roi,
- plotItem=self.img_item)
-
- assert item is not None
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['sum'].text(), '445410')
- self.assertEqual(tableItems['mean'].text(), '1010.0')
- self.statsWidget._setUpdateMode(UpdateMode.MANUAL)
- self.rectangle_roi.setOrigin(position=(10, 10))
- self.qapp.processEvents()
- self.assertNotEqual(tableItems['sum'].text(), '445410')
- self.assertNotEqual(tableItems['mean'].text(), '1010.0')
- self.statsWidget._updateAllStats(is_request=True)
- self.assertNotEqual(tableItems['sum'].text(), '445410')
- self.assertNotEqual(tableItems['mean'].text(), '1010.0')
-
-
-class TestRoiStatsPlotItemUpdate(_TestRoiStatsBase):
- """Test that the stats will be updated if the plot item is updated"""
- def testChangeImage(self):
- self.statsWidget._setUpdateMode(UpdateMode.AUTO)
- item = self.statsWidget.addItem(roi=self.rectangle_roi,
- plotItem=self.img_item)
-
- assert item is not None
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['mean'].text(), '1010.0')
-
- # update plot
- self.plot.addImage(numpy.arange(100, 10100).reshape(100, 100),
- legend='img1')
- self.assertNotEqual(tableItems['mean'].text(), '1059.5')
-
- def testUpdateModeScenario(self):
- """Test update according to a simple scenario"""
- self.statsWidget._setUpdateMode(UpdateMode.MANUAL)
- item = self.statsWidget.addItem(roi=self.rectangle_roi,
- plotItem=self.img_item)
-
- assert item is not None
- tableItems = self.statsTable()._itemToTableItems(item)
- self.assertEqual(tableItems['mean'].text(), '1010.0')
- self.plot.addImage(numpy.arange(100, 10100).reshape(100, 100),
- legend='img1')
- self.assertEqual(tableItems['mean'].text(), '1010.0')
- self.statsWidget._updateAllStats(is_request=True)
- self.assertEqual(tableItems['mean'].text(), '1110.0')
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for TestClass in (TestRoiStatsCouple, TestRoiStatsRoiUpdate,
- TestRoiStatsPlotItemUpdate):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testSaveAction.py b/silx/gui/plot/test/testSaveAction.py
deleted file mode 100644
index 0eb129d..0000000
--- a/silx/gui/plot/test/testSaveAction.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2017-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 the plot's save action (consistency of output)"""
-
-__authors__ = ["P. Knobel"]
-__license__ = "MIT"
-__date__ = "28/11/2017"
-
-
-import unittest
-import tempfile
-import os
-
-from silx.gui.plot.test.utils import PlotWidgetTestCase
-
-from silx.gui.plot import PlotWidget
-from silx.gui.plot.actions.io import SaveAction
-
-
-class TestSaveActionSaveCurvesAsSpec(unittest.TestCase):
-
- def setUp(self):
- self.plot = PlotWidget(backend='none')
- self.saveAction = SaveAction(plot=self.plot)
-
- self.tempdir = tempfile.mkdtemp()
- self.out_fname = os.path.join(self.tempdir, "out.dat")
-
- def tearDown(self):
- os.unlink(self.out_fname)
- os.rmdir(self.tempdir)
-
- def testSaveMultipleCurvesAsSpec(self):
- """Test that labels are properly used."""
- self.plot.setGraphXLabel("graph x label")
- self.plot.setGraphYLabel("graph y label")
-
- self.plot.addCurve([0, 1], [1, 2], "curve with labels",
- xlabel="curve0 X", ylabel="curve0 Y")
- self.plot.addCurve([-1, 3], [-6, 2], "curve with X label",
- xlabel="curve1 X")
- self.plot.addCurve([-2, 0], [8, 12], "curve with Y label",
- ylabel="curve2 Y")
- self.plot.addCurve([3, 1], [7, 6], "curve with no labels")
-
- self.saveAction._saveCurves(self.plot,
- self.out_fname,
- SaveAction.DEFAULT_ALL_CURVES_FILTERS[0]) # "All curves as SpecFile (*.dat)"
-
- with open(self.out_fname, "rb") as f:
- file_content = f.read()
- if hasattr(file_content, "decode"):
- file_content = file_content.decode()
-
- # case with all curve labels specified
- self.assertIn("#S 1 curve0 Y", file_content)
- self.assertIn("#L curve0 X curve0 Y", file_content)
-
- # graph X&Y labels are used when no curve label is specified
- self.assertIn("#S 2 graph y label", file_content)
- self.assertIn("#L curve1 X graph y label", file_content)
-
- self.assertIn("#S 3 curve2 Y", file_content)
- self.assertIn("#L graph x label curve2 Y", file_content)
-
- self.assertIn("#S 4 graph y label", file_content)
- self.assertIn("#L graph x label graph y label", file_content)
-
-
-class TestSaveActionExtension(PlotWidgetTestCase):
- """Test SaveAction file filter API"""
-
- def _dummySaveFunction(self, plot, filename, nameFilter):
- pass
-
- def testFileFilterAPI(self):
- """Test addition/update of a file filter"""
- saveAction = SaveAction(plot=self.plot, parent=self.plot)
-
- # Add a new file filter
- nameFilter = 'Dummy file (*.dummy)'
- saveAction.setFileFilter('all', nameFilter, self._dummySaveFunction)
- self.assertTrue(nameFilter in saveAction.getFileFilters('all'))
- self.assertEqual(saveAction.getFileFilters('all')[nameFilter],
- self._dummySaveFunction)
-
- # Add a new file filter at a particular position
- nameFilter = 'Dummy file2 (*.dummy)'
- saveAction.setFileFilter('all', nameFilter,
- self._dummySaveFunction, index=3)
- self.assertTrue(nameFilter in saveAction.getFileFilters('all'))
- filters = saveAction.getFileFilters('all')
- self.assertEqual(filters[nameFilter], self._dummySaveFunction)
- self.assertEqual(list(filters.keys()).index(nameFilter),3)
-
- # Update an existing file filter
- nameFilter = SaveAction.IMAGE_FILTER_EDF
- saveAction.setFileFilter('image', nameFilter, self._dummySaveFunction)
- self.assertEqual(saveAction.getFileFilters('image')[nameFilter],
- self._dummySaveFunction)
-
- # Change the position of an existing file filter
- nameFilter = 'Dummy file2 (*.dummy)'
- oldIndex = list(saveAction.getFileFilters('all')).index(nameFilter)
- newIndex = oldIndex - 1
- saveAction.setFileFilter('all', nameFilter,
- self._dummySaveFunction, index=newIndex)
- filters = saveAction.getFileFilters('all')
- self.assertEqual(filters[nameFilter], self._dummySaveFunction)
- self.assertEqual(list(filters.keys()).index(nameFilter), newIndex)
-
-def suite():
- test_suite = unittest.TestSuite()
- for cls in (TestSaveActionSaveCurvesAsSpec, TestSaveActionExtension):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(cls))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testScatterMaskToolsWidget.py b/silx/gui/plot/test/testScatterMaskToolsWidget.py
deleted file mode 100644
index 800f30e..0000000
--- a/silx/gui/plot/test/testScatterMaskToolsWidget.py
+++ /dev/null
@@ -1,318 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-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.
-#
-# ###########################################################################*/
-"""Basic tests for MaskToolsWidget"""
-
-__authors__ = ["T. Vincent", "P. Knobel"]
-__license__ = "MIT"
-__date__ = "17/01/2018"
-
-
-import logging
-import os.path
-import unittest
-
-import numpy
-
-from silx.gui import qt
-from silx.test.utils import temp_dir
-from silx.utils.testutils import ParametricTestCase
-from silx.gui.utils.testutils import getQToolButtonFromAction
-from silx.gui.plot import PlotWindow, ScatterMaskToolsWidget
-from .utils import PlotWidgetTestCase
-
-import fabio
-
-
-_logger = logging.getLogger(__name__)
-
-
-class TestScatterMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase):
- """Basic test for MaskToolsWidget"""
-
- def _createPlot(self):
- return PlotWindow()
-
- def setUp(self):
- super(TestScatterMaskToolsWidget, self).setUp()
- self.widget = ScatterMaskToolsWidget.ScatterMaskToolsDockWidget(
- plot=self.plot, name='TEST')
- self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, self.widget)
-
- self.maskWidget = self.widget.widget()
-
- def tearDown(self):
- del self.maskWidget
- del self.widget
- super(TestScatterMaskToolsWidget, self).tearDown()
-
- def testEmptyPlot(self):
- """Empty plot, display MaskToolsDockWidget, toggle multiple masks"""
- self.maskWidget.setMultipleMasks('single')
- self.qapp.processEvents()
-
- self.maskWidget.setMultipleMasks('exclusive')
- self.qapp.processEvents()
-
- def _drag(self):
- """Drag from plot center to offset position"""
- plot = self.plot.getWidgetHandle()
- xCenter, yCenter = plot.width() // 2, plot.height() // 2
- offset = min(plot.width(), plot.height()) // 10
-
- pos0 = xCenter, yCenter
- pos1 = xCenter + offset, yCenter + offset
-
- self.mouseMove(plot, pos=(0, 0))
- self.mouseMove(plot, pos=pos0)
- self.qapp.processEvents()
- self.mousePress(plot, qt.Qt.LeftButton, pos=pos0)
- self.qapp.processEvents()
-
- self.mouseMove(plot, pos=(pos0[0] + offset // 2, pos0[1] + offset // 2))
- self.mouseMove(plot, pos=pos1)
- self.qapp.processEvents()
- self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos1)
- self.qapp.processEvents()
- self.mouseMove(plot, pos=(0, 0))
-
- def _drawPolygon(self):
- """Draw a star polygon in the plot"""
- plot = self.plot.getWidgetHandle()
- x, y = plot.width() // 2, plot.height() // 2
- offset = min(plot.width(), plot.height()) // 10
-
- star = [(x, y + offset),
- (x - offset, y - offset),
- (x + offset, y),
- (x - offset, y),
- (x + offset, y - offset),
- (x, y + offset)] # Close polygon
-
- self.mouseMove(plot, pos=[0, 0])
- for pos in star:
- self.mouseMove(plot, pos=pos)
- self.qapp.processEvents()
- self.mousePress(plot, qt.Qt.LeftButton, pos=pos)
- self.qapp.processEvents()
- self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos)
- self.qapp.processEvents()
-
- def _drawPencil(self):
- """Draw a star polygon in the plot"""
- plot = self.plot.getWidgetHandle()
- x, y = plot.width() // 2, plot.height() // 2
- offset = min(plot.width(), plot.height()) // 10
-
- star = [(x, y + offset),
- (x - offset, y - offset),
- (x + offset, y),
- (x - offset, y),
- (x + offset, y - offset)]
-
- self.mouseMove(plot, pos=[0, 0])
- self.mouseMove(plot, pos=star[0])
- self.mousePress(plot, qt.Qt.LeftButton, pos=star[0])
- for pos in star[1:]:
- self.mouseMove(plot, pos=pos)
- self.mouseRelease(
- plot, qt.Qt.LeftButton, pos=star[-1])
-
- def testWithAScatter(self):
- """Plot with a Scatter: test MaskToolsWidget interactions"""
-
- # Add and remove a scatter (this should enable/disable GUI + change mask)
- self.plot.addScatter(
- x=numpy.arange(256),
- y=numpy.arange(256),
- value=numpy.random.random(256),
- legend='test')
- self.plot._setActiveItem(kind="scatter", legend="test")
- self.qapp.processEvents()
-
- self.plot.remove('test', kind='scatter')
- self.qapp.processEvents()
-
- self.plot.addScatter(
- x=numpy.arange(1000),
- y=1000 * (numpy.arange(1000) % 20),
- value=numpy.random.random(1000),
- legend='test')
- self.plot._setActiveItem(kind="scatter", legend="test")
- self.plot.resetZoom()
- self.qapp.processEvents()
-
- # Test draw rectangle #
- toolButton = getQToolButtonFromAction(self.maskWidget.rectAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- # mask
- self.maskWidget.maskStateGroup.button(1).click()
- self.qapp.processEvents()
- self._drag()
-
- self.assertFalse(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
-
- # unmask same region
- self.maskWidget.maskStateGroup.button(0).click()
- self.qapp.processEvents()
- self._drag()
- self.assertTrue(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
-
- # Test draw polygon #
- toolButton = getQToolButtonFromAction(self.maskWidget.polygonAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- # mask
- self.maskWidget.maskStateGroup.button(1).click()
- self.qapp.processEvents()
- self._drawPolygon()
- self.assertFalse(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
-
- # unmask same region
- self.maskWidget.maskStateGroup.button(0).click()
- self.qapp.processEvents()
- self._drawPolygon()
- self.assertTrue(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
-
- # Test draw pencil #
- toolButton = getQToolButtonFromAction(self.maskWidget.pencilAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- self.maskWidget.pencilSpinBox.setValue(30)
- self.qapp.processEvents()
-
- # mask
- self.maskWidget.maskStateGroup.button(1).click()
- self.qapp.processEvents()
- self._drawPencil()
- self.assertFalse(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
-
- # unmask same region
- self.maskWidget.maskStateGroup.button(0).click()
- self.qapp.processEvents()
- self._drawPencil()
- self.assertTrue(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
-
- # Test no draw tool #
- toolButton = getQToolButtonFromAction(self.maskWidget.browseAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
-
- self.plot.clear()
-
- def __loadSave(self, file_format):
- self.plot.addScatter(
- x=numpy.arange(256),
- y=25 * (numpy.arange(256) % 10),
- value=numpy.random.random(256),
- legend='test')
- self.plot._setActiveItem(kind="scatter", legend="test")
- self.plot.resetZoom()
- self.qapp.processEvents()
-
- # Draw a polygon mask
- toolButton = getQToolButtonFromAction(self.maskWidget.polygonAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
- self._drawPolygon()
-
- ref_mask = self.maskWidget.getSelectionMask()
- self.assertFalse(numpy.all(numpy.equal(ref_mask, 0)))
-
- with temp_dir() as tmp:
- mask_filename = os.path.join(tmp, 'mask.' + file_format)
- self.maskWidget.save(mask_filename, file_format)
-
- self.maskWidget.resetSelectionMask()
- self.assertTrue(
- numpy.all(numpy.equal(self.maskWidget.getSelectionMask(), 0)))
-
- self.maskWidget.load(mask_filename)
- self.assertTrue(numpy.all(numpy.equal(
- self.maskWidget.getSelectionMask(), ref_mask)))
-
- def testLoadSaveNpy(self):
- self.__loadSave("npy")
-
- def testLoadSaveCsv(self):
- self.__loadSave("csv")
-
- def testSigMaskChangedEmitted(self):
- self.qapp.processEvents()
- self.plot.addScatter(
- x=numpy.arange(1000),
- y=1000 * (numpy.arange(1000) % 20),
- value=numpy.ones((1000,)),
- legend='test')
- self.plot._setActiveItem(kind="scatter", legend="test")
- self.plot.resetZoom()
- self.qapp.processEvents()
-
- self.plot.remove('test', kind='scatter')
- self.qapp.processEvents()
-
- self.plot.addScatter(
- x=numpy.arange(1000),
- y=1000 * (numpy.arange(1000) % 20),
- value=numpy.random.random(1000),
- legend='test')
-
- l = []
-
- def slot():
- l.append(1)
-
- self.maskWidget.sigMaskChanged.connect(slot)
-
- # rectangle mask
- toolButton = getQToolButtonFromAction(self.maskWidget.rectAction)
- self.assertIsNot(toolButton, None)
- self.mouseClick(toolButton, qt.Qt.LeftButton)
- self.maskWidget.maskStateGroup.button(1).click()
- self.qapp.processEvents()
- self._drag()
-
- self.assertGreater(len(l), 0)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for TestClass in (TestScatterMaskToolsWidget,):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testScatterView.py b/silx/gui/plot/test/testScatterView.py
deleted file mode 100644
index 583e3ed..0000000
--- a/silx/gui/plot/test/testScatterView.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 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.
-#
-# ###########################################################################*/
-"""Basic tests for ScatterView"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "06/03/2018"
-
-
-import unittest
-
-import numpy
-
-from silx.gui.plot.items import Axis, Scatter
-from silx.gui.plot import ScatterView
-from silx.gui.plot.test.utils import PlotWidgetTestCase
-
-
-class TestScatterView(PlotWidgetTestCase):
- """Test of ScatterView widget"""
-
- def _createPlot(self):
- return ScatterView()
-
- def test(self):
- """Simple tests"""
- x = numpy.arange(100)
- y = numpy.arange(100)
- value = numpy.arange(100)
- self.plot.setData(x, y, value)
- self.qapp.processEvents()
-
- data = self.plot.getData()
- self.assertEqual(len(data), 5)
- self.assertTrue(numpy.all(numpy.equal(x, data[0])))
- self.assertTrue(numpy.all(numpy.equal(y, data[1])))
- self.assertTrue(numpy.all(numpy.equal(value, data[2])))
- self.assertIsNone(data[3]) # xerror
- self.assertIsNone(data[4]) # yerror
-
- # Test access to scatter item
- self.assertIsInstance(self.plot.getScatterItem(), Scatter)
-
- # Test toolbar actions
-
- action = self.plot.getScatterToolBar().getXAxisLogarithmicAction()
- action.trigger()
- self.qapp.processEvents()
-
- maskAction = self.plot.getScatterToolBar().actions()[-1]
- maskAction.trigger()
- self.qapp.processEvents()
-
- # Test proxy API
-
- self.plot.resetZoom()
- self.qapp.processEvents()
-
- scale = self.plot.getXAxis().getScale()
- self.assertEqual(scale, Axis.LOGARITHMIC)
-
- scale = self.plot.getYAxis().getScale()
- self.assertEqual(scale, Axis.LINEAR)
-
- title = 'Test ScatterView'
- self.plot.setGraphTitle(title)
- self.assertEqual(self.plot.getGraphTitle(), title)
-
- self.qapp.processEvents()
-
- # Reset scatter data
-
- self.plot.setData(None, None, None)
- self.qapp.processEvents()
-
- data = self.plot.getData()
- self.assertEqual(len(data), 5)
- self.assertEqual(len(data[0]), 0) # x
- self.assertEqual(len(data[1]), 0) # y
- self.assertEqual(len(data[2]), 0) # value
- self.assertIsNone(data[3]) # xerror
- self.assertIsNone(data[4]) # yerror
-
- def testAlpha(self):
- """Test alpha transparency in setData"""
- _pts = 100
- _levels = 100
- _fwhm = 50
- x = numpy.random.rand(_pts)*_levels
- y = numpy.random.rand(_pts)*_levels
- value = numpy.random.rand(_pts)*_levels
- x0 = x[int(_pts/2)]
- y0 = x[int(_pts/2)]
- #2D Gaussian kernel
- alpha = numpy.exp(-4*numpy.log(2) * ((x-x0)**2 + (y-y0)**2) / _fwhm**2)
-
- self.plot.setData(x, y, value, alpha=alpha)
- self.qapp.processEvents()
-
- alphaData = self.plot.getScatterItem().getAlphaData()
- self.assertTrue(numpy.all(numpy.equal(alpha, alphaData)))
-
-
-def suite():
- test_suite = unittest.TestSuite()
- loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
- test_suite.addTest(loadTests(TestScatterView))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testStackView.py b/silx/gui/plot/test/testStackView.py
deleted file mode 100644
index 7605bbc..0000000
--- a/silx/gui/plot/test/testStackView.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2020 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 tests for StackView"""
-
-__authors__ = ["P. Knobel"]
-__license__ = "MIT"
-__date__ = "20/03/2017"
-
-
-import unittest
-import numpy
-
-from silx.gui.utils.testutils import TestCaseQt, SignalListener
-
-from silx.gui import qt
-from silx.gui.plot import StackView
-from silx.gui.plot.StackView import StackViewMainWindow
-
-from silx.utils.array_like import ListOfImages
-
-
-class TestStackView(TestCaseQt):
- """Base class for tests of StackView."""
-
- def setUp(self):
- super(TestStackView, self).setUp()
- self.stackview = StackView()
- self.stackview.show()
- self.qWaitForWindowExposed(self.stackview)
- self.mystack = numpy.fromfunction(
- lambda i, j, k: numpy.sin(i/15.) + numpy.cos(j/4.) + 2 * numpy.sin(k/6.),
- (10, 20, 30)
- )
-
- def tearDown(self):
- self.stackview.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.stackview.close()
- del self.stackview
- super(TestStackView, self).tearDown()
-
- def testScaleColormapRangeToStack(self):
- """Test scaleColormapRangeToStack"""
- self.stackview.setStack(self.mystack)
- self.stackview.setColormap("viridis")
- colormap = self.stackview.getColormap()
-
- # Colormap autoscale to image
- self.assertEqual(colormap.getVRange(), (None, None))
- self.stackview.scaleColormapRangeToStack()
-
- # Colormap range set according to stack range
- self.assertEqual(colormap.getVRange(), (self.mystack.min(), self.mystack.max()))
-
- def testSetStack(self):
- self.stackview.setStack(self.mystack)
- self.stackview.setColormap("viridis", autoscale=True)
- my_trans_stack, params = self.stackview.getStack()
- self.assertEqual(my_trans_stack.shape, self.mystack.shape)
- self.assertTrue(numpy.array_equal(self.mystack,
- my_trans_stack))
- self.assertEqual(params["colormap"]["name"],
- "viridis")
-
- def testSetStackPerspective(self):
- self.stackview.setStack(self.mystack, perspective=1)
- # my_orig_stack, params = self.stackview.getStack()
- my_trans_stack, params = self.stackview.getCurrentView()
-
- # get stack returns the transposed data, depending on the perspective
- self.assertEqual(my_trans_stack.shape,
- (self.mystack.shape[1], self.mystack.shape[0], self.mystack.shape[2]))
- self.assertTrue(numpy.array_equal(numpy.transpose(self.mystack, axes=(1, 0, 2)),
- my_trans_stack))
-
- def testSetStackListOfImages(self):
- loi = [self.mystack[i] for i in range(self.mystack.shape[0])]
-
- self.stackview.setStack(loi)
- my_orig_stack, params = self.stackview.getStack(returnNumpyArray=True)
- my_trans_stack, params = self.stackview.getStack(returnNumpyArray=True)
- self.assertEqual(my_trans_stack.shape, self.mystack.shape)
- self.assertTrue(numpy.array_equal(self.mystack,
- my_trans_stack))
- self.assertTrue(numpy.array_equal(self.mystack,
- my_orig_stack))
- self.assertIsInstance(my_trans_stack, numpy.ndarray)
-
- self.stackview.setStack(loi, perspective=2)
- my_orig_stack, params = self.stackview.getStack(copy=False)
- my_trans_stack, params = self.stackview.getCurrentView(copy=False)
- # getStack(copy=False) must return the object set in setStack
- self.assertIs(my_orig_stack, loi)
- # getCurrentView(copy=False) returns a ListOfImages whose .images
- # attr is the original data
- self.assertEqual(my_trans_stack.shape,
- (self.mystack.shape[2], self.mystack.shape[0], self.mystack.shape[1]))
- self.assertTrue(numpy.array_equal(numpy.array(my_trans_stack),
- numpy.transpose(self.mystack, axes=(2, 0, 1))))
- self.assertIsInstance(my_trans_stack,
- ListOfImages) # returnNumpyArray=False by default in getStack
- self.assertIs(my_trans_stack.images, loi)
-
- def testPerspective(self):
- self.stackview.setStack(numpy.arange(24).reshape((2, 3, 4)))
- self.assertEqual(self.stackview._perspective, 0,
- "Default perspective is not 0 (dim1-dim2).")
-
- self.stackview._StackView__planeSelection.setPerspective(1)
- self.assertEqual(self.stackview._perspective, 1,
- "Plane selection combobox not updating perspective")
-
- self.stackview.setStack(numpy.arange(6).reshape((1, 2, 3)))
- self.assertEqual(self.stackview._perspective, 1,
- "Perspective not preserved when calling setStack "
- "without specifying the perspective parameter.")
-
- self.stackview.setStack(numpy.arange(24).reshape((2, 3, 4)), perspective=2)
- self.assertEqual(self.stackview._perspective, 2,
- "Perspective not set in setStack(..., perspective=2).")
-
- def testDefaultTitle(self):
- """Test that the plot title contains the proper Z information"""
- self.stackview.setStack(numpy.arange(24).reshape((4, 3, 2)),
- calibrations=[(0, 1), (-10, 10), (3.14, 3.14)])
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Image z=0")
- self.stackview.setFrameNumber(2)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Image z=2")
-
- self.stackview._StackView__planeSelection.setPerspective(1)
- self.stackview.setFrameNumber(0)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Image z=-10")
- self.stackview.setFrameNumber(2)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Image z=10")
-
- self.stackview._StackView__planeSelection.setPerspective(2)
- self.stackview.setFrameNumber(0)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Image z=3.14")
- self.stackview.setFrameNumber(1)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Image z=6.28")
-
- def testCustomTitle(self):
- """Test setting the plot title with a user defined callback"""
- self.stackview.setStack(numpy.arange(24).reshape((4, 3, 2)),
- calibrations=[(0, 1), (-10, 10), (3.14, 3.14)])
-
- def title_callback(frame_idx):
- return "Cubed index title %d" % (frame_idx**3)
-
- self.stackview.setTitleCallback(title_callback)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Cubed index title 0")
- self.stackview.setFrameNumber(2)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Cubed index title 8")
-
- # perspective should not matter, only frame index
- self.stackview._StackView__planeSelection.setPerspective(1)
- self.stackview.setFrameNumber(0)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Cubed index title 0")
- self.stackview.setFrameNumber(2)
- self.assertEqual(self.stackview._plot.getGraphTitle(),
- "Cubed index title 8")
-
- with self.assertRaises(TypeError):
- # setTitleCallback should not accept non-callable objects like strings
- self.stackview.setTitleCallback(
- "Là, vous faites sirop de vingt-et-un et vous dites : "
- "beau sirop, mi-sirop, siroté, gagne-sirop, sirop-grelot,"
- " passe-montagne, sirop au bon goût.")
-
- def testStackFrameNumber(self):
- self.stackview.setStack(self.mystack)
- self.assertEqual(self.stackview.getFrameNumber(), 0)
-
- listener = SignalListener()
- self.stackview.sigFrameChanged.connect(listener)
-
- self.stackview.setFrameNumber(1)
- self.assertEqual(self.stackview.getFrameNumber(), 1)
- self.assertEqual(listener.arguments(), [(1,)])
-
-
-class TestStackViewMainWindow(TestCaseQt):
- """Base class for tests of StackView."""
-
- def setUp(self):
- super(TestStackViewMainWindow, self).setUp()
- self.stackview = StackViewMainWindow()
- self.stackview.show()
- self.qWaitForWindowExposed(self.stackview)
- self.mystack = numpy.fromfunction(
- lambda i, j, k: numpy.sin(i/15.) + numpy.cos(j/4.) + 2 * numpy.sin(k/6.),
- (10, 20, 30)
- )
-
- def tearDown(self):
- self.stackview.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.stackview.close()
- del self.stackview
- super(TestStackViewMainWindow, self).tearDown()
-
- def testSetStack(self):
- self.stackview.setStack(self.mystack)
- self.stackview.setColormap("viridis", autoscale=True)
- my_trans_stack, params = self.stackview.getStack()
- self.assertEqual(my_trans_stack.shape, self.mystack.shape)
- self.assertTrue(numpy.array_equal(self.mystack,
- my_trans_stack))
- self.assertEqual(params["colormap"]["name"],
- "viridis")
-
- def testSetStackPerspective(self):
- self.stackview.setStack(self.mystack, perspective=1)
- my_trans_stack, params = self.stackview.getCurrentView()
- # get stack returns the transposed data, depending on the perspective
- self.assertEqual(my_trans_stack.shape,
- (self.mystack.shape[1], self.mystack.shape[0], self.mystack.shape[2]))
- self.assertTrue(numpy.array_equal(numpy.transpose(self.mystack, axes=(1, 0, 2)),
- my_trans_stack))
-
-
-def suite():
- test_suite = unittest.TestSuite()
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestStackView))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestStackViewMainWindow))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testStats.py b/silx/gui/plot/test/testStats.py
deleted file mode 100644
index d5046ba..0000000
--- a/silx/gui/plot/test/testStats.py
+++ /dev/null
@@ -1,1058 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2020 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 tests for CurvesROIWidget"""
-
-__authors__ = ["H. Payno"]
-__license__ = "MIT"
-__date__ = "07/03/2018"
-
-
-from silx.gui import qt
-from silx.gui.plot.stats import stats
-from silx.gui.plot import StatsWidget
-from silx.gui.plot.stats import statshandler
-from silx.gui.utils.testutils import TestCaseQt, SignalListener
-from silx.gui.plot import Plot1D, Plot2D
-from silx.gui.plot3d.SceneWidget import SceneWidget
-from silx.gui.plot.items.roi import RectangleROI, PolygonROI
-from silx.gui.plot.tools.roi import RegionOfInterestManager
-from silx.gui.plot.stats.stats import Stats
-from silx.gui.plot.CurvesROIWidget import ROI
-from silx.utils.testutils import ParametricTestCase
-import unittest
-import logging
-import numpy
-
-_logger = logging.getLogger(__name__)
-
-
-class TestStatsBase(object):
- """Base class for stats TestCase"""
- def setUp(self):
- self.createCurveContext()
- self.createImageContext()
- self.createScatterContext()
-
- def tearDown(self):
- self.plot1d.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot1d.close()
- del self.plot1d
- self.plot2d.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot2d.close()
- del self.plot2d
- self.scatterPlot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.scatterPlot.close()
- del self.scatterPlot
-
- def createCurveContext(self):
- self.plot1d = Plot1D()
- x = range(20)
- y = range(20)
- self.plot1d.addCurve(x, y, legend='curve0')
-
- self.curveContext = stats._CurveContext(
- item=self.plot1d.getCurve('curve0'),
- plot=self.plot1d,
- onlimits=False,
- roi=None)
-
- def createScatterContext(self):
- self.scatterPlot = Plot2D()
- lgd = 'scatter plot'
- self.xScatterData = numpy.array([0, 2, 3, 20, 50, 60, 36])
- self.yScatterData = numpy.array([2, 3, 4, 26, 69, 6, 18])
- self.valuesScatterData = numpy.array([5, 6, 7, 10, 90, 20, 5])
- self.scatterPlot.addScatter(self.xScatterData, self.yScatterData,
- self.valuesScatterData, legend=lgd)
- self.scatterContext = stats._ScatterContext(
- item=self.scatterPlot.getScatter(lgd),
- plot=self.scatterPlot,
- onlimits=False,
- roi=None
- )
-
- def createImageContext(self):
- self.plot2d = Plot2D()
- self._imgLgd = 'test image'
- self.imageData = numpy.arange(32*128).reshape(32, 128)
- self.plot2d.addImage(data=self.imageData,
- legend=self._imgLgd, replace=False)
- self.imageContext = stats._ImageContext(
- item=self.plot2d.getImage(self._imgLgd),
- plot=self.plot2d,
- onlimits=False,
- roi=None
- )
-
- def getBasicStats(self):
- return {
- 'min': stats.StatMin(),
- 'minCoords': stats.StatCoordMin(),
- 'max': stats.StatMax(),
- 'maxCoords': stats.StatCoordMax(),
- 'std': stats.Stat(name='std', fct=numpy.std),
- 'mean': stats.Stat(name='mean', fct=numpy.mean),
- 'com': stats.StatCOM()
- }
-
-
-class TestStats(TestStatsBase, TestCaseQt):
- """
- Test :class:`BaseClass` class and inheriting classes
- """
- def setUp(self):
- TestCaseQt.setUp(self)
- TestStatsBase.setUp(self)
-
- def tearDown(self):
- TestStatsBase.tearDown(self)
- TestCaseQt.tearDown(self)
-
- def testBasicStatsCurve(self):
- """Test result for simple stats on a curve"""
- _stats = self.getBasicStats()
- xData = yData = numpy.array(range(20))
- self.assertEqual(_stats['min'].calculate(self.curveContext), 0)
- self.assertEqual(_stats['max'].calculate(self.curveContext), 19)
- self.assertEqual(_stats['minCoords'].calculate(self.curveContext), (0,))
- self.assertEqual(_stats['maxCoords'].calculate(self.curveContext), (19,))
- self.assertEqual(_stats['std'].calculate(self.curveContext), numpy.std(yData))
- self.assertEqual(_stats['mean'].calculate(self.curveContext), numpy.mean(yData))
- com = numpy.sum(xData * yData) / numpy.sum(yData)
- self.assertEqual(_stats['com'].calculate(self.curveContext), com)
-
- def testBasicStatsImage(self):
- """Test result for simple stats on an image"""
- _stats = self.getBasicStats()
- self.assertEqual(_stats['min'].calculate(self.imageContext), 0)
- self.assertEqual(_stats['max'].calculate(self.imageContext), 128 * 32 - 1)
- self.assertEqual(_stats['minCoords'].calculate(self.imageContext), (0, 0))
- self.assertEqual(_stats['maxCoords'].calculate(self.imageContext), (127, 31))
- self.assertEqual(_stats['std'].calculate(self.imageContext), numpy.std(self.imageData))
- self.assertEqual(_stats['mean'].calculate(self.imageContext), numpy.mean(self.imageData))
-
- yData = numpy.sum(self.imageData.astype(numpy.float64), axis=1)
- xData = numpy.sum(self.imageData.astype(numpy.float64), axis=0)
- dataXRange = range(self.imageData.shape[1])
- dataYRange = range(self.imageData.shape[0])
-
- ycom = numpy.sum(yData*dataYRange) / numpy.sum(yData)
- xcom = numpy.sum(xData*dataXRange) / numpy.sum(xData)
-
- self.assertEqual(_stats['com'].calculate(self.imageContext), (xcom, ycom))
-
- def testStatsImageAdv(self):
- """Test that scale and origin are taking into account for images"""
-
- image2Data = numpy.arange(32 * 128).reshape(32, 128)
- self.plot2d.addImage(data=image2Data, legend=self._imgLgd,
- replace=True, origin=(100, 10), scale=(2, 0.5))
- image2Context = stats._ImageContext(
- item=self.plot2d.getImage(self._imgLgd),
- plot=self.plot2d,
- onlimits=False,
- roi=None,
- )
- _stats = self.getBasicStats()
- self.assertEqual(_stats['min'].calculate(image2Context), 0)
- self.assertEqual(
- _stats['max'].calculate(image2Context), 128 * 32 - 1)
- self.assertEqual(
- _stats['minCoords'].calculate(image2Context), (100, 10))
- self.assertEqual(
- _stats['maxCoords'].calculate(image2Context), (127*2. + 100,
- 31 * 0.5 + 10))
- self.assertEqual(_stats['std'].calculate(image2Context),
- numpy.std(self.imageData))
- self.assertEqual(_stats['mean'].calculate(image2Context),
- numpy.mean(self.imageData))
-
- yData = numpy.sum(self.imageData, axis=1)
- xData = numpy.sum(self.imageData, axis=0)
- dataXRange = numpy.arange(self.imageData.shape[1], dtype=numpy.float64)
- dataYRange = numpy.arange(self.imageData.shape[0], dtype=numpy.float64)
-
- ycom = numpy.sum(yData * dataYRange) / numpy.sum(yData)
- ycom = (ycom * 0.5) + 10
- xcom = numpy.sum(xData * dataXRange) / numpy.sum(xData)
- xcom = (xcom * 2.) + 100
- self.assertTrue(numpy.allclose(
- _stats['com'].calculate(image2Context), (xcom, ycom)))
-
- def testBasicStatsScatter(self):
- """Test result for simple stats on a scatter"""
- _stats = self.getBasicStats()
- self.assertEqual(_stats['min'].calculate(self.scatterContext), 5)
- self.assertEqual(_stats['max'].calculate(self.scatterContext), 90)
- self.assertEqual(_stats['minCoords'].calculate(self.scatterContext), (0, 2))
- self.assertEqual(_stats['maxCoords'].calculate(self.scatterContext), (50, 69))
- self.assertEqual(_stats['std'].calculate(self.scatterContext), numpy.std(self.valuesScatterData))
- self.assertEqual(_stats['mean'].calculate(self.scatterContext), numpy.mean(self.valuesScatterData))
-
- data = self.valuesScatterData.astype(numpy.float64)
- comx = numpy.sum(self.xScatterData * data) / numpy.sum(data)
- comy = numpy.sum(self.yScatterData * data) / numpy.sum(data)
- self.assertEqual(_stats['com'].calculate(self.scatterContext),
- (comx, comy))
-
- def testKindNotManagedByStat(self):
- """Make sure an exception is raised if we try to execute calculate
- of the base class"""
- b = stats.StatBase(name='toto', compatibleKinds='curve')
- with self.assertRaises(NotImplementedError):
- b.calculate(self.imageContext)
-
- def testKindNotManagedByContext(self):
- """
- Make sure an error is raised if we try to calculate a statistic with
- a context not managed
- """
- myStat = stats.Stat(name='toto', fct=numpy.std, kinds=('curve'))
- myStat.calculate(self.curveContext)
- with self.assertRaises(ValueError):
- myStat.calculate(self.scatterContext)
- with self.assertRaises(ValueError):
- myStat.calculate(self.imageContext)
-
- def testOnLimits(self):
- stat = stats.StatMin()
-
- self.plot1d.getXAxis().setLimitsConstraints(minPos=2, maxPos=5)
- curveContextOnLimits = stats._CurveContext(
- item=self.plot1d.getCurve('curve0'),
- plot=self.plot1d,
- onlimits=True,
- roi=None)
- self.assertEqual(stat.calculate(curveContextOnLimits), 2)
-
- self.plot2d.getXAxis().setLimitsConstraints(minPos=32)
- imageContextOnLimits = stats._ImageContext(
- item=self.plot2d.getImage('test image'),
- plot=self.plot2d,
- onlimits=True,
- roi=None)
- self.assertEqual(stat.calculate(imageContextOnLimits), 32)
-
- self.scatterPlot.getXAxis().setLimitsConstraints(minPos=40)
- scatterContextOnLimits = stats._ScatterContext(
- item=self.scatterPlot.getScatter('scatter plot'),
- plot=self.scatterPlot,
- onlimits=True,
- roi=None)
- self.assertEqual(stat.calculate(scatterContextOnLimits), 20)
-
-
-class TestStatsFormatter(TestCaseQt):
- """Simple test to check usage of the :class:`StatsFormatter`"""
- def setUp(self):
- TestCaseQt.setUp(self)
- self.plot1d = Plot1D()
- x = range(20)
- y = range(20)
- self.plot1d.addCurve(x, y, legend='curve0')
-
- self.curveContext = stats._CurveContext(
- item=self.plot1d.getCurve('curve0'),
- plot=self.plot1d,
- onlimits=False,
- roi=None)
-
- self.stat = stats.StatMin()
-
- def tearDown(self):
- self.plot1d.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot1d.close()
- del self.plot1d
- TestCaseQt.tearDown(self)
-
- def testEmptyFormatter(self):
- """Make sure a formatter with no formatter definition will return a
- simple cast to str"""
- emptyFormatter = statshandler.StatFormatter()
- self.assertEqual(
- emptyFormatter.format(self.stat.calculate(self.curveContext)), '0.000')
-
- def testSettedFormatter(self):
- """Make sure a formatter with no formatter definition will return a
- simple cast to str"""
- formatter= statshandler.StatFormatter(formatter='{0:.3f}')
- self.assertEqual(
- formatter.format(self.stat.calculate(self.curveContext)), '0.000')
-
-
-class TestStatsHandler(TestCaseQt):
- """Make sure the StatHandler is correctly making the link between
- :class:`StatBase` and :class:`StatFormatter` and checking the API is valid
- """
- def setUp(self):
- TestCaseQt.setUp(self)
- self.plot1d = Plot1D()
- x = range(20)
- y = range(20)
- self.plot1d.addCurve(x, y, legend='curve0')
- self.curveItem = self.plot1d.getCurve('curve0')
-
- self.stat = stats.StatMin()
-
- def tearDown(self):
- Stats._getContext.cache_clear()
- self.plot1d.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot1d.close()
- self.plot1d = None
- TestCaseQt.tearDown(self)
-
- def testConstructor(self):
- """Make sure the constructor can deal will all possible arguments:
-
- * tuple of :class:`StatBase` derivated classes
- * tuple of tuples (:class:`StatBase`, :class:`StatFormatter`)
- * tuple of tuples (str, pointer to function, kind)
- """
- handler0 = statshandler.StatsHandler(
- (stats.StatMin(), stats.StatMax())
- )
-
- res = handler0.calculate(item=self.curveItem, plot=self.plot1d,
- onlimits=False)
- self.assertTrue('min' in res)
- self.assertEqual(res['min'], '0')
- self.assertTrue('max' in res)
- self.assertEqual(res['max'], '19')
-
- handler1 = statshandler.StatsHandler(
- (
- (stats.StatMin(), statshandler.StatFormatter(formatter=None)),
- (stats.StatMax(), statshandler.StatFormatter())
- )
- )
-
- res = handler1.calculate(item=self.curveItem, plot=self.plot1d,
- onlimits=False)
- self.assertTrue('min' in res)
- self.assertEqual(res['min'], '0')
- self.assertTrue('max' in res)
- self.assertEqual(res['max'], '19.000')
-
- handler2 = statshandler.StatsHandler(
- (
- (stats.StatMin(), None),
- (stats.StatMax(), statshandler.StatFormatter())
- ))
-
- res = handler2.calculate(item=self.curveItem, plot=self.plot1d,
- onlimits=False)
- self.assertTrue('min' in res)
- self.assertEqual(res['min'], '0')
- self.assertTrue('max' in res)
- self.assertEqual(res['max'], '19.000')
-
- handler3 = statshandler.StatsHandler((
- (('amin', numpy.argmin), statshandler.StatFormatter()),
- ('amax', numpy.argmax)
- ))
-
- res = handler3.calculate(item=self.curveItem, plot=self.plot1d,
- onlimits=False)
- self.assertTrue('amin' in res)
- self.assertEqual(res['amin'], '0.000')
- self.assertTrue('amax' in res)
- self.assertEqual(res['amax'], '19')
-
- with self.assertRaises(ValueError):
- statshandler.StatsHandler(('name'))
-
-
-class TestStatsWidgetWithCurves(TestCaseQt, ParametricTestCase):
- """Basic test for StatsWidget with curves"""
- def setUp(self):
- TestCaseQt.setUp(self)
- self.plot = Plot1D()
- self.plot.show()
- x = range(20)
- y = range(20)
- self.plot.addCurve(x, y, legend='curve0')
- y = range(12, 32)
- self.plot.addCurve(x, y, legend='curve1')
- y = range(-2, 18)
- self.plot.addCurve(x, y, legend='curve2')
- self.widget = StatsWidget.StatsWidget(plot=self.plot)
- self.statsTable = self.widget._statsTable
-
- mystats = statshandler.StatsHandler((
- stats.StatMin(),
- (stats.StatCoordMin(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
- stats.StatMax(),
- (stats.StatCoordMax(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
- stats.StatDelta(),
- ('std', numpy.std),
- ('mean', numpy.mean),
- stats.StatCOM()
- ))
-
- self.statsTable.setStats(mystats)
-
- def tearDown(self):
- Stats._getContext.cache_clear()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- self.statsTable = None
- self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.widget.close()
- self.widget = None
- self.plot = None
- TestCaseQt.tearDown(self)
-
- def testDisplayActiveItemsSyncOptions(self):
- """
- Test that the several option of the sync options are well
- synchronized between the different object"""
- widget = StatsWidget.StatsWidget(plot=self.plot)
- table = StatsWidget.StatsTable(plot=self.plot)
-
- def check_display_only_active_item(only_active):
- # check internal value
- self.assertIs(widget._statsTable._displayOnlyActItem, only_active)
- # self.assertTrue(table._displayOnlyActItem is only_active)
- # check gui display
- self.assertEqual(widget._options.isActiveItemMode(), only_active)
-
- for displayOnlyActiveItems in (True, False):
- with self.subTest(displayOnlyActiveItems=displayOnlyActiveItems):
- widget.setDisplayOnlyActiveItem(displayOnlyActiveItems)
- # table.setDisplayOnlyActiveItem(displayOnlyActiveItems)
- check_display_only_active_item(displayOnlyActiveItems)
-
- check_display_only_active_item(only_active=False)
- widget.setAttribute(qt.Qt.WA_DeleteOnClose)
- table.setAttribute(qt.Qt.WA_DeleteOnClose)
- widget.close()
- table.close()
-
- def testInit(self):
- """Make sure all the curves are registred on initialization"""
- self.assertEqual(self.statsTable.rowCount(), 3)
-
- def testRemoveCurve(self):
- """Make sure the Curves stats take into account the curve removal from
- plot"""
- self.plot.removeCurve('curve2')
- self.assertEqual(self.statsTable.rowCount(), 2)
- for iRow in range(2):
- self.assertTrue(self.statsTable.item(iRow, 0).text() in ('curve0', 'curve1'))
-
- self.plot.removeCurve('curve0')
- self.assertEqual(self.statsTable.rowCount(), 1)
- self.plot.removeCurve('curve1')
- self.assertEqual(self.statsTable.rowCount(), 0)
-
- def testAddCurve(self):
- """Make sure the Curves stats take into account the add curve action"""
- self.plot.addCurve(legend='curve3', x=range(10), y=range(10))
- self.assertEqual(self.statsTable.rowCount(), 4)
-
- def testUpdateCurveFromAddCurve(self):
- """Make sure the stats of the cuve will be removed after updating a
- curve"""
- self.plot.addCurve(legend='curve0', x=range(10), y=range(10))
- self.qapp.processEvents()
- self.assertEqual(self.statsTable.rowCount(), 3)
- curve = self.plot._getItem(kind='curve', legend='curve0')
- tableItems = self.statsTable._itemToTableItems(curve)
- self.assertEqual(tableItems['max'].text(), '9')
-
- def testUpdateCurveFromCurveObj(self):
- self.plot.getCurve('curve0').setData(x=range(4), y=range(4))
- self.qapp.processEvents()
- self.assertEqual(self.statsTable.rowCount(), 3)
- curve = self.plot._getItem(kind='curve', legend='curve0')
- tableItems = self.statsTable._itemToTableItems(curve)
- self.assertEqual(tableItems['max'].text(), '3')
-
- def testSetAnotherPlot(self):
- plot2 = Plot1D()
- plot2.addCurve(x=range(26), y=range(26), legend='new curve')
- self.statsTable.setPlot(plot2)
- self.assertEqual(self.statsTable.rowCount(), 1)
- self.qapp.processEvents()
- plot2.setAttribute(qt.Qt.WA_DeleteOnClose)
- plot2.close()
- plot2 = None
-
- def testUpdateMode(self):
- """Make sure the update modes are well take into account"""
- self.plot.setActiveCurve('curve0')
- for display_only_active in (True, False):
- with self.subTest(display_only_active=display_only_active):
- self.widget.setDisplayOnlyActiveItem(display_only_active)
- self.plot.getCurve('curve0').setData(x=range(4), y=range(4))
- self.widget.setUpdateMode(StatsWidget.UpdateMode.AUTO)
- update_stats_action = self.widget._options.getUpdateStatsAction()
- # test from api
- self.assertEqual(self.widget.getUpdateMode(), StatsWidget.UpdateMode.AUTO)
- self.widget.show()
- # check stats change in auto mode
- self.plot.getCurve('curve0').setData(x=range(4), y=range(-1, 3))
- self.qapp.processEvents()
- tableItems = self.statsTable._itemToTableItems(self.plot.getCurve('curve0'))
- curve0_min = tableItems['min'].text()
- self.assertTrue(float(curve0_min) == -1.)
-
- self.plot.getCurve('curve0').setData(x=range(4), y=range(1, 5))
- self.qapp.processEvents()
- tableItems = self.statsTable._itemToTableItems(self.plot.getCurve('curve0'))
- curve0_min = tableItems['min'].text()
- self.assertTrue(float(curve0_min) == 1.)
-
- # check stats change in manual mode only if requested
- self.widget.setUpdateMode(StatsWidget.UpdateMode.MANUAL)
- self.assertEqual(self.widget.getUpdateMode(), StatsWidget.UpdateMode.MANUAL)
-
- self.plot.getCurve('curve0').setData(x=range(4), y=range(2, 6))
- self.qapp.processEvents()
- tableItems = self.statsTable._itemToTableItems(self.plot.getCurve('curve0'))
- curve0_min = tableItems['min'].text()
- self.assertTrue(float(curve0_min) == 1.)
-
- update_stats_action.trigger()
- tableItems = self.statsTable._itemToTableItems(self.plot.getCurve('curve0'))
- curve0_min = tableItems['min'].text()
- self.assertTrue(float(curve0_min) == 2.)
-
- def testItemHidden(self):
- """Test if an item is hide, then the associated stats item is also
- hide"""
- curve0 = self.plot.getCurve('curve0')
- curve1 = self.plot.getCurve('curve1')
- curve2 = self.plot.getCurve('curve2')
-
- self.plot.show()
- self.widget.show()
- self.qWaitForWindowExposed(self.widget)
- self.assertFalse(self.statsTable.isRowHidden(0))
- self.assertFalse(self.statsTable.isRowHidden(1))
- self.assertFalse(self.statsTable.isRowHidden(2))
-
- curve0.setVisible(False)
- self.qapp.processEvents()
- self.assertTrue(self.statsTable.isRowHidden(0))
- curve0.setVisible(True)
- self.qapp.processEvents()
- self.assertFalse(self.statsTable.isRowHidden(0))
- curve1.setVisible(False)
- self.qapp.processEvents()
- self.assertTrue(self.statsTable.isRowHidden(1))
- tableItems = self.statsTable._itemToTableItems(curve2)
- curve2_min = tableItems['min'].text()
- self.assertTrue(float(curve2_min) == -2.)
-
- curve0.setVisible(False)
- curve1.setVisible(False)
- curve2.setVisible(False)
- self.qapp.processEvents()
- self.assertTrue(self.statsTable.isRowHidden(0))
- self.assertTrue(self.statsTable.isRowHidden(1))
- self.assertTrue(self.statsTable.isRowHidden(2))
-
-
-class TestStatsWidgetWithImages(TestCaseQt):
- """Basic test for StatsWidget with images"""
-
- IMAGE_LEGEND = 'test image'
-
- def setUp(self):
- TestCaseQt.setUp(self)
- self.plot = Plot2D()
-
- self.plot.addImage(data=numpy.arange(128*128).reshape(128, 128),
- legend=self.IMAGE_LEGEND, replace=False)
-
- self.widget = StatsWidget.StatsTable(plot=self.plot)
-
- mystats = statshandler.StatsHandler((
- (stats.StatMin(), statshandler.StatFormatter()),
- (stats.StatCoordMin(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
- (stats.StatMax(), statshandler.StatFormatter()),
- (stats.StatCoordMax(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
- (stats.StatDelta(), statshandler.StatFormatter()),
- ('std', numpy.std),
- ('mean', numpy.mean),
- (stats.StatCOM(), statshandler.StatFormatter(None))
- ))
-
- self.widget.setStats(mystats)
-
- def tearDown(self):
- Stats._getContext.cache_clear()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.widget.close()
- self.widget = None
- self.plot = None
- TestCaseQt.tearDown(self)
-
- def test(self):
- image = self.plot._getItem(
- kind='image', legend=self.IMAGE_LEGEND)
- tableItems = self.widget._itemToTableItems(image)
-
- maxText = '{0:.3f}'.format((128 * 128) - 1)
- self.assertEqual(tableItems['legend'].text(), self.IMAGE_LEGEND)
- self.assertEqual(tableItems['min'].text(), '0.000')
- self.assertEqual(tableItems['max'].text(), maxText)
- self.assertEqual(tableItems['delta'].text(), maxText)
- self.assertEqual(tableItems['coords min'].text(), '0.0, 0.0')
- self.assertEqual(tableItems['coords max'].text(), '127.0, 127.0')
-
- def testItemHidden(self):
- """Test if an item is hide, then the associated stats item is also
- hide"""
- self.widget.show()
- self.plot.show()
- self.qWaitForWindowExposed(self.widget)
- self.assertFalse(self.widget.isRowHidden(0))
- self.plot.getImage(self.IMAGE_LEGEND).setVisible(False)
- self.qapp.processEvents()
- self.assertTrue(self.widget.isRowHidden(0))
-
-
-class TestStatsWidgetWithScatters(TestCaseQt):
-
- SCATTER_LEGEND = 'scatter plot'
-
- def setUp(self):
- TestCaseQt.setUp(self)
- self.scatterPlot = Plot2D()
- self.scatterPlot.addScatter([0, 1, 2, 20, 50, 60],
- [2, 3, 4, 26, 69, 6],
- [5, 6, 7, 10, 90, 20],
- legend=self.SCATTER_LEGEND)
- self.widget = StatsWidget.StatsTable(plot=self.scatterPlot)
-
- mystats = statshandler.StatsHandler((
- stats.StatMin(),
- (stats.StatCoordMin(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
- stats.StatMax(),
- (stats.StatCoordMax(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
- stats.StatDelta(),
- ('std', numpy.std),
- ('mean', numpy.mean),
- stats.StatCOM()
- ))
-
- self.widget.setStats(mystats)
-
- def tearDown(self):
- Stats._getContext.cache_clear()
- self.scatterPlot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.scatterPlot.close()
- self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.widget.close()
- self.widget = None
- self.scatterPlot = None
- TestCaseQt.tearDown(self)
-
- def testStats(self):
- scatter = self.scatterPlot._getItem(
- kind='scatter', legend=self.SCATTER_LEGEND)
- tableItems = self.widget._itemToTableItems(scatter)
- self.assertEqual(tableItems['legend'].text(), self.SCATTER_LEGEND)
- self.assertEqual(tableItems['min'].text(), '5')
- self.assertEqual(tableItems['coords min'].text(), '0, 2')
- self.assertEqual(tableItems['max'].text(), '90')
- self.assertEqual(tableItems['coords max'].text(), '50, 69')
- self.assertEqual(tableItems['delta'].text(), '85')
-
-
-class TestEmptyStatsWidget(TestCaseQt):
- def test(self):
- widget = StatsWidget.StatsWidget()
- widget.show()
- self.qWaitForWindowExposed(widget)
-
-
-# skip unit test for pyqt4 because there is some unrealised widget without
-# apparent reason
-@unittest.skipIf(qt.qVersion().split('.')[0] == '4', reason='PyQt4 not tested')
-class TestLineWidget(TestCaseQt):
- """Some test for the StatsLineWidget."""
- def setUp(self):
- TestCaseQt.setUp(self)
-
- mystats = statshandler.StatsHandler((
- (stats.StatMin(), statshandler.StatFormatter()),
- ))
-
- self.plot = Plot1D()
- self.plot.show()
- self.x = range(20)
- self.y0 = range(20)
- self.curve0 = self.plot.addCurve(self.x, self.y0, legend='curve0')
- self.y1 = range(12, 32)
- self.plot.addCurve(self.x, self.y1, legend='curve1')
- self.y2 = range(-2, 18)
- self.plot.addCurve(self.x, self.y2, legend='curve2')
- self.widget = StatsWidget.BasicGridStatsWidget(plot=self.plot,
- kind='curve',
- stats=mystats)
-
- def tearDown(self):
- Stats._getContext.cache_clear()
- self.qapp.processEvents()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- self.widget.setPlot(None)
- self.widget._lineStatsWidget._statQlineEdit.clear()
- self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.widget.close()
- self.widget = None
- self.plot = None
- TestCaseQt.tearDown(self)
-
- def testProcessing(self):
- self.widget._lineStatsWidget.setStatsOnVisibleData(False)
- self.qapp.processEvents()
- self.plot.setActiveCurve(legend='curve0')
- self.assertTrue(self.widget._lineStatsWidget._statQlineEdit['min'].text() == '0.000')
- self.plot.setActiveCurve(legend='curve1')
- self.assertTrue(self.widget._lineStatsWidget._statQlineEdit['min'].text() == '12.000')
- self.plot.getXAxis().setLimitsConstraints(minPos=2, maxPos=5)
- self.widget.setStatsOnVisibleData(True)
- self.qapp.processEvents()
- self.assertTrue(self.widget._lineStatsWidget._statQlineEdit['min'].text() == '14.000')
- self.plot.setActiveCurve(None)
- self.assertIsNone(self.plot.getActiveCurve())
- self.widget.setStatsOnVisibleData(False)
- self.qapp.processEvents()
- self.assertFalse(self.widget._lineStatsWidget._statQlineEdit['min'].text() == '14.000')
- self.widget.setKind('image')
- self.plot.addImage(numpy.arange(100*100).reshape(100, 100) + 0.312)
- self.qapp.processEvents()
- self.assertTrue(self.widget._lineStatsWidget._statQlineEdit['min'].text() == '0.312')
-
- def testUpdateMode(self):
- """Make sure the update modes are well take into account"""
- self.plot.setActiveCurve(self.curve0)
- _autoRB = self.widget._options._autoRB
- _manualRB = self.widget._options._manualRB
- # test from api
- self.widget.setUpdateMode(StatsWidget.UpdateMode.AUTO)
- self.assertTrue(_autoRB.isChecked())
- self.assertFalse(_manualRB.isChecked())
-
- # check stats change in auto mode
- curve0_min = self.widget._lineStatsWidget._statQlineEdit['min'].text()
- new_y = numpy.array(self.y0) - 2.56
- self.plot.addCurve(x=self.x, y=new_y, legend=self.curve0)
- curve0_min2 = self.widget._lineStatsWidget._statQlineEdit['min'].text()
- self.assertTrue(curve0_min != curve0_min2)
-
- # check stats change in manual mode only if requested
- self.widget.setUpdateMode(StatsWidget.UpdateMode.MANUAL)
- self.assertFalse(_autoRB.isChecked())
- self.assertTrue(_manualRB.isChecked())
-
- new_y = numpy.array(self.y0) - 1.2
- self.plot.addCurve(x=self.x, y=new_y, legend=self.curve0)
- curve0_min3 = self.widget._lineStatsWidget._statQlineEdit['min'].text()
- self.assertTrue(curve0_min3 == curve0_min2)
- self.widget._options._updateRequested()
- curve0_min3 = self.widget._lineStatsWidget._statQlineEdit['min'].text()
- self.assertTrue(curve0_min3 != curve0_min2)
-
- # test from gui
- self.widget.showRadioButtons(True)
- self.widget._options._autoRB.toggle()
- self.assertTrue(_autoRB.isChecked())
- self.assertFalse(_manualRB.isChecked())
-
- self.widget._options._manualRB.toggle()
- self.assertFalse(_autoRB.isChecked())
- self.assertTrue(_manualRB.isChecked())
-
-
-class TestUpdateModeWidget(TestCaseQt):
- """Test UpdateModeWidget"""
- def setUp(self):
- TestCaseQt.setUp(self)
- self.widget = StatsWidget.UpdateModeWidget(parent=None)
-
- def tearDown(self):
- self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.widget.close()
- self.widget = None
- TestCaseQt.tearDown(self)
-
- def testSignals(self):
- """Test the signal emission of the widget"""
- self.widget.setUpdateMode(StatsWidget.UpdateMode.AUTO)
- modeChangedListener = SignalListener()
- manualUpdateListener = SignalListener()
- self.widget.sigUpdateModeChanged.connect(modeChangedListener)
- self.widget.sigUpdateRequested.connect(manualUpdateListener)
- self.widget.setUpdateMode(StatsWidget.UpdateMode.AUTO)
- self.assertEqual(self.widget.getUpdateMode(), StatsWidget.UpdateMode.AUTO)
- self.assertEqual(modeChangedListener.callCount(), 0)
- self.qapp.processEvents()
-
- self.widget.setUpdateMode(StatsWidget.UpdateMode.MANUAL)
- self.assertEqual(self.widget.getUpdateMode(), StatsWidget.UpdateMode.MANUAL)
- self.qapp.processEvents()
- self.assertEqual(modeChangedListener.callCount(), 1)
- self.assertEqual(manualUpdateListener.callCount(), 0)
- self.widget._updatePB.click()
- self.widget._updatePB.click()
- self.assertEqual(manualUpdateListener.callCount(), 2)
-
- self.widget._autoRB.setChecked(True)
- self.assertEqual(modeChangedListener.callCount(), 2)
- self.widget._updatePB.click()
- self.assertEqual(manualUpdateListener.callCount(), 2)
-
-
-class TestStatsROI(TestStatsBase, TestCaseQt):
- """
- Test stats based on ROI
- """
- def setUp(self):
- TestCaseQt.setUp(self)
- self.createRois()
- TestStatsBase.setUp(self)
- self.createHistogramContext()
-
- self.roiManager = RegionOfInterestManager(self.plot2d)
- self.roiManager.addRoi(self._2Droi_rect)
- self.roiManager.addRoi(self._2Droi_poly)
-
- def tearDown(self):
- self.roiManager.clear()
- self.roiManager = None
- self._1Droi = None
- self._2Droi_rect = None
- self._2Droi_poly = None
- self.plotHisto.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plotHisto.close()
- self.plotHisto = None
- TestStatsBase.tearDown(self)
- TestCaseQt.tearDown(self)
-
- def createRois(self):
- self._1Droi = ROI(name='my1DRoi', fromdata=2.0, todata=5.0)
- self._2Droi_rect = RectangleROI()
- self._2Droi_rect.setGeometry(size=(10, 10), origin=(10, 0))
- self._2Droi_poly = PolygonROI()
- points = numpy.array(((0, 20), (0, 0), (10, 0)))
- self._2Droi_poly.setPoints(points=points)
-
- def createCurveContext(self):
- TestStatsBase.createCurveContext(self)
- self.curveContext = stats._CurveContext(
- item=self.plot1d.getCurve('curve0'),
- plot=self.plot1d,
- onlimits=False,
- roi=self._1Droi)
-
- def createHistogramContext(self):
- self.plotHisto = Plot1D()
- x = range(20)
- y = range(20)
- self.plotHisto.addHistogram(x, y, legend='histo0')
-
- self.histoContext = stats._HistogramContext(
- item=self.plotHisto.getHistogram('histo0'),
- plot=self.plotHisto,
- onlimits=False,
- roi=self._1Droi)
-
- def createScatterContext(self):
- TestStatsBase.createScatterContext(self)
- self.scatterContext = stats._ScatterContext(
- item=self.scatterPlot.getScatter('scatter plot'),
- plot=self.scatterPlot,
- onlimits=False,
- roi=self._1Droi
- )
-
- def createImageContext(self):
- TestStatsBase.createImageContext(self)
-
- self.imageContext = stats._ImageContext(
- item=self.plot2d.getImage(self._imgLgd),
- plot=self.plot2d,
- onlimits=False,
- roi=self._2Droi_rect
- )
-
- self.imageContext_2 = stats._ImageContext(
- item=self.plot2d.getImage(self._imgLgd),
- plot=self.plot2d,
- onlimits=False,
- roi=self._2Droi_poly
- )
-
- def testErrors(self):
- # test if onlimits is True and give also a roi
- with self.assertRaises(ValueError):
- stats._CurveContext(item=self.plot1d.getCurve('curve0'),
- plot=self.plot1d,
- onlimits=True,
- roi=self._1Droi)
-
- # test if is a curve context and give an invalid 2D roi
- with self.assertRaises(TypeError):
- stats._CurveContext(item=self.plot1d.getCurve('curve0'),
- plot=self.plot1d,
- onlimits=False,
- roi=self._2Droi_rect)
-
- def testBasicStatsCurve(self):
- """Test result for simple stats on a curve"""
- _stats = self.getBasicStats()
- xData = yData = numpy.array(range(0, 10))
- self.assertEqual(_stats['min'].calculate(self.curveContext), 2)
- self.assertEqual(_stats['max'].calculate(self.curveContext), 5)
- self.assertEqual(_stats['minCoords'].calculate(self.curveContext), (2,))
- self.assertEqual(_stats['maxCoords'].calculate(self.curveContext), (5,))
- self.assertEqual(_stats['std'].calculate(self.curveContext), numpy.std(yData[2:6]))
- self.assertEqual(_stats['mean'].calculate(self.curveContext), numpy.mean(yData[2:6]))
- com = numpy.sum(xData[2:6] * yData[2:6]) / numpy.sum(yData[2:6])
- self.assertEqual(_stats['com'].calculate(self.curveContext), com)
-
- def testBasicStatsImageRectRoi(self):
- """Test result for simple stats on an image"""
- self.assertEqual(self.imageContext.values.compressed().size, 121)
- _stats = self.getBasicStats()
- self.assertEqual(_stats['min'].calculate(self.imageContext), 10)
- self.assertEqual(_stats['max'].calculate(self.imageContext), 1300)
- self.assertEqual(_stats['minCoords'].calculate(self.imageContext), (10, 0))
- self.assertEqual(_stats['maxCoords'].calculate(self.imageContext), (20.0, 10.0))
- self.assertAlmostEqual(_stats['std'].calculate(self.imageContext),
- numpy.std(self.imageData[0:11, 10:21]))
- self.assertAlmostEqual(_stats['mean'].calculate(self.imageContext),
- numpy.mean(self.imageData[0:11, 10:21]))
-
- compressed_values = self.imageContext.values.compressed()
- compressed_values = compressed_values.reshape(11, 11)
- yData = numpy.sum(compressed_values.astype(numpy.float64), axis=1)
- xData = numpy.sum(compressed_values.astype(numpy.float64), axis=0)
-
- dataYRange = range(11)
- dataXRange = range(10, 21)
-
- ycom = numpy.sum(yData*dataYRange) / numpy.sum(yData)
- xcom = numpy.sum(xData*dataXRange) / numpy.sum(xData)
- self.assertEqual(_stats['com'].calculate(self.imageContext), (xcom, ycom))
-
- def testBasicStatsImagePolyRoi(self):
- """Test a simple rectangle ROI"""
- _stats = self.getBasicStats()
- self.assertEqual(_stats['min'].calculate(self.imageContext_2), 0)
- self.assertEqual(_stats['max'].calculate(self.imageContext_2), 2432)
- self.assertEqual(_stats['minCoords'].calculate(self.imageContext_2), (0.0, 0.0))
- # not 0.0, 19.0 because not fully in. Should all pixel have a weight,
- # on to manage them in stats. For now 0 if the center is not in, else 1
- self.assertEqual(_stats['maxCoords'].calculate(self.imageContext_2), (0.0, 19.0))
-
- def testBasicStatsScatter(self):
- self.assertEqual(self.scatterContext.values.compressed().size, 2)
- _stats = self.getBasicStats()
- self.assertEqual(_stats['min'].calculate(self.scatterContext), 6)
- self.assertEqual(_stats['max'].calculate(self.scatterContext), 7)
- self.assertEqual(_stats['minCoords'].calculate(self.scatterContext), (2, 3))
- self.assertEqual(_stats['maxCoords'].calculate(self.scatterContext), (3, 4))
- self.assertEqual(_stats['std'].calculate(self.scatterContext), numpy.std([6, 7]))
- self.assertEqual(_stats['mean'].calculate(self.scatterContext), numpy.mean([6, 7]))
-
- def testBasicHistogram(self):
- _stats = self.getBasicStats()
- xData = yData = numpy.array(range(2, 6))
- self.assertEqual(_stats['min'].calculate(self.histoContext), 2)
- self.assertEqual(_stats['max'].calculate(self.histoContext), 5)
- self.assertEqual(_stats['minCoords'].calculate(self.histoContext), (2,))
- self.assertEqual(_stats['maxCoords'].calculate(self.histoContext), (5,))
- self.assertEqual(_stats['std'].calculate(self.histoContext), numpy.std(yData))
- self.assertEqual(_stats['mean'].calculate(self.histoContext), numpy.mean(yData))
- com = numpy.sum(xData * yData) / numpy.sum(yData)
- self.assertEqual(_stats['com'].calculate(self.histoContext), com)
-
-
-class TestAdvancedROIImageContext(TestCaseQt):
- """Test stats result on an image context with different scale and
- origins"""
-
- def setUp(self):
- TestCaseQt.setUp(self)
- self.data_dims = (100, 100)
- self.data = numpy.random.rand(*self.data_dims)
- self.plot = Plot2D()
-
- def test(self):
- """Test stats result on an image context with different scale and
- origins"""
- roi_origins = [(0, 0), (2, 10), (14, 20)]
- img_origins = [(0, 0), (14, 20), (2, 10)]
- img_scales = [1.0, 0.5, 2.0]
- _stats = {'sum': stats.Stat(name='sum', fct=numpy.sum), }
- for roi_origin in roi_origins:
- for img_origin in img_origins:
- for img_scale in img_scales:
- with self.subTest(roi_origin=roi_origin,
- img_origin=img_origin,
- img_scale=img_scale):
- self.plot.addImage(self.data, legend='img',
- origin=img_origin,
- scale=img_scale)
- roi = RectangleROI()
- roi.setGeometry(origin=roi_origin, size=(20, 20))
- context = stats._ImageContext(
- item=self.plot.getImage('img'),
- plot=self.plot,
- onlimits=False,
- roi=roi)
- x_start = int((roi_origin[0] - img_origin[0]) / img_scale)
- x_end = int(x_start + (20 / img_scale)) + 1
- y_start = int((roi_origin[1] - img_origin[1])/ img_scale)
- y_end = int(y_start + (20 / img_scale)) + 1
- x_start = max(x_start, 0)
- x_end = min(max(x_end, 0), self.data_dims[1])
- y_start = max(y_start, 0)
- y_end = min(max(y_end, 0), self.data_dims[0])
- th_sum = numpy.sum(self.data[y_start:y_end, x_start:x_end])
- self.assertAlmostEqual(_stats['sum'].calculate(context),
- th_sum)
-
-def suite():
- test_suite = unittest.TestSuite()
- for TestClass in (TestStats, TestStatsHandler, TestStatsWidgetWithScatters,
- TestStatsWidgetWithImages, TestStatsWidgetWithCurves,
- TestStatsFormatter, TestEmptyStatsWidget, TestStatsROI,
- TestLineWidget, TestUpdateModeWidget, ):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testUtilsAxis.py b/silx/gui/plot/test/testUtilsAxis.py
deleted file mode 100644
index 64373b8..0000000
--- a/silx/gui/plot/test/testUtilsAxis.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 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 tests for PlotWidget"""
-
-__authors__ = ["V. Valls"]
-__license__ = "MIT"
-__date__ = "20/11/2018"
-
-
-import unittest
-from silx.gui.plot import PlotWidget
-from silx.gui.utils.testutils import TestCaseQt
-from silx.gui.plot.utils.axis import SyncAxes
-
-
-class TestAxisSync(TestCaseQt):
- """Tests AxisSync class"""
-
- def setUp(self):
- TestCaseQt.setUp(self)
- self.plot1 = PlotWidget()
- self.plot2 = PlotWidget()
- self.plot3 = PlotWidget()
-
- def tearDown(self):
- self.plot1 = None
- self.plot2 = None
- self.plot3 = None
- TestCaseQt.tearDown(self)
-
- def testMoveFirstAxis(self):
- """Test synchronization after construction"""
- _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
-
- self.plot1.getXAxis().setLimits(10, 500)
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot2.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
- def testMoveSecondAxis(self):
- """Test synchronization after construction"""
- _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
-
- self.plot2.getXAxis().setLimits(10, 500)
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot2.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
- def testMoveTwoAxes(self):
- """Test synchronization after construction"""
- _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
-
- self.plot1.getXAxis().setLimits(1, 50)
- self.plot2.getXAxis().setLimits(10, 500)
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot2.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
- def testDestruction(self):
- """Test synchronization when sync object is destroyed"""
- sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
- del sync
-
- self.plot1.getXAxis().setLimits(10, 500)
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- self.assertNotEqual(self.plot2.getXAxis().getLimits(), (10, 500))
- self.assertNotEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
- def testAxisDestruction(self):
- """Test synchronization when an axis disappear"""
- _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
-
- # Destroy the plot is possible
- import weakref
- plot = weakref.ref(self.plot2)
- self.plot2 = None
- result = self.qWaitForDestroy(plot)
- if not result:
- # We can't test
- self.skipTest("Object not destroyed")
-
- self.plot1.getXAxis().setLimits(10, 500)
- self.assertEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
- def testStop(self):
- """Test synchronization after calling stop"""
- sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
- sync.stop()
-
- self.plot1.getXAxis().setLimits(10, 500)
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- self.assertNotEqual(self.plot2.getXAxis().getLimits(), (10, 500))
- self.assertNotEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
- def testStopMovingStart(self):
- """Test synchronization after calling stop, moving an axis, then start again"""
- sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
- sync.stop()
- self.plot1.getXAxis().setLimits(10, 500)
- self.plot2.getXAxis().setLimits(1, 50)
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- sync.start()
-
- # The first axis is the reference
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot2.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
- def testDoubleStop(self):
- """Test double stop"""
- sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
- sync.stop()
- self.assertRaises(RuntimeError, sync.stop)
-
- def testDoubleStart(self):
- """Test double stop"""
- sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
- self.assertRaises(RuntimeError, sync.start)
-
- def testScale(self):
- """Test scale change"""
- _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
- self.plot1.getXAxis().setScale(self.plot1.getXAxis().LOGARITHMIC)
- self.assertEqual(self.plot1.getXAxis().getScale(), self.plot1.getXAxis().LOGARITHMIC)
- self.assertEqual(self.plot2.getXAxis().getScale(), self.plot1.getXAxis().LOGARITHMIC)
- self.assertEqual(self.plot3.getXAxis().getScale(), self.plot1.getXAxis().LOGARITHMIC)
-
- def testDirection(self):
- """Test direction change"""
- _sync = SyncAxes([self.plot1.getYAxis(), self.plot2.getYAxis(), self.plot3.getYAxis()])
- self.plot1.getYAxis().setInverted(True)
- self.assertEqual(self.plot1.getYAxis().isInverted(), True)
- self.assertEqual(self.plot2.getYAxis().isInverted(), True)
- self.assertEqual(self.plot3.getYAxis().isInverted(), True)
-
- def testSyncCenter(self):
- """Test direction change"""
- # Not the same scale
- self.plot1.getXAxis().setLimits(0, 200)
- self.plot2.getXAxis().setLimits(0, 20)
- self.plot3.getXAxis().setLimits(0, 2)
- _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()],
- syncLimits=False, syncCenter=True)
-
- self.assertEqual(self.plot1.getXAxis().getLimits(), (0, 200))
- self.assertEqual(self.plot2.getXAxis().getLimits(), (100 - 10, 100 + 10))
- self.assertEqual(self.plot3.getXAxis().getLimits(), (100 - 1, 100 + 1))
-
- def testSyncCenterAndZoom(self):
- """Test direction change"""
- # Not the same scale
- self.plot1.getXAxis().setLimits(0, 200)
- self.plot2.getXAxis().setLimits(0, 20)
- self.plot3.getXAxis().setLimits(0, 2)
- _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()],
- syncLimits=False, syncCenter=True, syncZoom=True)
-
- # Supposing all the plots use the same size
- self.assertEqual(self.plot1.getXAxis().getLimits(), (0, 200))
- self.assertEqual(self.plot2.getXAxis().getLimits(), (0, 200))
- self.assertEqual(self.plot3.getXAxis().getLimits(), (0, 200))
-
- def testAddAxis(self):
- """Test synchronization after construction"""
- sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis()])
- sync.addAxis(self.plot3.getXAxis())
-
- self.plot1.getXAxis().setLimits(10, 500)
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot2.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
- def testRemoveAxis(self):
- """Test synchronization after construction"""
- sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
- sync.removeAxis(self.plot3.getXAxis())
-
- self.plot1.getXAxis().setLimits(10, 500)
- self.assertEqual(self.plot1.getXAxis().getLimits(), (10, 500))
- self.assertEqual(self.plot2.getXAxis().getLimits(), (10, 500))
- self.assertNotEqual(self.plot3.getXAxis().getLimits(), (10, 500))
-
-
-def suite():
- test_suite = unittest.TestSuite()
- loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
- test_suite.addTest(loadTests(TestAxisSync))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/utils.py b/silx/gui/plot/test/utils.py
deleted file mode 100644
index ed1917a..0000000
--- a/silx/gui/plot/test/utils.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# 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.
-#
-# ###########################################################################*/
-"""Basic tests for PlotWidget"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "26/01/2018"
-
-
-import logging
-
-from silx.gui.utils.testutils import TestCaseQt
-
-from silx.gui import qt
-from silx.gui.plot import PlotWidget
-
-
-logger = logging.getLogger(__name__)
-
-
-class PlotWidgetTestCase(TestCaseQt):
- """Base class for tests of PlotWidget, not a TestCase in itself.
-
- plot attribute is the PlotWidget created for the test.
- """
-
- __screenshot_already_taken = False
-
- def __init__(self, methodName='runTest', backend=None):
- TestCaseQt.__init__(self, methodName=methodName)
- self.__backend = backend
-
- def _createPlot(self):
- return PlotWidget(backend=self.__backend)
-
- def setUp(self):
- super(PlotWidgetTestCase, self).setUp()
- self.plot = self._createPlot()
- self.plot.show()
- self.plotAlive = True
- self.qWaitForWindowExposed(self.plot)
- TestCaseQt.mouseClick(self, self.plot, button=qt.Qt.LeftButton, pos=(0, 0))
-
- def __onPlotDestroyed(self):
- self.plotAlive = False
-
- def _waitForPlotClosed(self):
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.destroyed.connect(self.__onPlotDestroyed)
- self.plot.close()
- del self.plot
- for _ in range(100):
- if not self.plotAlive:
- break
- self.qWait(10)
- else:
- logger.error("Plot is still alive")
-
- def tearDown(self):
- if not self._currentTestSucceeded():
- # MPL is the only widget which uses the real system mouse.
- # In case of a the windows is outside of the screen, minimzed,
- # overlapped by a system popup, the MPL widget will not receive the
- # mouse event.
- # Taking a screenshot help debuging this cases in the continuous
- # integration environement.
- if not PlotWidgetTestCase.__screenshot_already_taken:
- PlotWidgetTestCase.__screenshot_already_taken = True
- self.logScreenShot()
- self.qapp.processEvents()
- self._waitForPlotClosed()
- super(PlotWidgetTestCase, self).tearDown()