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__.py80
-rw-r--r--silx/gui/plot/test/testColorBar.py227
-rw-r--r--silx/gui/plot/test/testColormap.py291
-rw-r--r--silx/gui/plot/test/testColors.py8
-rw-r--r--silx/gui/plot/test/testComplexImageView.py95
-rw-r--r--silx/gui/plot/test/testCurvesROIWidget.py3
-rw-r--r--silx/gui/plot/test/testItem.py231
-rw-r--r--silx/gui/plot/test/testLegendSelector.py3
-rw-r--r--silx/gui/plot/test/testLimitConstraints.py125
-rw-r--r--silx/gui/plot/test/testMaskToolsWidget.py38
-rw-r--r--silx/gui/plot/test/testPlotInteraction.py27
-rw-r--r--silx/gui/plot/test/testPlotTools.py23
-rw-r--r--silx/gui/plot/test/testPlotWidget.py775
-rw-r--r--silx/gui/plot/test/testPlotWidgetNoBackend.py (renamed from silx/gui/plot/test/testPlot.py)98
-rw-r--r--silx/gui/plot/test/testPlotWindow.py14
-rw-r--r--silx/gui/plot/test/testScatterMaskToolsWidget.py37
-rw-r--r--silx/gui/plot/test/testStackView.py33
-rw-r--r--silx/gui/plot/test/testUtilsAxis.py148
-rw-r--r--silx/gui/plot/test/utils.py194
19 files changed, 2030 insertions, 420 deletions
diff --git a/silx/gui/plot/test/__init__.py b/silx/gui/plot/test/__init__.py
index b4378c7..2c2943e 100644
--- a/silx/gui/plot/test/__init__.py
+++ b/silx/gui/plot/test/__init__.py
@@ -24,48 +24,58 @@
# ###########################################################################*/
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "18/02/2016"
+__date__ = "04/08/2017"
import unittest
-from .._utils.test import suite as testUtilsSuite
-from .testColorBar import suite as testColorBarSuite
-from .testColormapDialog import suite as testColormapDialogSuite
-from .testColors import suite as testColorsSuite
-from .testCurvesROIWidget import suite as testCurvesROIWidgetSuite
-from .testAlphaSlider import suite as testAlphaSliderSuite
-from .testInteraction import suite as testInteractionSuite
-from .testLegendSelector import suite as testLegendSelectorSuite
-from .testMaskToolsWidget import suite as testMaskToolsWidgetSuite
-from .testScatterMaskToolsWidget import suite as testScatterMaskToolsWidgetSuite
-from .testPlotInteraction import suite as testPlotInteractionSuite
-from .testPlotTools import suite as testPlotToolsSuite
-from .testPlotWidget import suite as testPlotWidgetSuite
-from .testPlotWindow import suite as testPlotWindowSuite
-from .testPlot import suite as testPlotSuite
-from .testProfile import suite as testProfileSuite
-from .testStackView import suite as testStackViewSuite
+from .._utils import test
+from . import testColorBar
+from . import testColormap
+from . import testColormapDialog
+from . import testColors
+from . import testCurvesROIWidget
+from . import testAlphaSlider
+from . import testInteraction
+from . import testLegendSelector
+from . import testMaskToolsWidget
+from . import testScatterMaskToolsWidget
+from . import testPlotInteraction
+from . import testPlotTools
+from . import testPlotWidgetNoBackend
+from . import testPlotWidget
+from . import testPlotWindow
+from . import testProfile
+from . import testStackView
+from . import testItem
+from . import testUtilsAxis
+from . import testLimitConstraints
+from . import testComplexImageView
def suite():
test_suite = unittest.TestSuite()
test_suite.addTests(
- [testUtilsSuite(),
- testColorBarSuite(),
- testColorsSuite(),
- testColormapDialogSuite(),
- testCurvesROIWidgetSuite(),
- testAlphaSliderSuite(),
- testInteractionSuite(),
- testLegendSelectorSuite(),
- testMaskToolsWidgetSuite(),
- testScatterMaskToolsWidgetSuite(),
- testPlotInteractionSuite(),
- testPlotSuite(),
- testPlotToolsSuite(),
- testPlotWidgetSuite(),
- testPlotWindowSuite(),
- testProfileSuite(),
- testStackViewSuite()])
+ [test.suite(),
+ testColorBar.suite(),
+ testColors.suite(),
+ testColormapDialog.suite(),
+ testCurvesROIWidget.suite(),
+ testAlphaSlider.suite(),
+ testInteraction.suite(),
+ testLegendSelector.suite(),
+ testMaskToolsWidget.suite(),
+ testScatterMaskToolsWidget.suite(),
+ testPlotInteraction.suite(),
+ testPlotWidgetNoBackend.suite(),
+ testPlotTools.suite(),
+ testPlotWidget.suite(),
+ testPlotWindow.suite(),
+ testProfile.suite(),
+ testStackView.suite(),
+ testColormap.suite(),
+ testItem.suite(),
+ testUtilsAxis.suite(),
+ testLimitConstraints.suite(),
+ testComplexImageView.suite()])
return test_suite
diff --git a/silx/gui/plot/test/testColorBar.py b/silx/gui/plot/test/testColorBar.py
index 797ff03..80ae6a8 100644
--- a/silx/gui/plot/test/testColorBar.py
+++ b/silx/gui/plot/test/testColorBar.py
@@ -32,22 +32,37 @@ import unittest
from silx.gui.test.utils import TestCaseQt
from silx.gui.plot.ColorBar import _ColorScale
from silx.gui.plot.ColorBar import ColorBarWidget
+from silx.gui.plot.Colormap import Colormap
from silx.gui.plot import Plot2D
+from silx.gui import qt
import numpy
-class TestColorScale(unittest.TestCase):
+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.colorScaleWidget.deleteLater()
- self.colorScaleWidget = None
+ 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 = { 'name': 'gray', 'normalization': 'linear',
- 'autoscale': False, 'vmin': 0.0, 'vmax': 1.0 }
+ self.colorMapLin1 = Colormap(name='gray',
+ normalization=Colormap.LINEAR,
+ vmin=0.0,
+ vmax=1.0)
self.colorScaleWidget.setColormap(self.colorMapLin1)
self.assertTrue(
@@ -57,8 +72,10 @@ class TestColorScale(unittest.TestCase):
self.assertTrue(
self.colorScaleWidget.getValueFromRelativePosition(1.0) == 1.0)
- self.colorMapLin2 = { 'name': 'viridis', 'normalization': 'linear',
- 'autoscale': False, 'vmin': -10, 'vmax': 0 }
+ self.colorMapLin2 = Colormap(name='viridis',
+ normalization=Colormap.LINEAR,
+ vmin=-10,
+ vmax=0)
self.colorScaleWidget.setColormap(self.colorMapLin2)
self.assertTrue(
@@ -69,8 +86,10 @@ class TestColorScale(unittest.TestCase):
self.colorScaleWidget.getValueFromRelativePosition(1.0) == 0.0)
def testRelativePositionLog(self):
- self.colorMapLog1 = { 'name': 'temperature', 'normalization': 'log',
- 'autoscale': False, 'vmin': 1.0, 'vmax': 100.0 }
+ self.colorMapLog1 = Colormap(name='temperature',
+ normalization=Colormap.LOGARITHM,
+ vmin=1.0,
+ vmax=100.0)
self.colorScaleWidget.setColormap(self.colorMapLog1)
@@ -83,41 +102,38 @@ class TestColorScale(unittest.TestCase):
val = self.colorScaleWidget.getValueFromRelativePosition(0.0)
self.assertTrue(val == 1.0)
- def testNegativeLogMin(self):
- colormap = { 'name': 'gray', 'normalization': 'log',
- 'autoscale': False, 'vmin': -1.0, 'vmax': 1.0 }
-
- with self.assertRaises(ValueError):
- self.colorScaleWidget.setColormap(colormap)
-
- def testNegativeLogMax(self):
- colormap = { 'name': 'gray', 'normalization': 'log',
- 'autoscale': False, 'vmin': 1.0, 'vmax': -1.0 }
- with self.assertRaises(ValueError):
- self.colorScaleWidget.setColormap(colormap)
-
-class TestNoAutoscale(unittest.TestCase):
+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 = ColorBarWidget(parent=None, plot=self.plot)
+ 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 = { 'name': 'gray', 'normalization': 'log',
- 'autoscale': False, 'vmin': 1.0, 'vmax': 100.0 }
+ 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')
@@ -139,8 +155,10 @@ class TestNoAutoscale(unittest.TestCase):
self.assertTrue(val == 1.0)
def testLinearNormNoAutoscale(self):
- colormapLog = { 'name': 'gray', 'normalization': 'linear',
- 'autoscale': False, 'vmin': -4, 'vmax': 5 }
+ 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')
@@ -159,20 +177,26 @@ class TestNoAutoscale(unittest.TestCase):
val = self.colorScale.getValueFromRelativePosition(0.0)
self.assertTrue(val == -4.0)
-class TestColorbarWidget(TestCaseQt):
- """Test interaction with the ColorScaleBar"""
+
+class TestColorBarWidget(TestCaseQt):
+ """Test interaction with the ColorBarWidget"""
def setUp(self):
- super(TestColorbarWidget, self).setUp()
+ super(TestColorBarWidget, self).setUp()
self.plot = Plot2D()
- self.colorBar = ColorBarWidget(parent=None, plot=self.plot)
+ 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()
+ super(TestColorBarWidget, self).tearDown()
def testEmptyColorBar(self):
colorBar = ColorBarWidget(parent=None)
@@ -185,38 +209,43 @@ class TestColorbarWidget(TestCaseQt):
Note : colorbar is modified by the Plot directly not ColorBarWidget
"""
- colormapLog = { 'name': 'gray', 'normalization': 'log',
- 'autoscale': True, 'vmin': -1.0, 'vmax': 1.0 }
-
- colormapLog2 = { 'name': 'gray', 'normalization': 'log',
- 'autoscale': False, 'vmin': -1.0, 'vmax': 1.0 }
+ 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 autoscale : set to minmal positive value
- data[data<1] = data.max()
- self.assertTrue(self.colorBar._colormap['vmin'] == data.min())
- self.assertTrue(self.colorBar._colormap['vmax'] == data.max())
-
- data = numpy.linspace(-9, -2, 100).reshape(10, 10)
+ # 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)
- self.plot.addImage(data=data, colormap=colormapLog2, legend='toto')
+ # if data is positive
+ data[data<1] = data.max()
+ self.plot.addImage(data=data,
+ colormap=colormapLog,
+ legend='toto',
+ replace=True)
self.plot.setActiveImage('toto')
- # if negative values, changing bounds for default : 1, 10
- self.assertTrue(self.colorBar._colormap['vmin'] == 1)
- self.assertTrue(self.colorBar._colormap['vmax'] == 10)
- def testPlotAssocation(self):
- """Make sure the ColorBarWidget is proparly connected with the plot"""
- colormap = { 'name': 'gray', 'normalization': 'linear',
- 'autoscale': True, 'vmin': -1.0, 'vmax': 1.0 }
+ self.assertTrue(self.colorBar.getColorScaleBar().minVal == data.min())
+ self.assertTrue(self.colorBar.getColorScaleBar().maxVal == data.max())
- # make sure that default settings are the same
+ 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() == self.plot.getDefaultColormap())
+ 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')
@@ -224,12 +253,94 @@ class TestColorbarWidget(TestCaseQt):
# make sure the modification of the colormap has been done
self.assertFalse(
- self.colorBar.getColormap() == self.plot.getDefaultColormap())
+ 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.assertTrue(
+ self.colorBar.getColorScaleBar().getTickBar()._norm == "linear")
+
+ # 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.assertTrue(
+ self.colorBar.getColorScaleBar().getTickBar()._norm == 'log')
+
+ # 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):
+ for ui in (TestColorScale, TestNoAutoscale, TestColorBarWidget,
+ TestColorBarUpdate):
test_suite.addTest(
unittest.defaultTestLoader.loadTestsFromTestCase(ui))
@@ -237,4 +348,4 @@ def suite():
if __name__ == '__main__':
- unittest.main(defaultTest='suite') \ No newline at end of file
+ unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testColormap.py b/silx/gui/plot/test/testColormap.py
new file mode 100644
index 0000000..aa285d3
--- /dev/null
+++ b/silx/gui/plot/test/testColormap.py
@@ -0,0 +1,291 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2015-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.
+#
+# ###########################################################################*/
+"""This module provides the Colormap object
+"""
+
+from __future__ import absolute_import
+
+__authors__ = ["H.Payno"]
+__license__ = "MIT"
+__date__ = "05/12/2016"
+
+import unittest
+import numpy
+from silx.test.utils import ParametricTestCase
+from silx.gui.plot.Colormap import Colormap
+
+
+class TestDictAPI(unittest.TestCase):
+ """Make sure the old dictionary API is working
+ """
+
+ def setUp(self):
+ self.vmin = -1.0
+ self.vmax = 12
+
+ def testGetItem(self):
+ """test the item getter API ([xxx])"""
+ colormap = Colormap(name='viridis',
+ normalization=Colormap.LINEAR,
+ vmin=self.vmin,
+ vmax=self.vmax)
+ self.assertTrue(colormap['name'] == 'viridis')
+ self.assertTrue(colormap['normalization'] == Colormap.LINEAR)
+ self.assertTrue(colormap['vmin'] == self.vmin)
+ self.assertTrue(colormap['vmax'] == self.vmax)
+ with self.assertRaises(KeyError):
+ colormap['toto']
+
+ def testGetDict(self):
+ """Test the getDict function API"""
+ clmObject = Colormap(name='viridis',
+ normalization=Colormap.LINEAR,
+ vmin=self.vmin,
+ vmax=self.vmax)
+ clmDict = clmObject._toDict()
+ self.assertTrue(clmDict['name'] == 'viridis')
+ self.assertTrue(clmDict['autoscale'] is False)
+ self.assertTrue(clmDict['vmin'] == self.vmin)
+ self.assertTrue(clmDict['vmax'] == self.vmax)
+ self.assertTrue(clmDict['normalization'] == Colormap.LINEAR)
+
+ clmObject.setVRange(None, None)
+ self.assertTrue(clmObject._toDict()['autoscale'] is True)
+
+ def testSetValidDict(self):
+ """Test that if a colormap is created from a dict then it is correctly
+ created and the values are copied (so if some values from the dict
+ is changing, this won't affect the Colormap object"""
+ clm_dict = {
+ 'name': 'temperature',
+ 'vmin': 1.0,
+ 'vmax': 2.0,
+ 'normalization': 'linear',
+ 'colors': None,
+ 'autoscale': False
+ }
+
+ # Test that the colormap is correctly created
+ colormapObject = Colormap._fromDict(clm_dict)
+ self.assertTrue(colormapObject.getName() == clm_dict['name'])
+ self.assertTrue(colormapObject.getColormapLUT() == clm_dict['colors'])
+ self.assertTrue(colormapObject.getVMin() == clm_dict['vmin'])
+ self.assertTrue(colormapObject.getVMax() == clm_dict['vmax'])
+ self.assertTrue(colormapObject.isAutoscale() == clm_dict['autoscale'])
+
+ # Check that the colormap has copied the values
+ clm_dict['vmin'] = None
+ clm_dict['vmax'] = None
+ clm_dict['colors'] = [1.0, 2.0]
+ clm_dict['autoscale'] = True
+ clm_dict['normalization'] = Colormap.LOGARITHM
+ clm_dict['name'] = 'viridis'
+
+ self.assertFalse(colormapObject.getName() == clm_dict['name'])
+ self.assertFalse(colormapObject.getColormapLUT() == clm_dict['colors'])
+ self.assertFalse(colormapObject.getVMin() == clm_dict['vmin'])
+ self.assertFalse(colormapObject.getVMax() == clm_dict['vmax'])
+ self.assertFalse(colormapObject.isAutoscale() == clm_dict['autoscale'])
+
+ def testMissingKeysFromDict(self):
+ """Make sure we can create a Colormap object from a dictionnary even if
+ there is missing keys excepts if those keys are 'colors' or 'name'
+ """
+ colormap = Colormap._fromDict({'name': 'toto'})
+ self.assertTrue(colormap.getVMin() is None)
+ colormap = Colormap._fromDict({'colors': numpy.zeros(10)})
+ self.assertTrue(colormap.getName() is None)
+
+ with self.assertRaises(ValueError):
+ Colormap._fromDict({})
+
+ def testUnknowNorm(self):
+ """Make sure an error is raised if the given normalization is not
+ knowed
+ """
+ clm_dict = {
+ 'name': 'temperature',
+ 'vmin': 1.0,
+ 'vmax': 2.0,
+ 'normalization': 'toto',
+ 'colors': None,
+ 'autoscale': False
+ }
+ with self.assertRaises(ValueError):
+ colormapObject = Colormap._fromDict(clm_dict)
+
+
+class TestObjectAPI(ParametricTestCase):
+ """Test the new Object API of the colormap"""
+ def setUp(self):
+ signalHasBeenEmitting = False
+
+ def testVMinVMax(self):
+ """Test getter and setter associated to vmin and vmax values"""
+ vmin = 1.0
+ vmax = 2.0
+
+ colormapObject = Colormap(name='viridis',
+ vmin=vmin,
+ vmax=vmax,
+ normalization=Colormap.LINEAR)
+
+ with self.assertRaises(ValueError):
+ colormapObject.setVMin(3)
+
+ with self.assertRaises(ValueError):
+ colormapObject.setVMax(-2)
+
+ with self.assertRaises(ValueError):
+ colormapObject.setVRange(3, -2)
+
+ self.assertTrue(colormapObject.getColormapRange() == (1.0, 2.0))
+ self.assertTrue(colormapObject.isAutoscale() is False)
+ colormapObject.setVRange(None, None)
+ self.assertTrue(colormapObject.getVMin() is None)
+ self.assertTrue(colormapObject.getVMax() is None)
+ self.assertTrue(colormapObject.isAutoscale() is True)
+
+ def testCopy(self):
+ """Make sure the copy function is correctly processing
+ """
+ colormapObject = Colormap(name='toto',
+ colors=numpy.array([12, 13, 14]),
+ vmin=None,
+ vmax=None,
+ normalization=Colormap.LOGARITHM)
+
+ colormapObject2 = colormapObject.copy()
+ self.assertTrue(colormapObject == colormapObject2)
+ colormapObject.setColormapLUT(numpy.array([0, 1]))
+ self.assertFalse(colormapObject == colormapObject2)
+
+ colormapObject2 = colormapObject.copy()
+ self.assertTrue(colormapObject == colormapObject2)
+ colormapObject.setNormalization(Colormap.LINEAR)
+ self.assertFalse(colormapObject == colormapObject2)
+
+ def testGetColorMapRange(self):
+ """Make sure the getColormapRange function of colormap is correctly
+ applying
+ """
+ # test linear scale
+ data = numpy.array([-1, 1, 2, 3, float('nan')])
+ cl1 = Colormap(name='gray',
+ normalization=Colormap.LINEAR,
+ vmin=0,
+ vmax=2)
+ cl2 = Colormap(name='gray',
+ normalization=Colormap.LINEAR,
+ vmin=None,
+ vmax=2)
+ cl3 = Colormap(name='gray',
+ normalization=Colormap.LINEAR,
+ vmin=0,
+ vmax=None)
+ cl4 = Colormap(name='gray',
+ normalization=Colormap.LINEAR,
+ vmin=None,
+ vmax=None)
+
+ self.assertTrue(cl1.getColormapRange(data) == (0, 2))
+ self.assertTrue(cl2.getColormapRange(data) == (-1, 2))
+ self.assertTrue(cl3.getColormapRange(data) == (0, 3))
+ self.assertTrue(cl4.getColormapRange(data) == (-1, 3))
+
+ # test linear with annoying cases
+ self.assertEqual(cl3.getColormapRange((-1, -2)), (0, 0))
+ self.assertEqual(cl4.getColormapRange(()), (0., 1.))
+ self.assertEqual(cl4.getColormapRange(
+ (float('nan'), float('inf'), 1., -float('inf'), 2)), (1., 2.))
+ self.assertEqual(cl4.getColormapRange(
+ (float('nan'), float('inf'))), (0., 1.))
+
+ # test log scale
+ data = numpy.array([float('nan'), -1, 1, 10, 100, 1000])
+ cl1 = Colormap(name='gray',
+ normalization=Colormap.LOGARITHM,
+ vmin=1,
+ vmax=100)
+ cl2 = Colormap(name='gray',
+ normalization=Colormap.LOGARITHM,
+ vmin=None,
+ vmax=100)
+ cl3 = Colormap(name='gray',
+ normalization=Colormap.LOGARITHM,
+ vmin=1,
+ vmax=None)
+ cl4 = Colormap(name='gray',
+ normalization=Colormap.LOGARITHM,
+ vmin=None,
+ vmax=None)
+
+ self.assertTrue(cl1.getColormapRange(data) == (1, 100))
+ self.assertTrue(cl2.getColormapRange(data) == (1, 100))
+ self.assertTrue(cl3.getColormapRange(data) == (1, 1000))
+ self.assertTrue(cl4.getColormapRange(data) == (1, 1000))
+
+ # test log with annoying cases
+ self.assertEqual(cl3.getColormapRange((0.1, 0.2)), (1, 1))
+ self.assertEqual(cl4.getColormapRange((-2., -1.)), (1., 1.))
+ self.assertEqual(cl4.getColormapRange(()), (1., 10.))
+ self.assertEqual(cl4.getColormapRange(
+ (float('nan'), float('inf'), 1., -float('inf'), 2)), (1., 2.))
+ self.assertEqual(cl4.getColormapRange(
+ (float('nan'), float('inf'))), (1., 10.))
+
+ def testApplyToData(self):
+ """Test applyToData on different datasets"""
+ datasets = [
+ numpy.zeros((0, 0)), # Empty array
+ numpy.array((numpy.nan, numpy.inf)), # All non-finite
+ numpy.array((-numpy.inf, numpy.inf, 1.0, 2.0)), # Some infinite
+ ]
+
+ for normalization in ('linear', 'log'):
+ colormap = Colormap(name='gray',
+ normalization=normalization,
+ vmin=None,
+ vmax=None)
+
+ for data in datasets:
+ with self.subTest(data=data):
+ image = colormap.applyToData(data)
+ self.assertEqual(image.dtype, numpy.uint8)
+ self.assertEqual(image.shape[-1], 4)
+ self.assertEqual(image.shape[:-1], data.shape)
+
+
+def suite():
+ test_suite = unittest.TestSuite()
+ for ui in (TestDictAPI, TestObjectAPI):
+ test_suite.addTest(
+ unittest.defaultTestLoader.loadTestsFromTestCase(ui))
+
+ return test_suite
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testColors.py b/silx/gui/plot/test/testColors.py
index 94c22f3..18f0902 100644
--- a/silx/gui/plot/test/testColors.py
+++ b/silx/gui/plot/test/testColors.py
@@ -35,7 +35,7 @@ import unittest
from silx.test.utils import ParametricTestCase
from silx.gui.plot import Colors
-
+from silx.gui.plot.Colormap import Colormap
class TestRGBA(ParametricTestCase):
"""Basic tests of rgba function"""
@@ -65,8 +65,8 @@ class TestApplyColormapToData(ParametricTestCase):
def testApplyColormapToData(self):
"""Simple test of applyColormapToData function"""
- colormap = dict(name='gray', normalization='linear',
- autoscale=False, vmin=0, vmax=255)
+ colormap = Colormap(name='gray', normalization='linear',
+ vmin=0, vmax=255)
size = 10
expected = numpy.empty((size, 4), dtype='uint8')
@@ -78,7 +78,7 @@ class TestApplyColormapToData(ParametricTestCase):
for dtype in ('uint8', 'int32', 'float32', 'float64'):
with self.subTest(dtype=dtype):
array = numpy.arange(size, dtype=dtype)
- result = Colors.applyColormapToData(array, **colormap)
+ result = colormap.applyToData(data=array)
self.assertTrue(numpy.all(numpy.equal(result, expected)))
diff --git a/silx/gui/plot/test/testComplexImageView.py b/silx/gui/plot/test/testComplexImageView.py
new file mode 100644
index 0000000..f8ec370
--- /dev/null
+++ b/silx/gui/plot/test/testComplexImageView.py
@@ -0,0 +1,95 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2017 European Synchrotron Radiation Facility
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ###########################################################################*/
+"""Test suite for :class:`ComplexImageView`"""
+
+__authors__ = ["T. Vincent"]
+__license__ = "MIT"
+__date__ = "14/09/2017"
+
+
+import unittest
+import logging
+import numpy
+
+from silx.test.utils 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.complex)
+ 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.getSupportedVisualizationModes()
+ for mode in modes:
+ with self.subTest(mode=mode):
+ self.plot.setVisualizationMode(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.complex))
+ self.qWait(100)
+
+ # Test float data
+ self.plot.setData(numpy.arange(100, dtype=numpy.float).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
index 3c6f2ba..716960a 100644
--- a/silx/gui/plot/test/testCurvesROIWidget.py
+++ b/silx/gui/plot/test/testCurvesROIWidget.py
@@ -26,7 +26,7 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "15/05/2017"
import logging
@@ -41,7 +41,6 @@ from silx.gui.test.utils import TestCaseQt
from silx.gui.plot import PlotWindow, CurvesROIWidget
-logging.basicConfig()
_logger = logging.getLogger(__name__)
diff --git a/silx/gui/plot/test/testItem.py b/silx/gui/plot/test/testItem.py
new file mode 100644
index 0000000..8c15bb7
--- /dev/null
+++ b/silx/gui/plot/test/testItem.py
@@ -0,0 +1,231 @@
+# 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.
+#
+# ###########################################################################*/
+"""Tests for PlotWidget items."""
+
+__authors__ = ["T. Vincent"]
+__license__ = "MIT"
+__date__ = "01/09/2017"
+
+
+import unittest
+
+import numpy
+
+from silx.gui.test.utils import SignalListener
+from silx.gui.plot.items import ItemChangedType
+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 Points class
+ curve.setData(numpy.arange(100), numpy.arange(100))
+
+ # SymbolMixIn
+ curve.setSymbol('o')
+ 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.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')
+ data2 = data + 10
+
+ # Test of signals in Scatter class
+ scatter.setData(data2, data2, data2)
+
+ self.assertEqual(listener.arguments(),
+ [(ItemChangedType.COLORMAP,),
+ (ItemChangedType.DATA,)])
+
+ def testShapeChanged(self):
+ """Test sigItemChanged for shape"""
+ data = numpy.array((1., 10.))
+ self.plot.addItem(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,)])
+
+
+def suite():
+ test_suite = unittest.TestSuite()
+ loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
+ test_suite.addTest(loadTests(TestSigItemChangedSignal))
+ 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
index 371197f..9d4ada7 100644
--- a/silx/gui/plot/test/testLegendSelector.py
+++ b/silx/gui/plot/test/testLegendSelector.py
@@ -26,7 +26,7 @@
__authors__ = ["T. Rueter", "T. Vincent"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "15/05/2017"
import logging
@@ -37,7 +37,6 @@ from silx.gui.test.utils import TestCaseQt
from silx.gui.plot import LegendSelector
-logging.basicConfig()
_logger = logging.getLogger(__name__)
diff --git a/silx/gui/plot/test/testLimitConstraints.py b/silx/gui/plot/test/testLimitConstraints.py
new file mode 100644
index 0000000..94aae76
--- /dev/null
+++ b/silx/gui/plot/test/testLimitConstraints.py
@@ -0,0 +1,125 @@
+# 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.
+#
+# ###########################################################################*/
+"""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=1)
+ self.plot.getXAxis().setRangeConstraints(minRange=1, maxRange=1)
+ self.plot.getYAxis().setLimitsConstraints(minPos=1, maxPos=1)
+ 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
index 0c11928..191bbe0 100644
--- a/silx/gui/plot/test/testMaskToolsWidget.py
+++ b/silx/gui/plot/test/testMaskToolsWidget.py
@@ -26,7 +26,7 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "24/01/2017"
+__date__ = "01/09/2017"
import logging
@@ -37,8 +37,9 @@ import numpy
from silx.gui import qt
from silx.test.utils import temp_dir, ParametricTestCase
-from silx.gui.test.utils import TestCaseQt, getQToolButtonFromAction
+from silx.gui.test.utils import getQToolButtonFromAction
from silx.gui.plot import PlotWindow, MaskToolsWidget
+from .utils import PlotWidgetTestCase
try:
import fabio
@@ -46,33 +47,24 @@ except ImportError:
fabio = None
-logging.basicConfig()
_logger = logging.getLogger(__name__)
-class TestMaskToolsWidget(TestCaseQt, ParametricTestCase):
+class TestMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase):
"""Basic test for MaskToolsWidget"""
+ def _createPlot(self):
+ return PlotWindow()
+
def setUp(self):
super(TestMaskToolsWidget, self).setUp()
- self.plot = PlotWindow()
-
self.widget = MaskToolsWidget.MaskToolsDockWidget(plot=self.plot, name='TEST')
self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, self.widget)
-
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
self.maskWidget = self.widget.widget()
def tearDown(self):
del self.maskWidget
del self.widget
-
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
-
super(TestMaskToolsWidget, self).tearDown()
def testEmptyPlot(self):
@@ -85,7 +77,7 @@ class TestMaskToolsWidget(TestCaseQt, ParametricTestCase):
def _drag(self):
"""Drag from plot center to offset position"""
- plot = self.plot.centralWidget()
+ plot = self.plot.getWidgetHandle()
xCenter, yCenter = plot.width() // 2, plot.height() // 2
offset = min(plot.width(), plot.height()) // 10
@@ -99,7 +91,7 @@ class TestMaskToolsWidget(TestCaseQt, ParametricTestCase):
def _drawPolygon(self):
"""Draw a star polygon in the plot"""
- plot = self.plot.centralWidget()
+ plot = self.plot.getWidgetHandle()
x, y = plot.width() // 2, plot.height() // 2
offset = min(plot.width(), plot.height()) // 10
@@ -107,16 +99,17 @@ class TestMaskToolsWidget(TestCaseQt, ParametricTestCase):
(x - offset, y - offset),
(x + offset, y),
(x - offset, y),
- (x + offset, y - offset)]
+ (x + offset, y - offset),
+ (x, y + offset)] # Close polygon
+ self.mouseMove(plot, pos=(0, 0))
for pos in star:
self.mouseMove(plot, pos=pos)
- btn = qt.Qt.LeftButton if pos != star[-1] else qt.Qt.RightButton
- self.mouseClick(plot, btn, pos=pos)
+ self.mouseClick(plot, qt.Qt.LeftButton, pos=pos)
def _drawPencil(self):
"""Draw a star polygon in the plot"""
- plot = self.plot.centralWidget()
+ plot = self.plot.getWidgetHandle()
x, y = plot.width() // 2, plot.height() // 2
offset = min(plot.width(), plot.height()) // 10
@@ -126,9 +119,10 @@ class TestMaskToolsWidget(TestCaseQt, ParametricTestCase):
(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:
+ for pos in star[1:]:
self.mouseMove(plot, pos=pos)
self.mouseRelease(
plot, qt.Qt.LeftButton, pos=star[-1])
diff --git a/silx/gui/plot/test/testPlotInteraction.py b/silx/gui/plot/test/testPlotInteraction.py
index 25f57a9..335b1e4 100644
--- a/silx/gui/plot/test/testPlotInteraction.py
+++ b/silx/gui/plot/test/testPlotInteraction.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016 European Synchrotron Radiation Facility
+# 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
@@ -26,12 +26,12 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "13/10/2016"
+__date__ = "01/09/2017"
import unittest
from silx.gui import qt
-from silx.gui.plot.test.testPlotWidget import _PlotWidgetTest
+from .utils import PlotWidgetTestCase
class _SignalDump(object):
@@ -49,7 +49,7 @@ class _SignalDump(object):
return list(self._received)
-class TestSelectPolygon(_PlotWidgetTest):
+class TestSelectPolygon(PlotWidgetTestCase):
"""Test polygon selection interaction"""
def _interactionModeChanged(self, source):
@@ -59,17 +59,16 @@ class TestSelectPolygon(_PlotWidgetTest):
def _draw(self, polygon):
"""Draw a polygon in the plot
- :param polygon: List of points (x, y) of the polygon (not closed)
+ :param polygon: List of points (x, y) of the polygon (closed)
"""
- plot = self.plot.centralWidget()
+ plot = self.plot.getWidgetHandle()
dump = _SignalDump()
self.plot.sigPlotSignal.connect(dump)
for pos in polygon:
self.mouseMove(plot, pos=pos)
- btn = qt.Qt.LeftButton if pos != polygon[-1] else qt.Qt.RightButton
- self.mouseClick(plot, btn, pos=pos)
+ self.mouseClick(plot, qt.Qt.LeftButton, pos=pos)
self.plot.sigPlotSignal.disconnect(dump)
return [args[0] for args in dump.received]
@@ -89,7 +88,7 @@ class TestSelectPolygon(_PlotWidgetTest):
self.plot.sigInteractiveModeChanged.disconnect(
self._interactionModeChanged)
- plot = self.plot.centralWidget()
+ plot = self.plot.getWidgetHandle()
xCenter, yCenter = plot.width() // 2, plot.height() // 2
offset = min(plot.width(), plot.height()) // 10
@@ -98,7 +97,8 @@ class TestSelectPolygon(_PlotWidgetTest):
(xCenter - offset, yCenter - offset),
(xCenter + offset, yCenter),
(xCenter - offset, yCenter),
- (xCenter + offset, yCenter - offset)]
+ (xCenter + offset, yCenter - offset),
+ (xCenter, yCenter + offset)] # Close polygon
# Draw while dumping signals
events = self._draw(star)
@@ -113,7 +113,8 @@ class TestSelectPolygon(_PlotWidgetTest):
largeSquare = [(xCenter - offset, yCenter - offset),
(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)
@@ -128,7 +129,7 @@ class TestSelectPolygon(_PlotWidgetTest):
thinRectX = [(xCenter, yCenter - offset),
(xCenter, yCenter + offset),
(xCenter + 1, yCenter + offset),
- (xCenter + 1, yCenter - offset)]
+ (xCenter + 1, yCenter - offset)] # Close polygon
# Draw while dumping signals
events = self._draw(thinRectX)
@@ -143,7 +144,7 @@ class TestSelectPolygon(_PlotWidgetTest):
thinRectY = [(xCenter - offset, yCenter),
(xCenter + offset, yCenter),
(xCenter + offset, yCenter + 1),
- (xCenter - offset, yCenter + 1)]
+ (xCenter - offset, yCenter + 1)] # Close polygon
# Draw while dumping signals
events = self._draw(thinRectY)
diff --git a/silx/gui/plot/test/testPlotTools.py b/silx/gui/plot/test/testPlotTools.py
index 1d5e148..a08a18a 100644
--- a/silx/gui/plot/test/testPlotTools.py
+++ b/silx/gui/plot/test/testPlotTools.py
@@ -26,7 +26,7 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "01/09/2017"
import numpy
@@ -37,6 +37,7 @@ from silx.gui.test.utils import (
qWaitForWindowExposedAndActivate, TestCaseQt, getQToolButtonFromAction)
from silx.gui import qt
from silx.gui.plot import Plot2D, PlotWindow, PlotTools
+from .utils import PlotWidgetTestCase
# Makes sure a QApplication exists
@@ -67,23 +68,19 @@ def _tearDownDocTest(docTest):
# """
-class TestPositionInfo(TestCaseQt):
+class TestPositionInfo(PlotWidgetTestCase):
"""Tests for PositionInfo widget."""
+ def _createPlot(self):
+ return PlotWindow()
+
def setUp(self):
super(TestPositionInfo, self).setUp()
- self.plot = PlotWindow()
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
- self.mouseMove(self.plot, pos=(1, 1))
+ self.mouseMove(self.plot, pos=(0, 0))
self.qapp.processEvents()
self.qWait(100)
def tearDown(self):
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
-
super(TestPositionInfo, self).tearDown()
def _test(self, positionWidget, converterNames, **kwargs):
@@ -104,10 +101,10 @@ class TestPositionInfo(TestCaseQt):
with TestLogging(PlotTools.__name__, **kwargs):
# Move mouse to center
- self.mouseMove(self.plot)
+ center = self.plot.size() / 2
+ self.mouseMove(self.plot, pos=(center.width(), center.height()))
+ # Move out
self.mouseMove(self.plot, pos=(1, 1))
- self.qapp.processEvents()
- self.qWait(100)
def testDefaultConverters(self):
"""Test PositionInfo with default converters"""
diff --git a/silx/gui/plot/test/testPlotWidget.py b/silx/gui/plot/test/testPlotWidget.py
index 2de18a8..deeb198 100644
--- a/silx/gui/plot/test/testPlotWidget.py
+++ b/silx/gui/plot/test/testPlotWidget.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016 European Synchrotron Radiation Facility
+# 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
@@ -26,18 +26,24 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "01/09/2017"
import unittest
-
+import logging
import numpy
from silx.test.utils import ParametricTestCase
+from silx.gui.test.utils import SignalListener
from silx.gui.test.utils import TestCaseQt
+from silx.test import utils
+from silx.utils import deprecation
from silx.gui import qt
from silx.gui.plot import PlotWidget
+from silx.gui.plot.Colormap import Colormap
+
+from .utils import PlotWidgetTestCase
SIZE = 1024
@@ -47,27 +53,10 @@ DATA_2D = numpy.arange(SIZE ** 2).reshape(SIZE, SIZE)
"""Image data set"""
-class _PlotWidgetTest(TestCaseQt):
- """Base class for tests of PlotWidget, not a TestCase in itself.
-
- plot attribute is the PlotWidget created for the test.
- """
-
- def setUp(self):
- super(_PlotWidgetTest, self).setUp()
- self.plot = PlotWidget()
- 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(_PlotWidgetTest, self).tearDown()
+logger = logging.getLogger(__name__)
-class TestPlotWidget(_PlotWidgetTest, ParametricTestCase):
+class TestPlotWidget(PlotWidgetTestCase, ParametricTestCase):
"""Basic tests for PlotWidget"""
def testShow(self):
@@ -79,77 +68,115 @@ class TestPlotWidget(_PlotWidgetTest, ParametricTestCase):
title, xlabel, ylabel = 'the title', 'x label', 'y label'
self.plot.setGraphTitle(title)
- self.plot.setGraphXLabel(xlabel)
- self.plot.setGraphYLabel(ylabel)
+ self.plot.getXAxis().setLabel(xlabel)
+ self.plot.getYAxis().setLabel(ylabel)
self.qapp.processEvents()
self.assertEqual(self.plot.getGraphTitle(), title)
- self.assertEqual(self.plot.getGraphXLabel(), xlabel)
- self.assertEqual(self.plot.getGraphYLabel(), ylabel)
+ self.assertEqual(self.plot.getXAxis().getLabel(), xlabel)
+ self.assertEqual(self.plot.getYAxis().getLabel(), ylabel)
- def testChangeLimitsWithAspectRatio(self):
- def checkLimits(expectedXLim=None, expectedYLim=None,
- expectedRatio=None):
- xlim = self.plot.getGraphXLimits()
- ylim = self.plot.getGraphYLimits()
- ratio = abs(xlim[1] - xlim[0]) / abs(ylim[1] - ylim[0])
+ 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 expectedXLim is not None:
+ self.assertEqual(expectedXLim, xlim)
- if expectedYLim is not None:
- self.assertEqual(expectedYLim, ylim)
+ if expectedYLim is not None:
+ self.assertEqual(expectedYLim, ylim)
- if expectedRatio is not None:
- self.assertTrue(
- numpy.allclose(expectedRatio, ratio, atol=0.01))
+ 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.getGraphXLimits()
- ylim = self.plot.getGraphYLimits()
+ xlim = self.plot.getXAxis().getLimits()
+ ylim = self.plot.getYAxis().getLimits()
defaultRatio = abs(xlim[1] - xlim[0]) / abs(ylim[1] - ylim[0])
- self.plot.setGraphXLimits(1., 10.)
- checkLimits(expectedXLim=(1., 10.), expectedRatio=defaultRatio)
+ 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()
- checkLimits(expectedXLim=(1., 10.), expectedRatio=defaultRatio)
+ self._checkLimits(expectedYLim=(1., 10.), expectedRatio=defaultRatio)
- self.plot.setGraphYLimits(1., 10.)
- 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()
- checkLimits(expectedYLim=(1., 10.), expectedRatio=defaultRatio)
+ xlim = self.plot.getXAxis().getLimits()
+ ylim = self.plot.getYAxis().getLimits()
-class TestPlotImage(_PlotWidgetTest, ParametricTestCase):
+ 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._checkLimits(expectedXLim=xlim, expectedYLim=ylim)
+ self.assertEqual(listener.callCount(), 0)
+
+ # Resize with aspect ratio
+ self.plot.setKeepDataAspectRatio(True)
+ listener.clear() # Clean-up received signal
+ self.qapp.processEvents()
+ self.assertEqual(listener.callCount(), 0) # No event when redrawing
+
+ self.plot.resize(200, 200)
+ self.qapp.processEvents()
+
+ self.assertNotEqual(listener.callCount(), 0)
+
+
+class TestPlotImage(PlotWidgetTestCase, ParametricTestCase):
"""Basic tests for addImage"""
def setUp(self):
super(TestPlotImage, self).setUp()
- self.plot.setGraphYLabel('Rows')
- self.plot.setGraphXLabel('Columns')
+ self.plot.getYAxis().setLabel('Rows')
+ self.plot.getXAxis().setLabel('Columns')
def testPlotColormapTemperature(self):
self.plot.setGraphTitle('Temp. Linear')
- colormap = {'name': 'temperature', 'normalization': 'linear',
- 'autoscale': True, 'vmin': 0.0, 'vmax': 1.0}
+ 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 = {'name': 'gray', 'normalization': 'linear',
- 'autoscale': True, 'vmin': 0.0, 'vmax': 1.0}
+ 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 = {'name': 'temperature', 'normalization': 'log',
- 'autoscale': True, 'vmin': 0.0, 'vmax': 1.0}
+ colormap = Colormap(name='temperature',
+ normalization=Colormap.LOGARITHM,
+ vmin=None,
+ vmax=None)
self.plot.addImage(DATA_2D, legend="image 1", colormap=colormap)
def testPlotRgbRgba(self):
@@ -180,19 +207,23 @@ class TestPlotImage(_PlotWidgetTest, ParametricTestCase):
self.plot.setKeepDataAspectRatio(False)
self.plot.setGraphTitle('Custom colormap')
- colormap = {'name': None, 'normalization': 'linear',
- 'autoscale': True, 'vmin': 0.0, 'vmax': 1.0,
- 'colors': ((0., 0., 0.), (1., 0., 0.),
- (0., 1., 0.), (0., 0., 1.))}
+ 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,
replace=False, resetzoom=False)
- colormap = {'name': None, 'normalization': 'linear',
- 'autoscale': True, 'vmin': 0.0, 'vmax': 1.0,
- 'colors': numpy.array(
- ((0, 0, 0, 0), (0, 0, 0, 128),
- (128, 128, 128, 128), (255, 255, 255, 255)),
- dtype=numpy.uint8)}
+ 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),
replace=False, resetzoom=False)
@@ -228,8 +259,8 @@ class TestPlotImage(_PlotWidgetTest, ParametricTestCase):
ybounds = oy, oy + DATA_2D.shape[0] * sy
# Check limits without aspect ratio
- xmin, xmax = self.plot.getGraphXLimits()
- ymin, ymax = self.plot.getGraphYLimits()
+ 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))
@@ -237,8 +268,8 @@ class TestPlotImage(_PlotWidgetTest, ParametricTestCase):
# Check limits with aspect ratio
self.plot.setKeepDataAspectRatio(True)
- xmin, xmax = self.plot.getGraphXLimits()
- ymin, ymax = self.plot.getGraphYLimits()
+ xmin, xmax = self.plot.getXAxis().getLimits()
+ ymin, ymax = self.plot.getYAxis().getLimits()
self.assertTrue(xmin <= min(xbounds))
self.assertTrue(xmax >= max(xbounds))
self.assertTrue(ymin <= min(ybounds))
@@ -248,8 +279,42 @@ class TestPlotImage(_PlotWidgetTest, ParametricTestCase):
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=numpy.bool)
+ data[::2, ::2] = True
+ self.plot.addImage(data, legend='boolean')
-class TestPlotCurve(_PlotWidgetTest):
+ image = self.plot.getActiveImage()
+ retrievedData = image.getData(copy=False)
+ self.assertTrue(numpy.all(numpy.equal(retrievedData, data)))
+ self.assertIs(retrievedData.dtype.type, numpy.int8)
+
+
+class TestPlotCurve(PlotWidgetTestCase):
"""Basic tests for addCurve."""
# Test data sets
@@ -261,8 +326,8 @@ class TestPlotCurve(_PlotWidgetTest):
def setUp(self):
super(TestPlotCurve, self).setUp()
self.plot.setGraphTitle('Curve')
- self.plot.setGraphYLabel('Rows')
- self.plot.setGraphXLabel('Columns')
+ self.plot.getYAxis().setLabel('Rows')
+ self.plot.getXAxis().setLabel('Columns')
self.plot.setActiveCurveHandling(False)
@@ -307,16 +372,16 @@ class TestPlotCurve(_PlotWidgetTest):
self.plot.resetZoom()
-class TestPlotMarker(_PlotWidgetTest):
+class TestPlotMarker(PlotWidgetTestCase):
"""Basic tests for add*Marker"""
def setUp(self):
super(TestPlotMarker, self).setUp()
- self.plot.setGraphYLabel('Rows')
- self.plot.setGraphXLabel('Columns')
+ self.plot.getYAxis().setLabel('Rows')
+ self.plot.getXAxis().setLabel('Columns')
- self.plot.setXAxisAutoScale(False)
- self.plot.setYAxisAutoScale(False)
+ self.plot.getXAxis().setAutoScale(False)
+ self.plot.getYAxis().setAutoScale(False)
self.plot.setKeepDataAspectRatio(False)
self.plot.setLimits(0., 100., -100., 100.)
@@ -382,7 +447,7 @@ class TestPlotMarker(_PlotWidgetTest):
def testPlotMarkerWithoutLegend(self):
self.plot.setGraphTitle('Markers without legend')
- self.plot.setYAxisInverted(True)
+ self.plot.getYAxis().setInverted(True)
# Markers without legend
self.plot.addMarker(10, 10)
@@ -401,7 +466,7 @@ class TestPlotMarker(_PlotWidgetTest):
# TestPlotItem ################################################################
-class TestPlotItem(_PlotWidgetTest):
+class TestPlotItem(PlotWidgetTestCase):
"""Basic tests for addItem."""
# Polygon coordinates and color
@@ -431,10 +496,10 @@ class TestPlotItem(_PlotWidgetTest):
def setUp(self):
super(TestPlotItem, self).setUp()
- self.plot.setGraphYLabel('Rows')
- self.plot.setGraphXLabel('Columns')
- self.plot.setXAxisAutoScale(False)
- self.plot.setYAxisAutoScale(False)
+ 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.)
@@ -475,102 +540,428 @@ class TestPlotItem(_PlotWidgetTest):
self.plot.resetZoom()
-class TestPlotActiveCurveImage(_PlotWidgetTest):
+class TestPlotActiveCurveImage(PlotWidgetTestCase):
"""Basic tests for active image handling"""
def testActiveCurveAndLabels(self):
# Active curve handling off, no label change
self.plot.setActiveCurveHandling(False)
- self.plot.setGraphXLabel('XLabel')
- self.plot.setGraphYLabel('YLabel')
+ self.plot.getXAxis().setLabel('XLabel')
+ self.plot.getYAxis().setLabel('YLabel')
self.plot.addCurve((1, 2), (1, 2))
- self.assertEqual(self.plot.getGraphXLabel(), 'XLabel')
- self.assertEqual(self.plot.getGraphYLabel(), 'YLabel')
+ 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.getGraphXLabel(), 'XLabel')
- self.assertEqual(self.plot.getGraphYLabel(), 'YLabel')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
self.plot.clear()
- self.assertEqual(self.plot.getGraphXLabel(), 'XLabel')
- self.assertEqual(self.plot.getGraphYLabel(), 'YLabel')
+ 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.setGraphXLabel('XLabel')
- self.plot.setGraphYLabel('YLabel')
+ 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.assertEqual(self.plot.getGraphXLabel(), 'x1')
- self.assertEqual(self.plot.getGraphYLabel(), 'y1')
+ 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.getGraphXLabel(), 'x1')
- self.assertEqual(self.plot.getGraphYLabel(), 'y1')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
# labels changed
self.plot.setActiveCurve('2')
- self.assertEqual(self.plot.getGraphXLabel(), 'XLabel')
- self.assertEqual(self.plot.getGraphYLabel(), 'YLabel')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
self.plot.setActiveCurve('1')
- self.assertEqual(self.plot.getGraphXLabel(), 'x1')
- self.assertEqual(self.plot.getGraphYLabel(), 'y1')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
self.plot.clear()
- self.assertEqual(self.plot.getGraphXLabel(), 'XLabel')
- self.assertEqual(self.plot.getGraphYLabel(), 'YLabel')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
def testActiveImageAndLabels(self):
# Active image handling always on, no API for toggling it
- self.plot.setGraphXLabel('XLabel')
- self.plot.setGraphYLabel('YLabel')
+ self.plot.getXAxis().setLabel('XLabel')
+ self.plot.getYAxis().setLabel('YLabel')
# labels changed as active curve
self.plot.addImage(numpy.arange(100).reshape(10, 10), replace=False,
legend='1', xlabel='x1', ylabel='y1')
- self.assertEqual(self.plot.getGraphXLabel(), 'x1')
- self.assertEqual(self.plot.getGraphYLabel(), '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), replace=False,
legend='2')
- self.assertEqual(self.plot.getGraphXLabel(), 'x1')
- self.assertEqual(self.plot.getGraphYLabel(), 'y1')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
# labels changed
self.plot.setActiveImage('2')
- self.assertEqual(self.plot.getGraphXLabel(), 'XLabel')
- self.assertEqual(self.plot.getGraphYLabel(), 'YLabel')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
self.plot.setActiveImage('1')
- self.assertEqual(self.plot.getGraphXLabel(), 'x1')
- self.assertEqual(self.plot.getGraphYLabel(), 'y1')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
self.plot.clear()
- self.assertEqual(self.plot.getGraphXLabel(), 'XLabel')
- self.assertEqual(self.plot.getGraphYLabel(), 'YLabel')
+ self.assertEqual(self.plot.getXAxis().getLabel(), 'XLabel')
+ self.assertEqual(self.plot.getYAxis().getLabel(), 'YLabel')
##############################################################################
# Log
##############################################################################
-class TestPlotEmptyLog(_PlotWidgetTest):
+class TestPlotEmptyLog(PlotWidgetTestCase):
"""Basic tests for log plot"""
def testEmptyPlotTitleLabelsLog(self):
self.plot.setGraphTitle('Empty Log Log')
- self.plot.setGraphXLabel('X')
- self.plot.setGraphYLabel('Y')
+ 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 setUp(self):
+ super(TestPlotAxes, self).setUp()
+ self.plot = PlotWidget()
+ # 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)
+
+ @utils.test_logging(deprecation.depreclog.name, warning=2)
+ 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")
+
+ listener = SignalListener()
+ self.plot.sigSetXAxisLogarithmic.connect(listener.partial("x"))
+ self.plot.sigSetYAxisLogarithmic.connect(listener.partial("y"))
+
+ 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.assertEqual(listener.arguments(callIndex=-1), ("x", True))
+
self.plot.setYAxisLogarithmic(True)
- self.plot.resetZoom()
+ 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)
+ self.assertEqual(listener.arguments(callIndex=-1), ("y", 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)
+ self.assertEqual(listener.arguments(callIndex=-1), ("y", False))
+
+ @utils.test_logging(deprecation.depreclog.name, warning=2)
+ 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")
+
+ listener = SignalListener()
+ self.plot.sigSetXAxisAutoScale.connect(listener.partial("x"))
+ self.plot.sigSetYAxisAutoScale.connect(listener.partial("y"))
+
+ 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.assertEqual(listener.arguments(callIndex=-1), ("x", False))
+
+ 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)
+ self.assertEqual(listener.arguments(callIndex=-1), ("y", 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)
+ self.assertEqual(listener.arguments(callIndex=-1), ("y", True))
+
+ @utils.test_logging(deprecation.depreclog.name, warning=1)
+ 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")
+
+ listener = SignalListener()
+ self.plot.sigSetYAxisInverted.connect(listener.partial("y"))
+
+ 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)
+ self.assertEqual(listener.arguments(callIndex=-1), ("y", 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)
+ self.assertEqual(listener.arguments(callIndex=-1), ("y", 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)
-class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
+ 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.assertEquals(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.assertEquals(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.assertEquals(listener.arguments(callIndex=-1), (20.0, 30.0))
+ self.assertEquals(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.assertEquals(listener.arguments(callIndex=-1), (20.0, 30.0))
+ self.assertEquals(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.assertEquals(listener.arguments(callIndex=-1), (20.0, 30.0))
+ self.assertEquals(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.assertEquals(y.getScale(), y.LOGARITHMIC)
+ events = listener.arguments()
+ self.assertEquals(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.assertEquals(y.isAutoScale(), False)
+ events = listener.arguments()
+ self.assertEquals(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.assertEquals(y.isInverted(), True)
+ events = listener.arguments()
+ self.assertEquals(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)
+
+
+class TestPlotCurveLog(PlotWidgetTestCase, ParametricTestCase):
"""Basic tests for addCurve with log scale axes"""
# Test data
@@ -578,12 +969,12 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
yData = xData ** 2
def _setLabels(self):
- self.plot.setGraphXLabel('X')
- self.plot.setGraphYLabel('X * X')
+ self.plot.getXAxis().setLabel('X')
+ self.plot.getYAxis().setLabel('X * X')
def testPlotCurveLogX(self):
self._setLabels()
- self.plot.setXAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
self.plot.setGraphTitle('Curve X: Log Y: Linear')
self.plot.addCurve(self.xData, self.yData,
@@ -593,7 +984,7 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
def testPlotCurveLogY(self):
self._setLabels()
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
self.plot.setGraphTitle('Curve X: Linear Y: Log')
@@ -604,8 +995,8 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
def testPlotCurveLogXY(self):
self._setLabels()
- self.plot.setXAxisLogarithmic(True)
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
self.plot.setGraphTitle('Curve X: Log Y: Log')
@@ -615,8 +1006,8 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
color='green', linestyle="-", symbol='o')
def testPlotCurveErrorLogXY(self):
- self.plot.setXAxisLogarithmic(True)
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
# Every second error leads to negative number
errors = numpy.ones_like(self.xData)
@@ -666,17 +1057,17 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
self.qapp.processEvents()
# no log axis
- xLim = self.plot.getGraphXLimits()
+ xLim = self.plot.getXAxis().getLimits()
self.assertEqual(xLim, (min(xData), max(xData)))
- yLim = self.plot.getGraphYLimits()
+ yLim = self.plot.getYAxis().getLimits()
self.assertEqual(yLim, (min(yData), max(yData)))
# x axis log
- self.plot.setXAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
self.qapp.processEvents()
- xLim = self.plot.getGraphXLimits()
- yLim = self.plot.getGraphYLimits()
+ xLim = self.plot.getXAxis().getLimits()
+ yLim = self.plot.getYAxis().getLimits()
positives = xData > 0
if numpy.any(positives):
self.assertTrue(numpy.allclose(
@@ -688,11 +1079,11 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
self.assertEqual(yLim, (1., 100.))
# x axis and y axis log
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
self.qapp.processEvents()
- xLim = self.plot.getGraphXLimits()
- yLim = self.plot.getGraphYLimits()
+ 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(
@@ -704,11 +1095,11 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
self.assertEqual(yLim, (1., 100.))
# y axis log
- self.plot.setXAxisLogarithmic(False)
+ self.plot.getXAxis()._setLogarithmic(False)
self.qapp.processEvents()
- xLim = self.plot.getGraphXLimits()
- yLim = self.plot.getGraphYLimits()
+ xLim = self.plot.getXAxis().getLimits()
+ yLim = self.plot.getYAxis().getLimits()
positives = yData > 0
if numpy.any(positives):
self.assertEqual(
@@ -720,12 +1111,12 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
self.assertEqual(yLim, (1., 100.))
# no log axis
- self.plot.setYAxisLogarithmic(False)
+ self.plot.getYAxis()._setLogarithmic(False)
self.qapp.processEvents()
- xLim = self.plot.getGraphXLimits()
+ xLim = self.plot.getXAxis().getLimits()
self.assertEqual(xLim, (min(xData), max(xData)))
- yLim = self.plot.getGraphYLimits()
+ yLim = self.plot.getYAxis().getLimits()
self.assertEqual(yLim, (min(yData), max(yData)))
self.plot.clear()
@@ -733,52 +1124,58 @@ class TestPlotCurveLog(_PlotWidgetTest, ParametricTestCase):
self.qapp.processEvents()
-class TestPlotImageLog(_PlotWidgetTest):
+class TestPlotImageLog(PlotWidgetTestCase):
"""Basic tests for addImage with log scale axes."""
def setUp(self):
super(TestPlotImageLog, self).setUp()
- self.plot.setGraphXLabel('Columns')
- self.plot.setGraphYLabel('Rows')
+ self.plot.getXAxis().setLabel('Columns')
+ self.plot.getYAxis().setLabel('Rows')
def testPlotColormapGrayLogX(self):
- self.plot.setXAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
self.plot.setGraphTitle('CMap X: Log Y: Linear')
- colormap = {'name': 'gray', 'normalization': 'linear',
- 'autoscale': True, 'vmin': 0.0, 'vmax': 1.0}
+ colormap = Colormap(name='gray',
+ normalization='linear',
+ vmin=None,
+ vmax=None)
self.plot.addImage(DATA_2D, legend="image 1",
origin=(1., 1.), scale=(1., 1.),
replace=False, resetzoom=False, colormap=colormap)
self.plot.resetZoom()
def testPlotColormapGrayLogY(self):
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
self.plot.setGraphTitle('CMap X: Linear Y: Log')
- colormap = {'name': 'gray', 'normalization': 'linear',
- 'autoscale': True, 'vmin': 0.0, 'vmax': 1.0}
+ colormap = Colormap(name='gray',
+ normalization='linear',
+ vmin=None,
+ vmax=None)
self.plot.addImage(DATA_2D, legend="image 1",
origin=(1., 1.), scale=(1., 1.),
replace=False, resetzoom=False, colormap=colormap)
self.plot.resetZoom()
def testPlotColormapGrayLogXY(self):
- self.plot.setXAxisLogarithmic(True)
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
self.plot.setGraphTitle('CMap X: Log Y: Log')
- colormap = {'name': 'gray', 'normalization': 'linear',
- 'autoscale': True, 'vmin': 0.0, 'vmax': 1.0}
+ colormap = Colormap(name='gray',
+ normalization='linear',
+ vmin=None,
+ vmax=None)
self.plot.addImage(DATA_2D, legend="image 1",
origin=(1., 1.), scale=(1., 1.),
replace=False, resetzoom=False, colormap=colormap)
self.plot.resetZoom()
def testPlotRgbRgbaLogXY(self):
- self.plot.setXAxisLogarithmic(True)
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
self.plot.setGraphTitle('RGB + RGBA X: Log Y: Log')
rgb = numpy.array(
@@ -801,7 +1198,7 @@ class TestPlotImageLog(_PlotWidgetTest):
self.plot.resetZoom()
-class TestPlotMarkerLog(_PlotWidgetTest):
+class TestPlotMarkerLog(PlotWidgetTestCase):
"""Basic tests for markers on log scales"""
# Test marker parameters
@@ -816,14 +1213,14 @@ class TestPlotMarkerLog(_PlotWidgetTest):
def setUp(self):
super(TestPlotMarkerLog, self).setUp()
- self.plot.setGraphYLabel('Rows')
- self.plot.setGraphXLabel('Columns')
- self.plot.setXAxisAutoScale(False)
- self.plot.setYAxisAutoScale(False)
+ 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.setXAxisLogarithmic(True)
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
def testPlotMarkerXLog(self):
self.plot.setGraphTitle('Markers X, Log axes')
@@ -862,7 +1259,7 @@ class TestPlotMarkerLog(_PlotWidgetTest):
self.plot.resetZoom()
-class TestPlotItemLog(_PlotWidgetTest):
+class TestPlotItemLog(PlotWidgetTestCase):
"""Basic tests for items with log scale axes"""
# Polygon coordinates and color
@@ -892,14 +1289,14 @@ class TestPlotItemLog(_PlotWidgetTest):
def setUp(self):
super(TestPlotItemLog, self).setUp()
- self.plot.setGraphYLabel('Rows')
- self.plot.setGraphXLabel('Columns')
- self.plot.setXAxisAutoScale(False)
- self.plot.setYAxisAutoScale(False)
+ 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., 100.)
- self.plot.setXAxisLogarithmic(True)
- self.plot.setYAxisLogarithmic(True)
+ self.plot.getXAxis()._setLogarithmic(True)
+ self.plot.getYAxis()._setLogarithmic(True)
def testPlotItemPolygonLogFill(self):
self.plot.setGraphTitle('Item Fill Log')
@@ -940,26 +1337,18 @@ class TestPlotItemLog(_PlotWidgetTest):
def suite():
test_suite = unittest.TestSuite()
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotWidget))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotImage))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotCurve))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotMarker))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotItem))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotEmptyLog))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotCurveLog))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotImageLog))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotMarkerLog))
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestPlotItemLog))
+ loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
+ test_suite.addTest(loadTests(TestPlotWidget))
+ test_suite.addTest(loadTests(TestPlotImage))
+ test_suite.addTest(loadTests(TestPlotCurve))
+ test_suite.addTest(loadTests(TestPlotMarker))
+ test_suite.addTest(loadTests(TestPlotItem))
+ test_suite.addTest(loadTests(TestPlotAxes))
+ test_suite.addTest(loadTests(TestPlotEmptyLog))
+ test_suite.addTest(loadTests(TestPlotCurveLog))
+ test_suite.addTest(loadTests(TestPlotImageLog))
+ test_suite.addTest(loadTests(TestPlotMarkerLog))
+ test_suite.addTest(loadTests(TestPlotItemLog))
return test_suite
diff --git a/silx/gui/plot/test/testPlot.py b/silx/gui/plot/test/testPlotWidgetNoBackend.py
index 25e7511..3094a20 100644
--- a/silx/gui/plot/test/testPlot.py
+++ b/silx/gui/plot/test/testPlotWidgetNoBackend.py
@@ -22,11 +22,11 @@
# THE SOFTWARE.
#
# ###########################################################################*/
-"""Basic tests for Plot"""
+"""Basic tests for PlotWidget with 'none' backend"""
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "27/06/2017"
import unittest
@@ -35,7 +35,7 @@ from silx.test.utils import ParametricTestCase
import numpy
-from silx.gui.plot.Plot import Plot
+from silx.gui.plot.PlotWidget import PlotWidget
from silx.gui.plot.items.histogram import _getHistogramCurve, _computeEdges
@@ -45,21 +45,21 @@ class TestPlot(unittest.TestCase):
def testPlotTitleLabels(self):
"""Create a Plot and set the labels"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
title, xlabel, ylabel = 'the title', 'x label', 'y label'
plot.setGraphTitle(title)
- plot.setGraphXLabel(xlabel)
- plot.setGraphYLabel(ylabel)
+ plot.getXAxis().setLabel(xlabel)
+ plot.getYAxis().setLabel(ylabel)
self.assertEqual(plot.getGraphTitle(), title)
- self.assertEqual(plot.getGraphXLabel(), xlabel)
- self.assertEqual(plot.getGraphYLabel(), ylabel)
+ self.assertEqual(plot.getXAxis().getLabel(), xlabel)
+ self.assertEqual(plot.getYAxis().getLabel(), ylabel)
def testAddNoRemove(self):
"""add objects to the Plot"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
plot.addCurve(x=(1, 2, 3), y=(3, 2, 1))
plot.addImage(numpy.arange(100.).reshape(10, -1))
plot.addItem(
@@ -96,7 +96,7 @@ class TestPlotRanges(ParametricTestCase):
def testDataRangeNoPlot(self):
"""empty plot data range"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
for logX, logY in ((False, False),
(True, False),
@@ -104,8 +104,8 @@ class TestPlotRanges(ParametricTestCase):
(False, True),
(False, False)):
with self.subTest(logX=logX, logY=logY):
- plot.setXAxisLogarithmic(logX)
- plot.setYAxisLogarithmic(logY)
+ plot.getXAxis()._setLogarithmic(logX)
+ plot.getYAxis()._setLogarithmic(logY)
dataRange = plot.getDataRange()
self.assertIsNone(dataRange.x)
self.assertIsNone(dataRange.y)
@@ -114,7 +114,7 @@ class TestPlotRanges(ParametricTestCase):
def testDataRangeLeft(self):
"""left axis range"""
- plot = Plot(backend='none')
+ 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
@@ -130,8 +130,8 @@ class TestPlotRanges(ParametricTestCase):
(False, True),
(False, False)):
with self.subTest(logX=logX, logY=logY):
- plot.setXAxisLogarithmic(logX)
- plot.setYAxisLogarithmic(logY)
+ plot.getXAxis()._setLogarithmic(logX)
+ plot.getYAxis()._setLogarithmic(logY)
dataRange = plot.getDataRange()
xRange, yRange = self._getRanges([xData, yData],
[logX, logY])
@@ -142,7 +142,7 @@ class TestPlotRanges(ParametricTestCase):
def testDataRangeRight(self):
"""right axis range"""
- plot = Plot(backend='none')
+ 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,
@@ -156,8 +156,8 @@ class TestPlotRanges(ParametricTestCase):
(False, True),
(False, False)):
with self.subTest(logX=logX, logY=logY):
- plot.setXAxisLogarithmic(logX)
- plot.setYAxisLogarithmic(logY)
+ plot.getXAxis()._setLogarithmic(logX)
+ plot.getYAxis()._setLogarithmic(logY)
dataRange = plot.getDataRange()
xRange, yRange = self._getRanges([xData, yData],
[logX, logY])
@@ -172,7 +172,7 @@ class TestPlotRanges(ParametricTestCase):
scale = (3., 8.)
image = numpy.arange(100.).reshape(20, 5)
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
plot.addImage(image,
origin=origin, scale=scale)
@@ -190,8 +190,8 @@ class TestPlotRanges(ParametricTestCase):
(False, True),
(False, False)):
with self.subTest(logX=logX, logY=logY):
- plot.setXAxisLogarithmic(logX)
- plot.setYAxisLogarithmic(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),
@@ -203,7 +203,7 @@ class TestPlotRanges(ParametricTestCase):
def testDataRangeLeftRight(self):
"""right+left axis range"""
- plot = Plot(backend='none')
+ 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
@@ -225,8 +225,8 @@ class TestPlotRanges(ParametricTestCase):
(False, True),
(False, False)):
with self.subTest(logX=logX, logY=logY):
- plot.setXAxisLogarithmic(logX)
- plot.setYAxisLogarithmic(logY)
+ plot.getXAxis()._setLogarithmic(logX)
+ plot.getYAxis()._setLogarithmic(logY)
dataRange = plot.getDataRange()
xRangeL, yRangeL = self._getRanges([xData_l, yData_l],
[logX, logY])
@@ -244,7 +244,7 @@ class TestPlotRanges(ParametricTestCase):
# image sets x min and y max
# plot_left sets y min
# plot_right sets x max (and yright)
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
origin = (-10, 5)
scale = (3., 8.)
@@ -276,8 +276,8 @@ class TestPlotRanges(ParametricTestCase):
(False, True),
(False, False)):
with self.subTest(logX=logX, logY=logY):
- plot.setXAxisLogarithmic(logX)
- plot.setYAxisLogarithmic(logY)
+ plot.getXAxis()._setLogarithmic(logX)
+ plot.getYAxis()._setLogarithmic(logY)
dataRange = plot.getDataRange()
xRangeL, yRangeL = self._getRanges([xData_l, yData_l],
[logX, logY])
@@ -301,7 +301,7 @@ class TestPlotRanges(ParametricTestCase):
scale = (-3., 8.)
image = numpy.arange(100.).reshape(20, 5)
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
plot.addImage(image,
origin=origin, scale=scale)
@@ -320,8 +320,8 @@ class TestPlotRanges(ParametricTestCase):
(False, True),
(False, False)):
with self.subTest(logX=logX, logY=logY):
- plot.setXAxisLogarithmic(logX)
- plot.setYAxisLogarithmic(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),
@@ -337,7 +337,7 @@ class TestPlotRanges(ParametricTestCase):
scale = (3., -8.)
image = numpy.arange(100.).reshape(20, 5)
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
plot.addImage(image,
origin=origin, scale=scale)
@@ -356,8 +356,8 @@ class TestPlotRanges(ParametricTestCase):
(False, True),
(False, False)):
with self.subTest(logX=logX, logY=logY):
- plot.setXAxisLogarithmic(logX)
- plot.setYAxisLogarithmic(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),
@@ -368,7 +368,7 @@ class TestPlotRanges(ParametricTestCase):
def testDataRangeHiddenCurve(self):
"""curves with a hidden curve"""
- plot = Plot(backend='none')
+ 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()
@@ -384,9 +384,9 @@ class TestPlotGetCurveImage(unittest.TestCase):
"""Test of plot getCurve and getImage methods"""
def testGetCurve(self):
- """Plot.getCurve and Plot.getActiveCurve tests"""
+ """PlotWidget.getCurve and Plot.getActiveCurve tests"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
# No curve
curve = plot.getCurve()
@@ -423,9 +423,9 @@ class TestPlotGetCurveImage(unittest.TestCase):
self.assertIsNone(curve)
def testGetCurveOldApi(self):
- """old API Plot.getCurve and Plot.getActiveCurve tests"""
+ """old API PlotWidget.getCurve and Plot.getActiveCurve tests"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
# No curve
curve = plot.getCurve()
@@ -433,7 +433,7 @@ class TestPlotGetCurveImage(unittest.TestCase):
plot.setActiveCurveHandling(True)
x = numpy.arange(10.).astype(numpy.float32)
- y = x * x;
+ 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')
@@ -449,12 +449,12 @@ class TestPlotGetCurveImage(unittest.TestCase):
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')
+ self.assertTrue(numpy.allclose(yOut, 2 * x), 'curve 1 wrong y data')
def testGetImage(self):
- """Plot.getImage and Plot.getActiveImage tests"""
+ """PlotWidget.getImage and PlotWidget.getActiveImage tests"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
# No image
image = plot.getImage()
@@ -485,9 +485,9 @@ class TestPlotGetCurveImage(unittest.TestCase):
self.assertEqual(image.getLegend(), 'image 1')
def testGetImageOldApi(self):
- """Plot.getImage and Plot.getActiveImage old API tests"""
+ """PlotWidget.getImage and PlotWidget.getActiveImage old API tests"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
# No image
image = plot.getImage()
@@ -505,9 +505,9 @@ class TestPlotGetCurveImage(unittest.TestCase):
self.assertTrue(numpy.allclose(data, image), "image 0 data not correct")
def testGetAllImages(self):
- """Plot.getAllImages test"""
+ """PlotWidget.getAllImages test"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
# No image
images = plot.getAllImages()
@@ -530,7 +530,7 @@ class TestPlotAddScatter(unittest.TestCase):
def testAddGetScatter(self):
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
# No curve
scatter = plot._getItem(kind="scatter")
@@ -565,9 +565,9 @@ class TestPlotAddScatter(unittest.TestCase):
self.assertEqual(scatter1.getLegend(), 'scatter 1')
def testGetAllScatters(self):
- """Plot.getAllImages test"""
+ """PlotWidget.getAllImages test"""
- plot = Plot(backend='none')
+ plot = PlotWidget(backend='none')
scatters = plot._getItems(kind='scatter')
self.assertEqual(len(scatters), 0)
diff --git a/silx/gui/plot/test/testPlotWindow.py b/silx/gui/plot/test/testPlotWindow.py
index 5afd53a..24d840b 100644
--- a/silx/gui/plot/test/testPlotWindow.py
+++ b/silx/gui/plot/test/testPlotWindow.py
@@ -26,7 +26,7 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "27/06/2017"
import doctest
@@ -84,10 +84,10 @@ class TestPlotWindow(TestCaseQt):
self.plot.setLimits(1, 100, 1, 100)
checkList = [ # QAction, Plot state getter
- (self.plot.xAxisAutoScaleAction, self.plot.isXAxisAutoScale),
- (self.plot.yAxisAutoScaleAction, self.plot.isYAxisAutoScale),
- (self.plot.xAxisLogarithmicAction, self.plot.isXAxisLogarithmic),
- (self.plot.yAxisLogarithmicAction, self.plot.isYAxisLogarithmic),
+ (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),
]
@@ -121,9 +121,9 @@ class TestPlotWindow(TestCaseQt):
def testToolYAxisOrigin(self):
self.plot.toolBar()
self.plot.yAxisInvertedButton.setYAxisUpward()
- self.assertFalse(self.plot.isYAxisInverted())
+ self.assertFalse(self.plot.getYAxis().isInverted())
self.plot.yAxisInvertedButton.setYAxisDownward()
- self.assertTrue(self.plot.isYAxisInverted())
+ self.assertTrue(self.plot.getYAxis().isInverted())
def suite():
diff --git a/silx/gui/plot/test/testScatterMaskToolsWidget.py b/silx/gui/plot/test/testScatterMaskToolsWidget.py
index 8b5f2ad..178274a 100644
--- a/silx/gui/plot/test/testScatterMaskToolsWidget.py
+++ b/silx/gui/plot/test/testScatterMaskToolsWidget.py
@@ -26,7 +26,7 @@
__authors__ = ["T. Vincent", "P. Knobel"]
__license__ = "MIT"
-__date__ = "10/07/2017"
+__date__ = "01/09/2017"
import logging
@@ -37,8 +37,9 @@ import numpy
from silx.gui import qt
from silx.test.utils import temp_dir, ParametricTestCase
-from silx.gui.test.utils import TestCaseQt, getQToolButtonFromAction
+from silx.gui.test.utils import getQToolButtonFromAction
from silx.gui.plot import PlotWindow, ScatterMaskToolsWidget
+from .utils import PlotWidgetTestCase
try:
import fabio
@@ -46,34 +47,26 @@ except ImportError:
fabio = None
-logging.basicConfig()
_logger = logging.getLogger(__name__)
-class TestScatterMaskToolsWidget(TestCaseQt, ParametricTestCase):
+class TestScatterMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase):
"""Basic test for MaskToolsWidget"""
+ def _createPlot(self):
+ return PlotWindow()
+
def setUp(self):
super(TestScatterMaskToolsWidget, self).setUp()
- self.plot = PlotWindow()
-
self.widget = ScatterMaskToolsWidget.ScatterMaskToolsDockWidget(
plot=self.plot, name='TEST')
self.plot.addDockWidget(qt.Qt.BottomDockWidgetArea, self.widget)
- self.plot.show()
- self.qWaitForWindowExposed(self.plot)
-
self.maskWidget = self.widget.widget()
def tearDown(self):
del self.maskWidget
del self.widget
-
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- self.plot.close()
- del self.plot
-
super(TestScatterMaskToolsWidget, self).tearDown()
def testEmptyPlot(self):
@@ -86,7 +79,7 @@ class TestScatterMaskToolsWidget(TestCaseQt, ParametricTestCase):
def _drag(self):
"""Drag from plot center to offset position"""
- plot = self.plot.centralWidget()
+ plot = self.plot.getWidgetHandle()
xCenter, yCenter = plot.width() // 2, plot.height() // 2
offset = min(plot.width(), plot.height()) // 10
@@ -100,7 +93,7 @@ class TestScatterMaskToolsWidget(TestCaseQt, ParametricTestCase):
def _drawPolygon(self):
"""Draw a star polygon in the plot"""
- plot = self.plot.centralWidget()
+ plot = self.plot.getWidgetHandle()
x, y = plot.width() // 2, plot.height() // 2
offset = min(plot.width(), plot.height()) // 10
@@ -108,16 +101,17 @@ class TestScatterMaskToolsWidget(TestCaseQt, ParametricTestCase):
(x - offset, y - offset),
(x + offset, y),
(x - offset, y),
- (x + offset, y - offset)]
+ (x + offset, y - offset),
+ (x, y + offset)] # Close polygon
+ self.mouseMove(plot, pos=[0, 0])
for pos in star:
self.mouseMove(plot, pos=pos)
- btn = qt.Qt.LeftButton if pos != star[-1] else qt.Qt.RightButton
- self.mouseClick(plot, btn, pos=pos)
+ self.mouseClick(plot, qt.Qt.LeftButton, pos=pos)
def _drawPencil(self):
"""Draw a star polygon in the plot"""
- plot = self.plot.centralWidget()
+ plot = self.plot.getWidgetHandle()
x, y = plot.width() // 2, plot.height() // 2
offset = min(plot.width(), plot.height()) // 10
@@ -127,9 +121,10 @@ class TestScatterMaskToolsWidget(TestCaseQt, ParametricTestCase):
(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:
+ for pos in star[1:]:
self.mouseMove(plot, pos=pos)
self.mouseRelease(
plot, qt.Qt.LeftButton, pos=star[-1])
diff --git a/silx/gui/plot/test/testStackView.py b/silx/gui/plot/test/testStackView.py
index 69584cd..8d2a0ee 100644
--- a/silx/gui/plot/test/testStackView.py
+++ b/silx/gui/plot/test/testStackView.py
@@ -130,7 +130,7 @@ class TestStackView(TestCaseQt):
self.assertEqual(self.stackview._perspective, 2,
"Perspective not set in setStack(..., perspective=2).")
- def testTitle(self):
+ 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)])
@@ -156,6 +156,37 @@ class TestStackView(TestCaseQt):
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.")
+
class TestStackViewMainWindow(TestCaseQt):
"""Base class for tests of StackView."""
diff --git a/silx/gui/plot/test/testUtilsAxis.py b/silx/gui/plot/test/testUtilsAxis.py
new file mode 100644
index 0000000..6702b00
--- /dev/null
+++ b/silx/gui/plot/test/testUtilsAxis.py
@@ -0,0 +1,148 @@
+# 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__ = "04/08/2017"
+
+
+import unittest
+from silx.gui.plot import PlotWidget
+from silx.gui.plot.utils.axis import SyncAxes
+
+
+class TestAxisSync(unittest.TestCase):
+ """Tests AxisSync class"""
+
+ def setUp(self):
+ self.plot1 = PlotWidget()
+ self.plot2 = PlotWidget()
+ self.plot3 = PlotWidget()
+
+ def tearDown(self):
+ self.plot1 = None
+ self.plot2 = None
+ self.plot3 = None
+
+ 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 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 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
new file mode 100644
index 0000000..ef547c6
--- /dev/null
+++ b/silx/gui/plot/test/utils.py
@@ -0,0 +1,194 @@
+# 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__ = ["T. Vincent"]
+__license__ = "MIT"
+__date__ = "01/09/2017"
+
+
+import logging
+import contextlib
+
+from silx.gui.test.utils import TestCaseQt
+
+from silx.gui import qt
+from silx.gui.plot import PlotWidget
+from silx.gui.plot.backends.BackendMatplotlib import BackendMatplotlibQt
+
+
+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.
+ """
+
+ def __init__(self, methodName='runTest'):
+ TestCaseQt.__init__(self, methodName=methodName)
+ self.__mousePos = None
+
+ def _createPlot(self):
+ return PlotWidget()
+
+ 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):
+ self.qapp.processEvents()
+ self._waitForPlotClosed()
+ super(PlotWidgetTestCase, self).tearDown()
+
+ def _logMplEvents(self, event):
+ self.__mplEvents.append(event)
+
+ @contextlib.contextmanager
+ def _waitForMplEvent(self, plot, mplEventType):
+ """Check if an event was received by the MPL backend.
+
+ :param PlotWidget plot: A plot widget or a MPL plot backend
+ :param str mplEventType: MPL event type
+ :raises RuntimeError: When the event did not happen
+ """
+ self.__mplEvents = []
+ if isinstance(plot, BackendMatplotlibQt):
+ backend = plot
+ else:
+ backend = plot._backend
+
+ callbackId = backend.mpl_connect(mplEventType, self._logMplEvents)
+ received = False
+ yield
+ for _ in range(100):
+ if len(self.__mplEvents) > 0:
+ received = True
+ break
+ self.qWait(10)
+ backend.mpl_disconnect(callbackId)
+ del self.__mplEvents
+ if not received:
+ self.logScreenShot()
+ raise RuntimeError("MPL event %s expected but nothing received" % mplEventType)
+
+ def _haveMplEvent(self, widget, pos):
+ """Check if the widget at this position is a matplotlib widget."""
+ if isinstance(pos, qt.QPoint):
+ pass
+ else:
+ pos = qt.QPoint(pos[0], pos[1])
+ pos = widget.mapTo(widget.window(), pos)
+ target = widget.window().childAt(pos)
+
+ # Check if the target is a MPL container
+ backend = target
+ if hasattr(target, "_backend"):
+ backend = target._backend
+ haveEvent = isinstance(backend, BackendMatplotlibQt)
+ return haveEvent
+
+ def _patchPos(self, widget, pos):
+ """Return a real position relative to the widget.
+
+ If pos is None, the returned value is the center of the widget,
+ as the default behaviour of functions like QTest.mouseMove.
+ Else the position is returned as it is.
+ """
+ if pos is None:
+ pos = widget.size() / 2
+ pos = pos.width(), pos.height()
+ return pos
+
+ def _checkMouseMove(self, widget, pos):
+ """Returns true if the position differe from the current position of
+ the cursor"""
+ pos = qt.QPoint(pos[0], pos[1])
+ pos = widget.mapTo(widget.window(), pos)
+ willMove = pos != self.__mousePos
+ self.__mousePos = pos
+ return willMove
+
+ def mouseMove(self, widget, pos=None, delay=-1):
+ """Override TestCaseQt to wait while MPL did not reveive the expected
+ event"""
+ pos = self._patchPos(widget, pos)
+ willMove = self._checkMouseMove(widget, pos)
+ hadMplEvents = self._haveMplEvent(widget, self.__mousePos)
+ willHaveMplEvents = self._haveMplEvent(widget, pos)
+ if (not hadMplEvents and not willHaveMplEvents) or not willMove:
+ return TestCaseQt.mouseMove(self, widget, pos=pos, delay=delay)
+ with self._waitForMplEvent(widget, "motion_notify_event"):
+ TestCaseQt.mouseMove(self, widget, pos=pos, delay=delay)
+
+ def mouseClick(self, widget, button, modifier=None, pos=None, delay=-1):
+ """Override TestCaseQt to wait while MPL did not reveive the expected
+ event"""
+ pos = self._patchPos(widget, pos)
+ self._checkMouseMove(widget, pos)
+ if not self._haveMplEvent(widget, pos):
+ return TestCaseQt.mouseClick(self, widget, button, modifier=modifier, pos=pos, delay=delay)
+ with self._waitForMplEvent(widget, "button_release_event"):
+ TestCaseQt.mouseClick(self, widget, button, modifier=modifier, pos=pos, delay=delay)
+
+ def mousePress(self, widget, button, modifier=None, pos=None, delay=-1):
+ """Override TestCaseQt to wait while MPL did not reveive the expected
+ event"""
+ pos = self._patchPos(widget, pos)
+ self._checkMouseMove(widget, pos)
+ if not self._haveMplEvent(widget, pos):
+ return TestCaseQt.mousePress(self, widget, button, modifier=modifier, pos=pos, delay=delay)
+ with self._waitForMplEvent(widget, "button_press_event"):
+ TestCaseQt.mousePress(self, widget, button, modifier=modifier, pos=pos, delay=delay)
+
+ def mouseRelease(self, widget, button, modifier=None, pos=None, delay=-1):
+ """Override TestCaseQt to wait while MPL did not reveive the expected
+ event"""
+ pos = self._patchPos(widget, pos)
+ self._checkMouseMove(widget, pos)
+ if not self._haveMplEvent(widget, pos):
+ return TestCaseQt.mouseRelease(self, widget, button, modifier=modifier, pos=pos, delay=delay)
+ with self._waitForMplEvent(widget, "button_release_event"):
+ TestCaseQt.mouseRelease(self, widget, button, modifier=modifier, pos=pos, delay=delay)