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__.py25
-rw-r--r--silx/gui/plot/test/testColorBar.py12
-rw-r--r--silx/gui/plot/test/testColormap.py353
-rw-r--r--silx/gui/plot/test/testColormapDialog.py385
-rw-r--r--silx/gui/plot/test/testColors.py94
-rw-r--r--silx/gui/plot/test/testCurvesROIWidget.py24
-rw-r--r--silx/gui/plot/test/testImageView.py4
-rw-r--r--silx/gui/plot/test/testLimitConstraints.py6
-rw-r--r--silx/gui/plot/test/testPixelIntensityHistoAction.py104
-rw-r--r--silx/gui/plot/test/testPlotTools.py200
-rw-r--r--silx/gui/plot/test/testPlotWidget.py71
-rw-r--r--silx/gui/plot/test/testPlotWidgetNoBackend.py12
-rw-r--r--silx/gui/plot/test/testSaveAction.py40
-rw-r--r--silx/gui/plot/test/testScatterView.py115
-rw-r--r--silx/gui/plot/test/testStackView.py15
-rw-r--r--silx/gui/plot/test/testStats.py561
-rw-r--r--silx/gui/plot/test/utils.py7
17 files changed, 923 insertions, 1105 deletions
diff --git a/silx/gui/plot/test/__init__.py b/silx/gui/plot/test/__init__.py
index 154a70a..1428bad 100644
--- a/silx/gui/plot/test/__init__.py
+++ b/silx/gui/plot/test/__init__.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
+# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -24,24 +24,21 @@
# ###########################################################################*/
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "28/11/2017"
+__date__ = "24/04/2018"
import unittest
from .._utils import test
from . import testColorBar
-from . import testColormap
-from . import testColormapDialog
-from . import testColors
from . import testCurvesROIWidget
+from . import testStats
from . import testAlphaSlider
from . import testInteraction
from . import testLegendSelector
from . import testMaskToolsWidget
from . import testScatterMaskToolsWidget
from . import testPlotInteraction
-from . import testPlotTools
from . import testPlotWidgetNoBackend
from . import testPlotWidget
from . import testPlotWindow
@@ -53,16 +50,21 @@ from . import testLimitConstraints
from . import testComplexImageView
from . import testImageView
from . import testSaveAction
+from . import testScatterView
+from . import testPixelIntensityHistoAction
def suite():
+ # Lazy-loading to avoid cyclic reference
+ from ..tools import test as testTools
+
test_suite = unittest.TestSuite()
test_suite.addTests(
[test.suite(),
+ testTools.suite(),
testColorBar.suite(),
- testColors.suite(),
- testColormapDialog.suite(),
testCurvesROIWidget.suite(),
+ testStats.suite(),
testAlphaSlider.suite(),
testInteraction.suite(),
testLegendSelector.suite(),
@@ -70,16 +72,17 @@ def 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(),
testImageView.suite(),
- testSaveAction.suite()])
+ testSaveAction.suite(),
+ testScatterView.suite(),
+ testPixelIntensityHistoAction.suite()
+ ])
return test_suite
diff --git a/silx/gui/plot/test/testColorBar.py b/silx/gui/plot/test/testColorBar.py
index 80ae6a8..0d1c952 100644
--- a/silx/gui/plot/test/testColorBar.py
+++ b/silx/gui/plot/test/testColorBar.py
@@ -26,13 +26,13 @@
__authors__ = ["H. Payno"]
__license__ = "MIT"
-__date__ = "11/04/2017"
+__date__ = "24/04/2018"
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.colors import Colormap
from silx.gui.plot import Plot2D
from silx.gui import qt
import numpy
@@ -64,7 +64,7 @@ class TestColorScale(TestCaseQt):
vmin=0.0,
vmax=1.0)
self.colorScaleWidget.setColormap(self.colorMapLin1)
-
+
self.assertTrue(
self.colorScaleWidget.getValueFromRelativePosition(0.25) == 0.25)
self.assertTrue(
@@ -77,7 +77,7 @@ class TestColorScale(TestCaseQt):
vmin=-10,
vmax=0)
self.colorScaleWidget.setColormap(self.colorMapLin2)
-
+
self.assertTrue(
self.colorScaleWidget.getValueFromRelativePosition(0.25) == -7.5)
self.assertTrue(
@@ -98,7 +98,7 @@ class TestColorScale(TestCaseQt):
val = self.colorScaleWidget.getValueFromRelativePosition(0.5)
self.assertTrue(val == 10.0)
-
+
val = self.colorScaleWidget.getValueFromRelativePosition(0.0)
self.assertTrue(val == 1.0)
@@ -225,7 +225,7 @@ class TestColorBarWidget(TestCaseQt):
self.assertTrue(self.colorBar.getColorScaleBar().maxVal == 30)
# if data is positive
- data[data<1] = data.max()
+ data[data < 1] = data.max()
self.plot.addImage(data=data,
colormap=colormapLog,
legend='toto',
diff --git a/silx/gui/plot/test/testColormap.py b/silx/gui/plot/test/testColormap.py
deleted file mode 100644
index 4888a7c..0000000
--- a/silx/gui/plot/test/testColormap.py
+++ /dev/null
@@ -1,353 +0,0 @@
-# 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__ = "17/01/2018"
-
-import unittest
-import numpy
-from silx.utils.testutils import ParametricTestCase
-from silx.gui.plot.Colormap import Colormap
-from silx.gui.plot.Colormap import preferredColormaps, setPreferredColormaps
-from silx.utils.exceptions import NotEditableError
-
-
-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):
- Colormap._fromDict(clm_dict)
-
-
-class TestObjectAPI(ParametricTestCase):
- """Test the new Object API of the colormap"""
- 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 testGetNColors(self):
- """Test getNColors method"""
- # specific LUT
- colormap = Colormap(name=None,
- colors=((0, 0, 0), (1, 1, 1)),
- vmin=1000,
- vmax=2000)
- colors = colormap.getNColors()
- self.assertTrue(numpy.all(numpy.equal(
- colors,
- ((0, 0, 0, 255), (255, 255, 255, 255)))))
-
- def testEditableMode(self):
- """Make sure the colormap will raise NotEditableError when try to
- change a colormap not editable"""
- colormap = Colormap()
- colormap.setEditable(False)
- with self.assertRaises(NotEditableError):
- colormap.setVRange(0., 1.)
- with self.assertRaises(NotEditableError):
- colormap.setVMin(1.)
- with self.assertRaises(NotEditableError):
- colormap.setVMax(1.)
- with self.assertRaises(NotEditableError):
- colormap.setNormalization(Colormap.LOGARITHM)
- with self.assertRaises(NotEditableError):
- colormap.setName('magma')
- with self.assertRaises(NotEditableError):
- colormap.setColormapLUT(numpy.array([0, 1]))
- with self.assertRaises(NotEditableError):
- colormap._setFromDict(colormap._toDict())
- state = colormap.saveState()
- with self.assertRaises(NotEditableError):
- colormap.restoreState(state)
-
-
-class TestPreferredColormaps(unittest.TestCase):
- """Test get|setPreferredColormaps functions"""
-
- def setUp(self):
- # Save preferred colormaps
- self._colormaps = preferredColormaps()
-
- def tearDown(self):
- # Restore saved preferred colormaps
- setPreferredColormaps(self._colormaps)
-
- def test(self):
- colormaps = 'viridis', 'magma'
-
- setPreferredColormaps(colormaps)
- self.assertEqual(preferredColormaps(), colormaps)
-
- with self.assertRaises(ValueError):
- setPreferredColormaps(())
-
- with self.assertRaises(ValueError):
- setPreferredColormaps(('This is not a colormap',))
-
- colormaps = 'red', 'green'
- setPreferredColormaps(('This is not a colormap',) + colormaps)
- self.assertEqual(preferredColormaps(), colormaps)
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for ui in (TestDictAPI, TestObjectAPI, TestPreferredColormaps):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(ui))
-
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testColormapDialog.py b/silx/gui/plot/test/testColormapDialog.py
deleted file mode 100644
index 8087369..0000000
--- a/silx/gui/plot/test/testColormapDialog.py
+++ /dev/null
@@ -1,385 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-# ###########################################################################*/
-"""Basic tests for ColormapDialog"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "17/01/2018"
-
-
-import doctest
-import unittest
-
-from silx.gui.test.utils import qWaitForWindowExposedAndActivate
-from silx.gui import qt
-from silx.gui.plot import ColormapDialog
-from silx.gui.test.utils import TestCaseQt
-from silx.gui.plot.Colormap import Colormap, preferredColormaps
-from silx.utils.testutils import ParametricTestCase
-from silx.gui.plot.PlotWindow import PlotWindow
-
-import numpy.random
-
-
-# Makes sure a QApplication exists
-_qapp = qt.QApplication.instance() or qt.QApplication([])
-
-
-def _tearDownQt(docTest):
- """Tear down to use for test from docstring.
-
- Checks that dialog widget is displayed
- """
- dialogWidget = docTest.globs['dialog']
- qWaitForWindowExposedAndActivate(dialogWidget)
- dialogWidget.setAttribute(qt.Qt.WA_DeleteOnClose)
- dialogWidget.close()
- del dialogWidget
- _qapp.processEvents()
-
-
-cmapDocTestSuite = doctest.DocTestSuite(ColormapDialog, tearDown=_tearDownQt)
-"""Test suite of tests from the module's docstrings."""
-
-
-class TestColormapDialog(TestCaseQt, ParametricTestCase):
- """Test the ColormapDialog."""
- def setUp(self):
- TestCaseQt.setUp(self)
- ParametricTestCase.setUp(self)
- self.colormap = Colormap(name='gray', vmin=10.0, vmax=20.0,
- normalization='linear')
-
- self.colormapDiag = ColormapDialog.ColormapDialog()
- self.colormapDiag.setAttribute(qt.Qt.WA_DeleteOnClose)
-
- def tearDown(self):
- del self.colormapDiag
- ParametricTestCase.tearDown(self)
- TestCaseQt.tearDown(self)
-
- def testGUIEdition(self):
- """Make sure the colormap is correctly edited and also that the
- modification are correctly updated if an other colormapdialog is
- editing the same colormap"""
- colormapDiag2 = ColormapDialog.ColormapDialog()
- colormapDiag2.setColormap(self.colormap)
- self.colormapDiag.setColormap(self.colormap)
-
- self.colormapDiag._comboBoxColormap.setCurrentName('red')
- self.colormapDiag._normButtonLog.setChecked(True)
- self.assertTrue(self.colormap.getName() == 'red')
- self.assertTrue(self.colormapDiag.getColormap().getName() == 'red')
- self.assertTrue(self.colormap.getNormalization() == 'log')
- self.assertTrue(self.colormap.getVMin() == 10)
- self.assertTrue(self.colormap.getVMax() == 20)
- # checked second colormap dialog
- self.assertTrue(colormapDiag2._comboBoxColormap.getCurrentName() == 'red')
- self.assertTrue(colormapDiag2._normButtonLog.isChecked())
- self.assertTrue(int(colormapDiag2._minValue.getValue()) == 10)
- self.assertTrue(int(colormapDiag2._maxValue.getValue()) == 20)
- colormapDiag2.close()
-
- def testGUIModalOk(self):
- """Make sure the colormap is modified if gone through accept"""
- assert self.colormap.isAutoscale() is False
- self.colormapDiag.setModal(True)
- self.colormapDiag.show()
- self.colormapDiag.setColormap(self.colormap)
- self.assertTrue(self.colormap.getVMin() is not None)
- self.colormapDiag._minValue.setValue(None)
- self.assertTrue(self.colormap.getVMin() is None)
- self.colormapDiag._maxValue.setValue(None)
- self.mouseClick(
- widget=self.colormapDiag._buttonsModal.button(qt.QDialogButtonBox.Ok),
- button=qt.Qt.LeftButton
- )
- self.assertTrue(self.colormap.getVMin() is None)
- self.assertTrue(self.colormap.getVMax() is None)
- self.assertTrue(self.colormap.isAutoscale() is True)
-
- def testGUIModalCancel(self):
- """Make sure the colormap is not modified if gone through reject"""
- assert self.colormap.isAutoscale() is False
- self.colormapDiag.setModal(True)
- self.colormapDiag.show()
- self.colormapDiag.setColormap(self.colormap)
- self.assertTrue(self.colormap.getVMin() is not None)
- self.colormapDiag._minValue.setValue(None)
- self.assertTrue(self.colormap.getVMin() is None)
- self.mouseClick(
- widget=self.colormapDiag._buttonsModal.button(qt.QDialogButtonBox.Cancel),
- button=qt.Qt.LeftButton
- )
- self.assertTrue(self.colormap.getVMin() is not None)
-
- def testGUIModalClose(self):
- assert self.colormap.isAutoscale() is False
- self.colormapDiag.setModal(False)
- self.colormapDiag.show()
- self.colormapDiag.setColormap(self.colormap)
- self.assertTrue(self.colormap.getVMin() is not None)
- self.colormapDiag._minValue.setValue(None)
- self.assertTrue(self.colormap.getVMin() is None)
- self.mouseClick(
- widget=self.colormapDiag._buttonsNonModal.button(qt.QDialogButtonBox.Close),
- button=qt.Qt.LeftButton
- )
- self.assertTrue(self.colormap.getVMin() is None)
-
- def testGUIModalReset(self):
- assert self.colormap.isAutoscale() is False
- self.colormapDiag.setModal(False)
- self.colormapDiag.show()
- self.colormapDiag.setColormap(self.colormap)
- self.assertTrue(self.colormap.getVMin() is not None)
- self.colormapDiag._minValue.setValue(None)
- self.assertTrue(self.colormap.getVMin() is None)
- self.mouseClick(
- widget=self.colormapDiag._buttonsNonModal.button(qt.QDialogButtonBox.Reset),
- button=qt.Qt.LeftButton
- )
- self.assertTrue(self.colormap.getVMin() is not None)
- self.colormapDiag.close()
-
- def testGUIClose(self):
- """Make sure the colormap is modify if go through reject"""
- assert self.colormap.isAutoscale() is False
- self.colormapDiag.show()
- self.colormapDiag.setColormap(self.colormap)
- self.assertTrue(self.colormap.getVMin() is not None)
- self.colormapDiag._minValue.setValue(None)
- self.assertTrue(self.colormap.getVMin() is None)
- self.colormapDiag.close()
- self.assertTrue(self.colormap.getVMin() is None)
-
- def testSetColormapIsCorrect(self):
- """Make sure the interface fir the colormap when set a new colormap"""
- self.colormap.setName('red')
- for norm in (Colormap.NORMALIZATIONS):
- for autoscale in (True, False):
- if autoscale is True:
- self.colormap.setVRange(None, None)
- else:
- self.colormap.setVRange(11, 101)
- self.colormap.setNormalization(norm)
- with self.subTest(colormap=self.colormap):
- self.colormapDiag.setColormap(self.colormap)
- self.assertTrue(
- self.colormapDiag._normButtonLinear.isChecked() == (norm is Colormap.LINEAR))
- self.assertTrue(
- self.colormapDiag._comboBoxColormap.getCurrentName() == 'red')
- self.assertTrue(
- self.colormapDiag._minValue.isAutoChecked() == autoscale)
- self.assertTrue(
- self.colormapDiag._maxValue.isAutoChecked() == autoscale)
- if autoscale is False:
- self.assertTrue(self.colormapDiag._minValue.getValue() == 11)
- self.assertTrue(self.colormapDiag._maxValue.getValue() == 101)
- self.assertTrue(self.colormapDiag._minValue.isEnabled())
- self.assertTrue(self.colormapDiag._maxValue.isEnabled())
- else:
- self.assertFalse(self.colormapDiag._minValue._numVal.isEnabled())
- self.assertFalse(self.colormapDiag._maxValue._numVal.isEnabled())
-
- def testColormapDel(self):
- """Check behavior if the colormap has been deleted outside. For now
- we make sure the colormap is still running and nothing more"""
- self.colormapDiag.setColormap(self.colormap)
- self.colormapDiag.show()
- del self.colormap
- self.assertTrue(self.colormapDiag.getColormap() is None)
- self.colormapDiag._comboBoxColormap.setCurrentName('blue')
-
- def testColormapEditedOutside(self):
- """Make sure the GUI is still up to date if the colormap is modified
- outside"""
- self.colormapDiag.setColormap(self.colormap)
- self.colormapDiag.show()
-
- self.colormap.setName('red')
- self.assertTrue(
- self.colormapDiag._comboBoxColormap.getCurrentName() == 'red')
- self.colormap.setNormalization(Colormap.LOGARITHM)
- self.assertFalse(self.colormapDiag._normButtonLinear.isChecked())
- self.colormap.setVRange(11, 201)
- self.assertTrue(self.colormapDiag._minValue.getValue() == 11)
- self.assertTrue(self.colormapDiag._maxValue.getValue() == 201)
- self.assertTrue(self.colormapDiag._minValue._numVal.isEnabled())
- self.assertTrue(self.colormapDiag._maxValue._numVal.isEnabled())
- self.assertFalse(self.colormapDiag._minValue.isAutoChecked())
- self.assertFalse(self.colormapDiag._maxValue.isAutoChecked())
- self.colormap.setVRange(None, None)
- self.assertFalse(self.colormapDiag._minValue._numVal.isEnabled())
- self.assertFalse(self.colormapDiag._maxValue._numVal.isEnabled())
- self.assertTrue(self.colormapDiag._minValue.isAutoChecked())
- self.assertTrue(self.colormapDiag._maxValue.isAutoChecked())
-
- def testSetColormapScenario(self):
- """Test of a simple scenario of a colormap dialog editing several
- colormap"""
- colormap1 = Colormap(name='gray', vmin=10.0, vmax=20.0,
- normalization='linear')
- colormap2 = Colormap(name='red', vmin=10.0, vmax=20.0,
- normalization='log')
- colormap3 = Colormap(name='blue', vmin=None, vmax=None,
- normalization='linear')
- self.colormapDiag.setColormap(self.colormap)
- self.colormapDiag.setColormap(colormap1)
- del colormap1
- self.colormapDiag.setColormap(colormap2)
- del colormap2
- self.colormapDiag.setColormap(colormap3)
- del colormap3
-
- def testNotPreferredColormap(self):
- """Test that the colormapEditor is able to edit a colormap which is not
- part of the 'prefered colormap'
- """
- def getFirstNotPreferredColormap():
- cms = Colormap.getSupportedColormaps()
- preferred = preferredColormaps()
- for cm in cms:
- if cm not in preferred:
- return cm
- return None
-
- colormapName = getFirstNotPreferredColormap()
- assert colormapName is not None
- colormap = Colormap(name=colormapName)
- self.colormapDiag.setColormap(colormap)
- self.colormapDiag.show()
- cb = self.colormapDiag._comboBoxColormap
- self.assertTrue(cb.getCurrentName() == colormapName)
- cb.setCurrentIndex(0)
- index = cb.findColormap(colormapName)
- assert index is not 0 # if 0 then the rest of the test has no sense
- cb.setCurrentIndex(index)
- self.assertTrue(cb.getCurrentName() == colormapName)
-
- def testColormapEditableMode(self):
- """Test that the colormapDialog is correctly updated when changing the
- colormap editable status"""
- colormap = Colormap(normalization='linear', vmin=1.0, vmax=10.0)
- self.colormapDiag.setColormap(colormap)
- for editable in (True, False):
- with self.subTest(editable=editable):
- colormap.setEditable(editable)
- self.assertTrue(
- self.colormapDiag._comboBoxColormap.isEnabled() is editable)
- self.assertTrue(
- self.colormapDiag._minValue.isEnabled() is editable)
- self.assertTrue(
- self.colormapDiag._maxValue.isEnabled() is editable)
- self.assertTrue(
- self.colormapDiag._normButtonLinear.isEnabled() is editable)
- self.assertTrue(
- self.colormapDiag._normButtonLog.isEnabled() is editable)
-
- # Make sure the reset button is also set to enable when edition mode is
- # False
- self.colormapDiag.setModal(False)
- colormap.setEditable(True)
- self.colormapDiag._normButtonLog.setChecked(True)
- resetButton = self.colormapDiag._buttonsNonModal.button(qt.QDialogButtonBox.Reset)
- self.assertTrue(resetButton.isEnabled())
- colormap.setEditable(False)
- self.assertFalse(resetButton.isEnabled())
-
-
-class TestColormapAction(TestCaseQt):
- def setUp(self):
- TestCaseQt.setUp(self)
- self.plot = PlotWindow()
- self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
-
- self.colormap1 = Colormap(name='blue', vmin=0.0, vmax=1.0,
- normalization='linear')
- self.colormap2 = Colormap(name='red', vmin=10.0, vmax=100.0,
- normalization='log')
- self.defaultColormap = self.plot.getDefaultColormap()
-
- self.plot.getColormapAction()._actionTriggered(checked=True)
- self.colormapDialog = self.plot.getColormapAction()._dialog
- self.colormapDialog.setAttribute(qt.Qt.WA_DeleteOnClose)
-
- def tearDown(self):
- self.colormapDialog.close()
- self.plot.close()
- del self.colormapDialog
- del self.plot
- TestCaseQt.tearDown(self)
-
- def testActiveColormap(self):
- self.assertTrue(self.colormapDialog.getColormap() is self.defaultColormap)
-
- self.plot.addImage(data=numpy.random.rand(10, 10), legend='img1',
- replace=False, origin=(0, 0),
- colormap=self.colormap1)
- self.plot.setActiveImage('img1')
- self.assertTrue(self.colormapDialog.getColormap() is self.colormap1)
-
- self.plot.addImage(data=numpy.random.rand(10, 10), legend='img2',
- replace=False, origin=(0, 0),
- colormap=self.colormap2)
- self.plot.addImage(data=numpy.random.rand(10, 10), legend='img3',
- replace=False, origin=(0, 0))
-
- self.plot.setActiveImage('img3')
- self.assertTrue(self.colormapDialog.getColormap() is self.defaultColormap)
- self.plot.getActiveImage().setColormap(self.colormap2)
- self.assertTrue(self.colormapDialog.getColormap() is self.colormap2)
-
- self.plot.remove('img2')
- self.plot.remove('img3')
- self.plot.remove('img1')
- self.assertTrue(self.colormapDialog.getColormap() is self.defaultColormap)
-
- def testShowHideColormapDialog(self):
- self.plot.getColormapAction()._actionTriggered(checked=False)
- self.assertFalse(self.plot.getColormapAction().isChecked())
- self.plot.getColormapAction()._actionTriggered(checked=True)
- self.assertTrue(self.plot.getColormapAction().isChecked())
- self.plot.addImage(data=numpy.random.rand(10, 10), legend='img1',
- replace=False, origin=(0, 0),
- colormap=self.colormap1)
- self.colormap1.setName('red')
- self.plot.getColormapAction()._actionTriggered()
- self.colormap1.setName('blue')
- self.colormapDialog.close()
- self.assertFalse(self.plot.getColormapAction().isChecked())
-
-
-def suite():
- test_suite = unittest.TestSuite()
- test_suite.addTest(cmapDocTestSuite)
- for testClass in (TestColormapDialog, TestColormapAction):
- test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(
- testClass))
- 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
deleted file mode 100644
index 4d617eb..0000000
--- a/silx/gui/plot/test/testColors.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-# ###########################################################################*/
-"""Basic tests for Colors"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "17/01/2018"
-
-
-import numpy
-
-import unittest
-from silx.utils.testutils import ParametricTestCase
-
-from silx.gui.plot import Colors
-from silx.gui.plot.Colormap import Colormap
-
-class TestRGBA(ParametricTestCase):
- """Basic tests of rgba function"""
-
- def testRGBA(self):
- """"Test rgba function with accepted values"""
- tests = { # name: (colors, expected values)
- 'blue': ('blue', (0., 0., 1., 1.)),
- '#010203': ('#010203', (1. / 255., 2. / 255., 3. / 255., 1.)),
- '#01020304': ('#01020304', (1. / 255., 2. / 255., 3. / 255., 4. / 255.)),
- '3 x uint8': (numpy.array((1, 255, 0), dtype=numpy.uint8),
- (1 / 255., 1., 0., 1.)),
- '4 x uint8': (numpy.array((1, 255, 0, 1), dtype=numpy.uint8),
- (1 / 255., 1., 0., 1 / 255.)),
- '3 x float overflow': ((3., 0.5, 1.), (1., 0.5, 1., 1.)),
- }
-
- for name, test in tests.items():
- color, expected = test
- with self.subTest(msg=name):
- result = Colors.rgba(color)
- self.assertEqual(result, expected)
-
-
-class TestApplyColormapToData(ParametricTestCase):
- """Tests of applyColormapToData function"""
-
- def testApplyColormapToData(self):
- """Simple test of applyColormapToData function"""
- colormap = Colormap(name='gray', normalization='linear',
- vmin=0, vmax=255)
-
- size = 10
- expected = numpy.empty((size, 4), dtype='uint8')
- expected[:, 0] = numpy.arange(size, dtype='uint8')
- expected[:, 1] = expected[:, 0]
- expected[:, 2] = expected[:, 0]
- expected[:, 3] = 255
-
- for dtype in ('uint8', 'int32', 'float32', 'float64'):
- with self.subTest(dtype=dtype):
- array = numpy.arange(size, dtype=dtype)
- result = colormap.applyToData(data=array)
- self.assertTrue(numpy.all(numpy.equal(result, expected)))
-
-
-def suite():
- test_suite = unittest.TestSuite()
- for testClass in (TestRGBA, TestApplyColormapToData):
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(testClass))
- 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 0fd2456..7a2e3d1 100644
--- a/silx/gui/plot/test/testCurvesROIWidget.py
+++ b/silx/gui/plot/test/testCurvesROIWidget.py
@@ -24,7 +24,7 @@
# ###########################################################################*/
"""Basic tests for CurvesROIWidget"""
-__authors__ = ["T. Vincent", "P. Knobel"]
+__authors__ = ["T. Vincent", "P. Knobel", "H. Payno"]
__license__ = "MIT"
__date__ = "16/11/2017"
@@ -32,9 +32,8 @@ __date__ = "16/11/2017"
import logging
import os.path
import unittest
-
+from collections import OrderedDict
import numpy
-
from silx.gui import qt
from silx.test.utils import temp_dir
from silx.gui.test.utils import TestCaseQt
@@ -153,6 +152,25 @@ class TestCurvesROIWidget(TestCaseQt):
self.assertEqual(output["negative"]["rawcounts"],
y[selection].sum(), "Calculation failed on negative X coordinates")
+ def testDeferedInit(self):
+ x = numpy.arange(100.)
+ y = numpy.arange(100.)
+ self.plot.addCurve(x=x, y=y, legend="name", replace="True")
+ roisDefs = OrderedDict([
+ ["range1",
+ OrderedDict([["from", 20], ["to", 200], ["type", "energy"]])],
+ ["range2",
+ OrderedDict([["from", 300], ["to", 500], ["type", "energy"]])]
+ ])
+
+ roiWidget = self.plot.getCurvesRoiDockWidget().roiWidget
+ self.assertFalse(roiWidget._isInit)
+ self.plot.getCurvesRoiDockWidget().setRois(roisDefs)
+ self.assertTrue(len(roiWidget.getRois()) is len(roisDefs))
+ self.plot.getCurvesRoiDockWidget().setVisible(True)
+ self.assertTrue(len(roiWidget.getRois()) is len(roisDefs))
+
+
def suite():
test_suite = unittest.TestSuite()
for TestClass in (TestCurvesROIWidget,):
diff --git a/silx/gui/plot/test/testImageView.py b/silx/gui/plot/test/testImageView.py
index 641d438..5059a0b 100644
--- a/silx/gui/plot/test/testImageView.py
+++ b/silx/gui/plot/test/testImageView.py
@@ -26,7 +26,7 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "22/09/2017"
+__date__ = "24/04/2018"
import unittest
@@ -36,7 +36,7 @@ from silx.gui import qt
from silx.gui.test.utils import TestCaseQt
from silx.gui.plot import ImageView
-from silx.gui.plot.Colormap import Colormap
+from silx.gui.colors import Colormap
class TestImageView(TestCaseQt):
diff --git a/silx/gui/plot/test/testLimitConstraints.py b/silx/gui/plot/test/testLimitConstraints.py
index 94aae76..5e7e0b1 100644
--- a/silx/gui/plot/test/testLimitConstraints.py
+++ b/silx/gui/plot/test/testLimitConstraints.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016 European Synchrotron Radiation Facility
+# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -44,9 +44,9 @@ class TestLimitConstaints(unittest.TestCase):
def testApi(self):
"""Test availability of the API"""
- self.plot.getXAxis().setLimitsConstraints(minPos=1, maxPos=1)
+ self.plot.getXAxis().setLimitsConstraints(minPos=1, maxPos=10)
self.plot.getXAxis().setRangeConstraints(minRange=1, maxRange=1)
- self.plot.getYAxis().setLimitsConstraints(minPos=1, maxPos=1)
+ self.plot.getYAxis().setLimitsConstraints(minPos=1, maxPos=10)
self.plot.getYAxis().setRangeConstraints(minRange=1, maxRange=1)
def testXMinMax(self):
diff --git a/silx/gui/plot/test/testPixelIntensityHistoAction.py b/silx/gui/plot/test/testPixelIntensityHistoAction.py
new file mode 100644
index 0000000..987e5b2
--- /dev/null
+++ b/silx/gui/plot/test/testPixelIntensityHistoAction.py
@@ -0,0 +1,104 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ###########################################################################*/
+"""Basic tests for PixelIntensitiesHistoAction"""
+
+__authors__ = ["T. Vincent"]
+__license__ = "MIT"
+__date__ = "02/03/2018"
+
+
+import numpy
+import unittest
+
+from silx.utils.testutils import ParametricTestCase
+from silx.gui.test.utils import TestCaseQt, getQToolButtonFromAction
+from silx.gui import qt
+from silx.gui.plot import Plot2D
+
+
+class TestPixelIntensitiesHisto(TestCaseQt, ParametricTestCase):
+ """Tests for PixelIntensitiesHistoAction widget."""
+
+ def setUp(self):
+ super(TestPixelIntensitiesHisto, self).setUp()
+ self.image = numpy.random.rand(100, 100)
+ self.plotImage = Plot2D()
+ self.plotImage.getIntensityHistogramAction().setVisible(True)
+
+ def tearDown(self):
+ del self.plotImage
+ super(TestPixelIntensitiesHisto, self).tearDown()
+
+ def testShowAndHide(self):
+ """Simple test that the plot is showing and hiding when activating the
+ action"""
+ self.plotImage.addImage(self.image, origin=(0, 0), legend='sino')
+ self.plotImage.show()
+
+ histoAction = self.plotImage.getIntensityHistogramAction()
+
+ # test the pixel intensity diagram is showing
+ button = getQToolButtonFromAction(histoAction)
+ self.assertIsNot(button, None)
+ self.mouseMove(button)
+ self.mouseClick(button, qt.Qt.LeftButton)
+ self.qapp.processEvents()
+ self.assertTrue(histoAction.getHistogramPlotWidget().isVisible())
+
+ # test the pixel intensity diagram is hiding
+ self.qapp.setActiveWindow(self.plotImage)
+ self.qapp.processEvents()
+ self.mouseMove(button)
+ self.mouseClick(button, qt.Qt.LeftButton)
+ self.qapp.processEvents()
+ self.assertFalse(histoAction.getHistogramPlotWidget().isVisible())
+
+ def testImageFormatInput(self):
+ """Test multiple type as image input"""
+ typesToTest = [numpy.uint8, numpy.int8, numpy.int16, numpy.int32,
+ numpy.float32, numpy.float64]
+ self.plotImage.addImage(self.image, origin=(0, 0), legend='sino')
+ self.plotImage.show()
+ button = getQToolButtonFromAction(
+ self.plotImage.getIntensityHistogramAction())
+ self.mouseMove(button)
+ self.mouseClick(button, qt.Qt.LeftButton)
+ self.qapp.processEvents()
+ for typeToTest in typesToTest:
+ with self.subTest(typeToTest=typeToTest):
+ self.plotImage.addImage(self.image.astype(typeToTest),
+ origin=(0, 0), legend='sino')
+
+
+def suite():
+ test_suite = unittest.TestSuite()
+ test_suite.addTest(
+ unittest.defaultTestLoader.loadTestsFromTestCase(
+ TestPixelIntensitiesHisto))
+ return test_suite
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testPlotTools.py b/silx/gui/plot/test/testPlotTools.py
deleted file mode 100644
index 3d5849f..0000000
--- a/silx/gui/plot/test/testPlotTools.py
+++ /dev/null
@@ -1,200 +0,0 @@
-# coding: utf-8
-# /*##########################################################################
-#
-# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-#
-# ###########################################################################*/
-"""Basic tests for PlotTools"""
-
-__authors__ = ["T. Vincent"]
-__license__ = "MIT"
-__date__ = "17/01/2018"
-
-
-import numpy
-import unittest
-
-from silx.utils.testutils import ParametricTestCase, TestLogging
-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
-_qapp = qt.QApplication.instance() or qt.QApplication([])
-
-
-def _tearDownDocTest(docTest):
- """Tear down to use for test from docstring.
-
- Checks that plot widget is displayed
- """
- plot = docTest.globs['plot']
- qWaitForWindowExposedAndActivate(plot)
- plot.setAttribute(qt.Qt.WA_DeleteOnClose)
- plot.close()
- del plot
-
-# Disable doctest because of
-# "NameError: name 'numpy' is not defined"
-#
-# import doctest
-# positionInfoTestSuite = doctest.DocTestSuite(
-# PlotTools, tearDown=_tearDownDocTest,
-# optionflags=doctest.ELLIPSIS)
-# """Test suite of tests from PlotTools docstrings.
-#
-# Test PositionInfo and ProfileToolBar docstrings.
-# """
-
-
-class TestPositionInfo(PlotWidgetTestCase):
- """Tests for PositionInfo widget."""
-
- def _createPlot(self):
- return PlotWindow()
-
- def setUp(self):
- super(TestPositionInfo, self).setUp()
- self.mouseMove(self.plot, pos=(0, 0))
- self.qapp.processEvents()
- self.qWait(100)
-
- def tearDown(self):
- super(TestPositionInfo, self).tearDown()
-
- def _test(self, positionWidget, converterNames, **kwargs):
- """General test of PositionInfo.
-
- - Add it to a toolbar and
- - Move mouse around the center of the PlotWindow.
- """
- toolBar = qt.QToolBar()
- self.plot.addToolBar(qt.Qt.BottomToolBarArea, toolBar)
-
- toolBar.addWidget(positionWidget)
-
- converters = positionWidget.getConverters()
- self.assertEqual(len(converters), len(converterNames))
- for index, name in enumerate(converterNames):
- self.assertEqual(converters[index][0], name)
-
- with TestLogging(PlotTools.__name__, **kwargs):
- # Move mouse to center
- center = self.plot.size() / 2
- self.mouseMove(self.plot, pos=(center.width(), center.height()))
- # Move out
- self.mouseMove(self.plot, pos=(1, 1))
-
- def testDefaultConverters(self):
- """Test PositionInfo with default converters"""
- positionWidget = PlotTools.PositionInfo(plot=self.plot)
- self._test(positionWidget, ('X', 'Y'))
-
- def testCustomConverters(self):
- """Test PositionInfo with custom converters"""
- converters = [
- ('Coords', lambda x, y: (int(x), int(y))),
- ('Radius', lambda x, y: numpy.sqrt(x * x + y * y)),
- ('Angle', lambda x, y: numpy.degrees(numpy.arctan2(y, x)))
- ]
- positionWidget = PlotTools.PositionInfo(plot=self.plot,
- converters=converters)
- self._test(positionWidget, ('Coords', 'Radius', 'Angle'))
-
- def testFailingConverters(self):
- """Test PositionInfo with failing custom converters"""
- def raiseException(x, y):
- raise RuntimeError()
-
- positionWidget = PlotTools.PositionInfo(
- plot=self.plot,
- converters=[('Exception', raiseException)])
- self._test(positionWidget, ['Exception'], error=2)
-
-
-class TestPixelIntensitiesHisto(TestCaseQt, ParametricTestCase):
- """Tests for ProfileToolBar widget."""
-
- def setUp(self):
- super(TestPixelIntensitiesHisto, self).setUp()
- self.image = numpy.random.rand(100, 100)
- self.plotImage = Plot2D()
- self.plotImage.getIntensityHistogramAction().setVisible(True)
-
- def tearDown(self):
- del self.plotImage
- super(TestPixelIntensitiesHisto, self).tearDown()
-
- def testShowAndHide(self):
- """Simple test that the plot is showing and hiding when activating the
- action"""
- self.plotImage.addImage(self.image, origin=(0, 0), legend='sino')
- self.plotImage.show()
-
- histoAction = self.plotImage.getIntensityHistogramAction()
-
- # test the pixel intensity diagram is showing
- button = getQToolButtonFromAction(histoAction)
- self.assertIsNot(button, None)
- self.mouseMove(button)
- self.mouseClick(button, qt.Qt.LeftButton)
- self.qapp.processEvents()
- self.assertTrue(histoAction.getHistogramPlotWidget().isVisible())
-
- # test the pixel intensity diagram is hiding
- self.qapp.setActiveWindow(self.plotImage)
- self.qapp.processEvents()
- self.mouseMove(button)
- self.mouseClick(button, qt.Qt.LeftButton)
- self.qapp.processEvents()
- self.assertFalse(histoAction.getHistogramPlotWidget().isVisible())
-
- def testImageFormatInput(self):
- """Test multiple type as image input"""
- typesToTest = [numpy.uint8, numpy.int8, numpy.int16, numpy.int32,
- numpy.float32, numpy.float64]
- self.plotImage.addImage(self.image, origin=(0, 0), legend='sino')
- self.plotImage.show()
- button = getQToolButtonFromAction(
- self.plotImage.getIntensityHistogramAction())
- self.mouseMove(button)
- self.mouseClick(button, qt.Qt.LeftButton)
- self.qapp.processEvents()
- for typeToTest in typesToTest:
- with self.subTest(typeToTest=typeToTest):
- self.plotImage.addImage(self.image.astype(typeToTest),
- origin=(0, 0), legend='sino')
-
-
-def suite():
- test_suite = unittest.TestSuite()
- # test_suite.addTest(positionInfoTestSuite)
- for testClass in (TestPositionInfo, TestPixelIntensitiesHisto):
- test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(
- testClass))
- return test_suite
-
-
-if __name__ == '__main__':
- unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testPlotWidget.py b/silx/gui/plot/test/testPlotWidget.py
index 72617e5..dac6580 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-2017 European Synchrotron Radiation Facility
+# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -26,22 +26,24 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "26/01/2018"
+__date__ = "24/04/2018"
import unittest
import logging
import numpy
-from silx.utils.testutils import ParametricTestCase
+from silx.utils.testutils import ParametricTestCase, parameterize
from silx.gui.test.utils import SignalListener
from silx.gui.test.utils import TestCaseQt
from silx.utils import testutils
from silx.utils import deprecation
+from silx.test.utils import test_options
+
from silx.gui import qt
from silx.gui.plot import PlotWidget
-from silx.gui.plot.Colormap import Colormap
+from silx.gui.colors import Colormap
from .utils import PlotWidgetTestCase
@@ -188,7 +190,7 @@ class TestPlotImage(PlotWidgetTestCase, ParametricTestCase):
self.plot.addImage(rgb, legend="rgb",
origin=(0, 0), scale=(10, 10),
- replace=False, resetzoom=False)
+ resetzoom=False)
rgba = numpy.array(
(((0, 0, 0, .5), (.5, 0, 0, 1), (1, 0, 0, .5)),
@@ -197,7 +199,7 @@ class TestPlotImage(PlotWidgetTestCase, ParametricTestCase):
self.plot.addImage(rgba, legend="rgba",
origin=(5, 5), scale=(10, 10),
- replace=False, resetzoom=False)
+ resetzoom=False)
self.plot.resetZoom()
@@ -212,7 +214,7 @@ class TestPlotImage(PlotWidgetTestCase, ParametricTestCase):
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)
+ resetzoom=False)
colormap = Colormap(name=None,
normalization=Colormap.LINEAR,
@@ -224,7 +226,7 @@ class TestPlotImage(PlotWidgetTestCase, ParametricTestCase):
dtype=numpy.uint8))
self.plot.addImage(DATA_2D, legend="image 2", colormap=colormap,
origin=(DATA_2D.shape[0], 0),
- replace=False, resetzoom=False)
+ resetzoom=False)
self.plot.resetZoom()
def testImageOriginScale(self):
@@ -614,13 +616,13 @@ class TestPlotActiveCurveImage(PlotWidgetTestCase):
self.plot.getYAxis().setLabel('YLabel')
# labels changed as active curve
- self.plot.addImage(numpy.arange(100).reshape(10, 10), replace=False,
+ self.plot.addImage(numpy.arange(100).reshape(10, 10),
legend='1', xlabel='x1', ylabel='y1')
self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
# labels not changed as not active curve
- self.plot.addImage(numpy.arange(100).reshape(10, 10), replace=False,
+ self.plot.addImage(numpy.arange(100).reshape(10, 10),
legend='2')
self.assertEqual(self.plot.getXAxis().getLabel(), 'x1')
self.assertEqual(self.plot.getYAxis().getLabel(), 'y1')
@@ -660,9 +662,13 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase):
xData = numpy.arange(1, 10)
yData = xData ** 2
+ def __init__(self, methodName='runTest', backend=None):
+ unittest.TestCase.__init__(self, methodName)
+ self.__backend = backend
+
def setUp(self):
super(TestPlotAxes, self).setUp()
- self.plot = PlotWidget()
+ self.plot = PlotWidget(backend=self.__backend)
# It is not needed to display the plot
# It saves a lot of time
# self.plot.show()
@@ -721,7 +727,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase):
if getter is not None:
self.assertEqual(getter(), expected)
- @testutils.test_logging(deprecation.depreclog.name, warning=2)
+ @testutils.test_logging(deprecation.depreclog.name)
def testOldPlotAxis_Logarithmic(self):
"""Test silx API prior to silx 0.6"""
x = self.plot.getXAxis()
@@ -760,7 +766,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase):
self.assertEqual(self.plot.isYAxisLogarithmic(), False)
self.assertEqual(listener.arguments(callIndex=-1), ("y", False))
- @testutils.test_logging(deprecation.depreclog.name, warning=2)
+ @testutils.test_logging(deprecation.depreclog.name)
def testOldPlotAxis_AutoScale(self):
"""Test silx API prior to silx 0.6"""
x = self.plot.getXAxis()
@@ -799,7 +805,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase):
self.assertEqual(self.plot.isYAxisAutoScale(), True)
self.assertEqual(listener.arguments(callIndex=-1), ("y", True))
- @testutils.test_logging(deprecation.depreclog.name, warning=1)
+ @testutils.test_logging(deprecation.depreclog.name)
def testOldPlotAxis_Inverted(self):
"""Test silx API prior to silx 0.6"""
x = self.plot.getXAxis()
@@ -1162,7 +1168,7 @@ class TestPlotImageLog(PlotWidgetTestCase):
vmax=None)
self.plot.addImage(DATA_2D, legend="image 1",
origin=(1., 1.), scale=(1., 1.),
- replace=False, resetzoom=False, colormap=colormap)
+ resetzoom=False, colormap=colormap)
self.plot.resetZoom()
def testPlotColormapGrayLogY(self):
@@ -1175,7 +1181,7 @@ class TestPlotImageLog(PlotWidgetTestCase):
vmax=None)
self.plot.addImage(DATA_2D, legend="image 1",
origin=(1., 1.), scale=(1., 1.),
- replace=False, resetzoom=False, colormap=colormap)
+ resetzoom=False, colormap=colormap)
self.plot.resetZoom()
def testPlotColormapGrayLogXY(self):
@@ -1189,7 +1195,7 @@ class TestPlotImageLog(PlotWidgetTestCase):
vmax=None)
self.plot.addImage(DATA_2D, legend="image 1",
origin=(1., 1.), scale=(1., 1.),
- replace=False, resetzoom=False, colormap=colormap)
+ resetzoom=False, colormap=colormap)
self.plot.resetZoom()
def testPlotRgbRgbaLogXY(self):
@@ -1204,7 +1210,7 @@ class TestPlotImageLog(PlotWidgetTestCase):
self.plot.addImage(rgb, legend="rgb",
origin=(1, 1), scale=(10, 10),
- replace=False, resetzoom=False)
+ resetzoom=False)
rgba = numpy.array(
(((0, 0, 0, .5), (.5, 0, 0, 1), (1, 0, 0, .5)),
@@ -1213,7 +1219,7 @@ class TestPlotImageLog(PlotWidgetTestCase):
self.plot.addImage(rgba, legend="rgba",
origin=(5., 5.), scale=(10., 10.),
- replace=False, resetzoom=False)
+ resetzoom=False)
self.plot.resetZoom()
@@ -1355,19 +1361,22 @@ class TestPlotItemLog(PlotWidgetTestCase):
def suite():
+ testClasses = (TestPlotWidget, TestPlotImage, TestPlotCurve,
+ TestPlotMarker, TestPlotItem, TestPlotAxes,
+ TestPlotEmptyLog, TestPlotCurveLog, TestPlotImageLog,
+ TestPlotMarkerLog, TestPlotItemLog)
+
test_suite = unittest.TestSuite()
- 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))
+
+ # Tests with matplotlib
+ for testClass in testClasses:
+ test_suite.addTest(parameterize(testClass, backend=None))
+
+ if test_options.WITH_GL_TEST:
+ # Tests with OpenGL backend
+ for testClass in testClasses:
+ test_suite.addTest(parameterize(testClass, backend='gl'))
+
return test_suite
diff --git a/silx/gui/plot/test/testPlotWidgetNoBackend.py b/silx/gui/plot/test/testPlotWidgetNoBackend.py
index 0d0ddc4..cd7cbb3 100644
--- a/silx/gui/plot/test/testPlotWidgetNoBackend.py
+++ b/silx/gui/plot/test/testPlotWidgetNoBackend.py
@@ -460,8 +460,8 @@ class TestPlotGetCurveImage(unittest.TestCase):
image = plot.getImage()
self.assertIsNone(image)
- plot.addImage(((0, 1), (2, 3)), legend='image 0', replace=False)
- plot.addImage(((0, 1), (2, 3)), legend='image 1', replace=False)
+ plot.addImage(((0, 1), (2, 3)), legend='image 0')
+ plot.addImage(((0, 1), (2, 3)), legend='image 1')
# Active image
active = plot.getActiveImage()
@@ -470,7 +470,7 @@ class TestPlotGetCurveImage(unittest.TestCase):
self.assertEqual(image.getLegend(), 'image 0')
# No active image
- plot.addImage(((0, 1), (2, 3)), legend='image 2', replace=False)
+ plot.addImage(((0, 1), (2, 3)), legend='image 2')
plot.setActiveImage(None)
active = plot.getActiveImage()
self.assertIsNone(active)
@@ -496,7 +496,7 @@ class TestPlotGetCurveImage(unittest.TestCase):
image = numpy.arange(10).astype(numpy.float32)
image.shape = 5, 2
- plot.addImage(image, legend='image 0', info=["Hi!"], replace=False)
+ plot.addImage(image, legend='image 0', info=["Hi!"])
# Active image
data, legend, info, something, params = plot.getActiveImage()
@@ -515,8 +515,8 @@ class TestPlotGetCurveImage(unittest.TestCase):
# 2 images
data = numpy.arange(100).reshape(10, 10)
- plot.addImage(data, legend='1', replace=False)
- plot.addImage(data, origin=(10, 10), legend='2', replace=False)
+ plot.addImage(data, legend='1')
+ plot.addImage(data, origin=(10, 10), legend='2')
images = plot.getAllImages(just_legend=True)
self.assertEqual(list(images), ['1', '2'])
images = plot.getAllImages(just_legend=False)
diff --git a/silx/gui/plot/test/testSaveAction.py b/silx/gui/plot/test/testSaveAction.py
index 4dfe373..85669bf 100644
--- a/silx/gui/plot/test/testSaveAction.py
+++ b/silx/gui/plot/test/testSaveAction.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017 European Synchrotron Radiation Facility
+# Copyright (c) 2017-2018 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -33,11 +33,13 @@ import unittest
import tempfile
import os
+from silx.gui.plot.test.utils import PlotWidgetTestCase
+
from silx.gui.plot import PlotWidget
from silx.gui.plot.actions.io import SaveAction
-class TestSaveAction(unittest.TestCase):
+class TestSaveActionSaveCurvesAsSpec(unittest.TestCase):
def setUp(self):
self.plot = PlotWidget(backend='none')
@@ -63,8 +65,9 @@ class TestSaveAction(unittest.TestCase):
ylabel="curve2 Y")
self.plot.addCurve([3, 1], [7, 6], "curve with no labels")
- self.saveAction._saveCurves(self.out_fname,
- SaveAction.ALL_CURVES_FILTERS[0]) # "All curves as SpecFile (*.dat)"
+ self.saveAction._saveCurves(self.plot,
+ self.out_fname,
+ SaveAction.DEFAULT_ALL_CURVES_FILTERS[0]) # "All curves as SpecFile (*.dat)"
with open(self.out_fname, "rb") as f:
file_content = f.read()
@@ -86,10 +89,35 @@ class TestSaveAction(unittest.TestCase):
self.assertIn("#L graph x label graph y label", file_content)
+class TestSaveActionExtension(PlotWidgetTestCase):
+ """Test SaveAction file filter API"""
+
+ def _dummySaveFunction(self, plot, filename, nameFilter):
+ pass
+
+ def testFileFilterAPI(self):
+ """Test addition/update of a file filter"""
+ saveAction = SaveAction(plot=self.plot, parent=self.plot)
+
+ # Add a new file filter
+ nameFilter = 'Dummy file (*.dummy)'
+ saveAction.setFileFilter('all', nameFilter, self._dummySaveFunction)
+ self.assertTrue(nameFilter in saveAction.getFileFilters('all'))
+ self.assertEqual(saveAction.getFileFilters('all')[nameFilter],
+ self._dummySaveFunction)
+
+ # Update an existing file filter
+ nameFilter = SaveAction.IMAGE_FILTER_EDF
+ saveAction.setFileFilter('image', nameFilter, self._dummySaveFunction)
+ self.assertEqual(saveAction.getFileFilters('image')[nameFilter],
+ self._dummySaveFunction)
+
+
def suite():
test_suite = unittest.TestSuite()
- test_suite.addTest(
- unittest.defaultTestLoader.loadTestsFromTestCase(TestSaveAction))
+ for cls in (TestSaveActionSaveCurvesAsSpec, TestSaveActionExtension):
+ test_suite.addTest(
+ unittest.defaultTestLoader.loadTestsFromTestCase(cls))
return test_suite
diff --git a/silx/gui/plot/test/testScatterView.py b/silx/gui/plot/test/testScatterView.py
new file mode 100644
index 0000000..40fdac6
--- /dev/null
+++ b/silx/gui/plot/test/testScatterView.py
@@ -0,0 +1,115 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2018 European Synchrotron Radiation Facility
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ###########################################################################*/
+"""Basic tests for ScatterView"""
+
+__authors__ = ["T. Vincent"]
+__license__ = "MIT"
+__date__ = "06/03/2018"
+
+
+import unittest
+
+import numpy
+
+from silx.gui.plot.items import Axis, Scatter
+from silx.gui.plot import ScatterView
+from silx.gui.plot.test.utils import PlotWidgetTestCase
+
+
+class TestScatterView(PlotWidgetTestCase):
+ """Test of ScatterView widget"""
+
+ def _createPlot(self):
+ return ScatterView()
+
+ def test(self):
+ """Simple tests"""
+ x = numpy.arange(100)
+ y = numpy.arange(100)
+ value = numpy.arange(100)
+ self.plot.setData(x, y, value)
+ self.qapp.processEvents()
+
+ data = self.plot.getData()
+ self.assertEqual(len(data), 5)
+ self.assertTrue(numpy.all(numpy.equal(x, data[0])))
+ self.assertTrue(numpy.all(numpy.equal(y, data[1])))
+ self.assertTrue(numpy.all(numpy.equal(value, data[2])))
+ self.assertIsNone(data[3]) # xerror
+ self.assertIsNone(data[4]) # yerror
+
+ # Test access to scatter item
+ self.assertIsInstance(self.plot.getScatterItem(), Scatter)
+
+ # Test toolbar actions
+
+ action = self.plot.getScatterToolBar().getXAxisLogarithmicAction()
+ action.trigger()
+ self.qapp.processEvents()
+
+ maskAction = self.plot.getScatterToolBar().actions()[-1]
+ maskAction.trigger()
+ self.qapp.processEvents()
+
+ # Test proxy API
+
+ self.plot.resetZoom()
+ self.qapp.processEvents()
+
+ scale = self.plot.getXAxis().getScale()
+ self.assertEqual(scale, Axis.LOGARITHMIC)
+
+ scale = self.plot.getYAxis().getScale()
+ self.assertEqual(scale, Axis.LINEAR)
+
+ title = 'Test ScatterView'
+ self.plot.setGraphTitle(title)
+ self.assertEqual(self.plot.getGraphTitle(), title)
+
+ self.qapp.processEvents()
+
+ # Reset scatter data
+
+ self.plot.setData(None, None, None)
+ self.qapp.processEvents()
+
+ data = self.plot.getData()
+ self.assertEqual(len(data), 5)
+ self.assertEqual(len(data[0]), 0) # x
+ self.assertEqual(len(data[1]), 0) # y
+ self.assertEqual(len(data[2]), 0) # value
+ self.assertIsNone(data[3]) # xerror
+ self.assertIsNone(data[4]) # yerror
+
+
+def suite():
+ test_suite = unittest.TestSuite()
+ loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
+ test_suite.addTest(loadTests(TestScatterView))
+ return test_suite
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testStackView.py b/silx/gui/plot/test/testStackView.py
index 8d2a0ee..3dcea36 100644
--- a/silx/gui/plot/test/testStackView.py
+++ b/silx/gui/plot/test/testStackView.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
+# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,7 @@ __date__ = "20/03/2017"
import unittest
import numpy
-from silx.gui.test.utils import TestCaseQt
+from silx.gui.test.utils import TestCaseQt, SignalListener
from silx.gui import qt
from silx.gui.plot import StackView
@@ -187,6 +187,17 @@ class TestStackView(TestCaseQt):
"beau sirop, mi-sirop, siroté, gagne-sirop, sirop-grelot,"
" passe-montagne, sirop au bon goût.")
+ def testStackFrameNumber(self):
+ self.stackview.setStack(self.mystack)
+ self.assertEqual(self.stackview.getFrameNumber(), 0)
+
+ listener = SignalListener()
+ self.stackview.sigFrameChanged.connect(listener)
+
+ self.stackview.setFrameNumber(1)
+ self.assertEqual(self.stackview.getFrameNumber(), 1)
+ self.assertEqual(listener.arguments(), [(1,)])
+
class TestStackViewMainWindow(TestCaseQt):
"""Base class for tests of StackView."""
diff --git a/silx/gui/plot/test/testStats.py b/silx/gui/plot/test/testStats.py
new file mode 100644
index 0000000..123eb89
--- /dev/null
+++ b/silx/gui/plot/test/testStats.py
@@ -0,0 +1,561 @@
+# coding: utf-8
+# /*##########################################################################
+#
+# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# ###########################################################################*/
+"""Basic tests for CurvesROIWidget"""
+
+__authors__ = ["H. Payno"]
+__license__ = "MIT"
+__date__ = "07/03/2018"
+
+
+from silx.gui import qt
+from silx.gui.plot.stats import stats
+from silx.gui.plot import StatsWidget
+from silx.gui.plot.stats import statshandler
+from silx.gui.test.utils import TestCaseQt
+from silx.gui.plot import Plot1D, Plot2D
+import unittest
+import logging
+import numpy
+
+_logger = logging.getLogger(__name__)
+
+
+class TestStats(TestCaseQt):
+ """
+ Test :class:`BaseClass` class and inheriting classes
+ """
+ def setUp(self):
+ TestCaseQt.setUp(self)
+ self.createCurveContext()
+ self.createImageContext()
+ self.createScatterContext()
+
+ def tearDown(self):
+ self.plot1d.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.plot1d.close()
+ self.plot2d.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.plot2d.close()
+ self.scatterPlot.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.scatterPlot.close()
+
+ def createCurveContext(self):
+ self.plot1d = Plot1D()
+ x = range(20)
+ y = range(20)
+ self.plot1d.addCurve(x, y, legend='curve0')
+
+ self.curveContext = stats._CurveContext(
+ item=self.plot1d.getCurve('curve0'),
+ plot=self.plot1d,
+ onlimits=False)
+
+ def createScatterContext(self):
+ self.scatterPlot = Plot2D()
+ lgd = 'scatter plot'
+ self.xScatterData = numpy.array([0, 1, 2, 20, 50, 60, 36])
+ self.yScatterData = numpy.array([2, 3, 4, 26, 69, 6, 18])
+ self.valuesScatterData = numpy.array([5, 6, 7, 10, 90, 20, 5])
+ self.scatterPlot.addScatter(self.xScatterData, self.yScatterData,
+ self.valuesScatterData, legend=lgd)
+ self.scatterContext = stats._ScatterContext(
+ item=self.scatterPlot.getScatter(lgd),
+ plot=self.scatterPlot,
+ onlimits=False
+ )
+
+ def createImageContext(self):
+ self.plot2d = Plot2D()
+ self._imgLgd = 'test image'
+ self.imageData = numpy.arange(32*128).reshape(32, 128)
+ self.plot2d.addImage(data=self.imageData,
+ legend=self._imgLgd, replace=False)
+ self.imageContext = stats._ImageContext(
+ item=self.plot2d.getImage(self._imgLgd),
+ plot=self.plot2d,
+ onlimits=False
+ )
+
+ def getBasicStats(self):
+ return {
+ 'min': stats.StatMin(),
+ 'minCoords': stats.StatCoordMin(),
+ 'max': stats.StatMax(),
+ 'maxCoords': stats.StatCoordMax(),
+ 'std': stats.Stat(name='std', fct=numpy.std),
+ 'mean': stats.Stat(name='mean', fct=numpy.mean),
+ 'com': stats.StatCOM()
+ }
+
+ def testBasicStatsCurve(self):
+ """Test result for simple stats on a curve"""
+ _stats = self.getBasicStats()
+ xData = yData = numpy.array(range(20))
+ self.assertTrue(_stats['min'].calculate(self.curveContext) == 0)
+ self.assertTrue(_stats['max'].calculate(self.curveContext) == 19)
+ self.assertTrue(_stats['minCoords'].calculate(self.curveContext) == [0])
+ self.assertTrue(_stats['maxCoords'].calculate(self.curveContext) == [19])
+ self.assertTrue(_stats['std'].calculate(self.curveContext) == numpy.std(yData))
+ self.assertTrue(_stats['mean'].calculate(self.curveContext) == numpy.mean(yData))
+ com = numpy.sum(xData * yData) / numpy.sum(yData)
+ self.assertTrue(_stats['com'].calculate(self.curveContext) == com)
+
+ def testBasicStatsImage(self):
+ """Test result for simple stats on an image"""
+ _stats = self.getBasicStats()
+ self.assertTrue(_stats['min'].calculate(self.imageContext) == 0)
+ self.assertTrue(_stats['max'].calculate(self.imageContext) == 128 * 32 - 1)
+ self.assertTrue(_stats['minCoords'].calculate(self.imageContext) == (0, 0))
+ self.assertTrue(_stats['maxCoords'].calculate(self.imageContext) == (127, 31))
+ self.assertTrue(_stats['std'].calculate(self.imageContext) == numpy.std(self.imageData))
+ self.assertTrue(_stats['mean'].calculate(self.imageContext) == numpy.mean(self.imageData))
+
+ yData = numpy.sum(self.imageData, axis=1)
+ xData = numpy.sum(self.imageData, axis=0)
+ dataXRange = range(self.imageData.shape[1])
+ dataYRange = range(self.imageData.shape[0])
+
+ ycom = numpy.sum(yData*dataYRange) / numpy.sum(yData)
+ xcom = numpy.sum(xData*dataXRange) / numpy.sum(xData)
+
+ self.assertTrue(_stats['com'].calculate(self.imageContext) == (xcom, ycom))
+
+ def testStatsImageAdv(self):
+ """Test that scale and origin are taking into account for images"""
+
+ image2Data = numpy.arange(32 * 128).reshape(32, 128)
+ self.plot2d.addImage(data=image2Data, legend=self._imgLgd,
+ replace=True, origin=(100, 10), scale=(2, 0.5))
+ image2Context = stats._ImageContext(
+ item=self.plot2d.getImage(self._imgLgd),
+ plot=self.plot2d,
+ onlimits=False
+ )
+ _stats = self.getBasicStats()
+ self.assertTrue(_stats['min'].calculate(image2Context) == 0)
+ self.assertTrue(
+ _stats['max'].calculate(image2Context) == 128 * 32 - 1)
+ self.assertTrue(
+ _stats['minCoords'].calculate(image2Context) == (100, 10))
+ self.assertTrue(
+ _stats['maxCoords'].calculate(image2Context) == (127*2. + 100,
+ 31 * 0.5 + 10)
+ )
+ self.assertTrue(
+ _stats['std'].calculate(image2Context) == numpy.std(
+ self.imageData))
+ self.assertTrue(
+ _stats['mean'].calculate(image2Context) == numpy.mean(
+ self.imageData))
+
+ yData = numpy.sum(self.imageData, axis=1)
+ xData = numpy.sum(self.imageData, axis=0)
+ dataXRange = range(self.imageData.shape[1])
+ dataYRange = range(self.imageData.shape[0])
+
+ ycom = numpy.sum(yData * dataYRange) / numpy.sum(yData)
+ ycom = (ycom * 0.5) + 10
+ xcom = numpy.sum(xData * dataXRange) / numpy.sum(xData)
+ xcom = (xcom * 2.) + 100
+ self.assertTrue(
+ _stats['com'].calculate(image2Context) == (xcom, ycom))
+
+ def testBasicStatsScatter(self):
+ """Test result for simple stats on a scatter"""
+ _stats = self.getBasicStats()
+ self.assertTrue(_stats['min'].calculate(self.scatterContext) == 5)
+ self.assertTrue(_stats['max'].calculate(self.scatterContext) == 90)
+ self.assertTrue(_stats['minCoords'].calculate(self.scatterContext) == (0, 2))
+ self.assertTrue(_stats['maxCoords'].calculate(self.scatterContext) == (50, 69))
+ self.assertTrue(_stats['std'].calculate(self.scatterContext) == numpy.std(self.valuesScatterData))
+ self.assertTrue(_stats['mean'].calculate(self.scatterContext) == numpy.mean(self.valuesScatterData))
+
+ comx = numpy.sum(self.xScatterData * self.valuesScatterData).astype(numpy.float32) / numpy.sum(
+ self.valuesScatterData).astype(numpy.float32)
+ comy = numpy.sum(self.yScatterData * self.valuesScatterData).astype(numpy.float32) / numpy.sum(
+ self.valuesScatterData).astype(numpy.float32)
+ self.assertTrue(numpy.all(
+ numpy.equal(_stats['com'].calculate(self.scatterContext),
+ (comx, comy)))
+ )
+
+ def testKindNotManagedByStat(self):
+ """Make sure an exception is raised if we try to execute calculate
+ of the base class"""
+ b = stats.StatBase(name='toto', compatibleKinds='curve')
+ with self.assertRaises(NotImplementedError):
+ b.calculate(self.imageContext)
+
+ def testKindNotManagedByContext(self):
+ """
+ Make sure an error is raised if we try to calculate a statistic with
+ a context not managed
+ """
+ myStat = stats.Stat(name='toto', fct=numpy.std, kinds=('curve'))
+ myStat.calculate(self.curveContext)
+ with self.assertRaises(ValueError):
+ myStat.calculate(self.scatterContext)
+ with self.assertRaises(ValueError):
+ myStat.calculate(self.imageContext)
+
+ def testOnLimits(self):
+ stat = stats.StatMin()
+
+ self.plot1d.getXAxis().setLimitsConstraints(minPos=2, maxPos=5)
+ curveContextOnLimits = stats._CurveContext(
+ item=self.plot1d.getCurve('curve0'),
+ plot=self.plot1d,
+ onlimits=True)
+ self.assertTrue(stat.calculate(curveContextOnLimits) == 2)
+
+ self.plot2d.getXAxis().setLimitsConstraints(minPos=32)
+ imageContextOnLimits = stats._ImageContext(
+ item=self.plot2d.getImage('test image'),
+ plot=self.plot2d,
+ onlimits=True)
+ self.assertTrue(stat.calculate(imageContextOnLimits) == 32)
+
+ self.scatterPlot.getXAxis().setLimitsConstraints(minPos=40)
+ scatterContextOnLimits = stats._ScatterContext(
+ item=self.scatterPlot.getScatter('scatter plot'),
+ plot=self.scatterPlot,
+ onlimits=True)
+ self.assertTrue(stat.calculate(scatterContextOnLimits) == 20)
+
+
+class TestStatsFormatter(TestCaseQt):
+ """Simple test to check usage of the :class:`StatsFormatter`"""
+ def setUp(self):
+ self.plot1d = Plot1D()
+ x = range(20)
+ y = range(20)
+ self.plot1d.addCurve(x, y, legend='curve0')
+
+ self.curveContext = stats._CurveContext(
+ item=self.plot1d.getCurve('curve0'),
+ plot=self.plot1d,
+ onlimits=False)
+
+ self.stat = stats.StatMin()
+
+ def tearDown(self):
+ self.plot1d.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.plot1d.close()
+
+ def testEmptyFormatter(self):
+ """Make sure a formatter with no formatter definition will return a
+ simple cast to str"""
+ emptyFormatter = statshandler.StatFormatter()
+ self.assertTrue(
+ emptyFormatter.format(self.stat.calculate(self.curveContext)) == '0.000')
+
+ def testSettedFormatter(self):
+ """Make sure a formatter with no formatter definition will return a
+ simple cast to str"""
+ formatter= statshandler.StatFormatter(formatter='{0:.3f}')
+ self.assertTrue(
+ formatter.format(self.stat.calculate(self.curveContext)) == '0.000')
+
+
+class TestStatsHandler(unittest.TestCase):
+ """Make sure the StatHandler is correctly making the link between
+ :class:`StatBase` and :class:`StatFormatter` and checking the API is valid
+ """
+ def setUp(self):
+ self.plot1d = Plot1D()
+ x = range(20)
+ y = range(20)
+ self.plot1d.addCurve(x, y, legend='curve0')
+ self.curveItem = self.plot1d.getCurve('curve0')
+
+ self.stat = stats.StatMin()
+
+ def tearDown(self):
+ self.plot1d.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.plot1d.close()
+
+ def testConstructor(self):
+ """Make sure the constructor can deal will all possible arguments:
+
+ * tuple of :class:`StatBase` derivated classes
+ * tuple of tuples (:class:`StatBase`, :class:`StatFormatter`)
+ * tuple of tuples (str, pointer to function, kind)
+ """
+ handler0 = statshandler.StatsHandler(
+ (stats.StatMin(), stats.StatMax())
+ )
+
+ res = handler0.calculate(item=self.curveItem, plot=self.plot1d,
+ onlimits=False)
+ self.assertTrue('min' in res)
+ self.assertTrue(res['min'] == '0')
+ self.assertTrue('max' in res)
+ self.assertTrue(res['max'] == '19')
+
+ handler1 = statshandler.StatsHandler(
+ (
+ (stats.StatMin(), statshandler.StatFormatter(formatter=None)),
+ (stats.StatMax(), statshandler.StatFormatter())
+ )
+ )
+
+ res = handler1.calculate(item=self.curveItem, plot=self.plot1d,
+ onlimits=False)
+ self.assertTrue('min' in res)
+ self.assertTrue(res['min'] == '0')
+ self.assertTrue('max' in res)
+ self.assertTrue(res['max'] == '19.000')
+
+ handler2 = statshandler.StatsHandler(
+ (
+ (stats.StatMin(), None),
+ (stats.StatMax(), statshandler.StatFormatter())
+ ))
+
+ res = handler2.calculate(item=self.curveItem, plot=self.plot1d,
+ onlimits=False)
+ self.assertTrue('min' in res)
+ self.assertTrue(res['min'] == '0')
+ self.assertTrue('max' in res)
+ self.assertTrue(res['max'] == '19.000')
+
+ handler3 = statshandler.StatsHandler((
+ (('amin', numpy.argmin), statshandler.StatFormatter()),
+ ('amax', numpy.argmax)
+ ))
+
+ res = handler3.calculate(item=self.curveItem, plot=self.plot1d,
+ onlimits=False)
+ self.assertTrue('amin' in res)
+ self.assertTrue(res['amin'] == '0.000')
+ self.assertTrue('amax' in res)
+ self.assertTrue(res['amax'] == '19')
+
+ with self.assertRaises(ValueError):
+ statshandler.StatsHandler(('name'))
+
+
+class TestStatsWidgetWithCurves(TestCaseQt):
+ """Basic test for StatsWidget with curves"""
+ def setUp(self):
+ TestCaseQt.setUp(self)
+ self.plot = Plot1D()
+ x = range(20)
+ y = range(20)
+ self.plot.addCurve(x, y, legend='curve0')
+ y = range(12, 32)
+ self.plot.addCurve(x, y, legend='curve1')
+ y = range(-2, 18)
+ self.plot.addCurve(x, y, legend='curve2')
+ self.widget = StatsWidget.StatsTable(plot=self.plot)
+
+ mystats = statshandler.StatsHandler((
+ stats.StatMin(),
+ (stats.StatCoordMin(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
+ stats.StatMax(),
+ (stats.StatCoordMax(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
+ stats.StatDelta(),
+ ('std', numpy.std),
+ ('mean', numpy.mean),
+ stats.StatCOM()
+ ))
+
+ self.widget.setStats(mystats)
+
+ def tearDown(self):
+ self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.plot.close()
+ self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.widget.close()
+ self.widget = None
+ self.plot = None
+ TestCaseQt.tearDown(self)
+
+ def testInit(self):
+ """Make sure all the curves are registred on initialization"""
+ self.assertTrue(self.widget.rowCount() is 3)
+
+ def testRemoveCurve(self):
+ """Make sure the Curves stats take into account the curve removal from
+ plot"""
+ self.plot.removeCurve('curve2')
+ self.assertTrue(self.widget.rowCount() is 2)
+ for iRow in range(2):
+ self.assertTrue(self.widget.item(iRow, 0).text() in ('curve0', 'curve1'))
+
+ self.plot.removeCurve('curve0')
+ self.assertTrue(self.widget.rowCount() is 1)
+ self.plot.removeCurve('curve1')
+ self.assertTrue(self.widget.rowCount() is 0)
+
+ def testAddCurve(self):
+ """Make sure the Curves stats take into account the add curve action"""
+ self.plot.addCurve(legend='curve3', x=range(10), y=range(10))
+ self.assertTrue(self.widget.rowCount() is 4)
+
+ def testUpdateCurveFrmAddCurve(self):
+ """Make sure the stats of the cuve will be removed after updating a
+ curve"""
+ self.plot.addCurve(legend='curve0', x=range(10), y=range(10))
+ self.assertTrue(self.widget.rowCount() is 3)
+ itemMax = self.widget._getItem(name='max', legend='curve0',
+ kind='curve', indexTable=None)
+ self.assertTrue(itemMax.text() == '9')
+
+ def testUpdateCurveFrmCurveObj(self):
+ self.plot.getCurve('curve0').setData(x=range(4), y=range(4))
+ self.assertTrue(self.widget.rowCount() is 3)
+ itemMax = self.widget._getItem(name='max', legend='curve0',
+ kind='curve', indexTable=None)
+ self.assertTrue(itemMax.text() == '3')
+
+ def testSetAnotherPlot(self):
+ plot2 = Plot1D()
+ plot2.addCurve(x=range(26), y=range(26), legend='new curve')
+ self.widget.setPlot(plot2)
+ self.assertTrue(self.widget.rowCount() is 1)
+ self.qapp.processEvents()
+ plot2.setAttribute(qt.Qt.WA_DeleteOnClose)
+ plot2.close()
+ plot2 = None
+
+
+class TestStatsWidgetWithImages(TestCaseQt):
+ """Basic test for StatsWidget with images"""
+ def setUp(self):
+ TestCaseQt.setUp(self)
+ self.plot = Plot2D()
+
+ self.plot.addImage(data=numpy.arange(128*128).reshape(128, 128),
+ legend='test image', replace=False)
+
+ self.widget = StatsWidget.StatsTable(plot=self.plot)
+
+ mystats = statshandler.StatsHandler((
+ (stats.StatMin(), statshandler.StatFormatter()),
+ (stats.StatCoordMin(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
+ (stats.StatMax(), statshandler.StatFormatter()),
+ (stats.StatCoordMax(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
+ (stats.StatDelta(), statshandler.StatFormatter()),
+ ('std', numpy.std),
+ ('mean', numpy.mean),
+ (stats.StatCOM(), statshandler.StatFormatter(None))
+ ))
+
+ self.widget.setStats(mystats)
+
+ def tearDown(self):
+ self.plot.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.plot.close()
+ self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.widget.close()
+ self.widget = None
+ self.plot = None
+ TestCaseQt.tearDown(self)
+
+ def test(self):
+ columnsIndex = self.widget._columns_index
+ itemLegend = self.widget._lgdAndKindToItems[('test image', 'image')]['legend']
+ itemMin = self.widget.item(itemLegend.row(), columnsIndex['min'])
+ itemMax = self.widget.item(itemLegend.row(), columnsIndex['max'])
+ itemDelta = self.widget.item(itemLegend.row(), columnsIndex['delta'])
+ itemCoordsMin = self.widget.item(itemLegend.row(),
+ columnsIndex['coords min'])
+ itemCoordsMax = self.widget.item(itemLegend.row(),
+ columnsIndex['coords max'])
+ max = (128 * 128) - 1
+ self.assertTrue(itemMin.text() == '0.000')
+ self.assertTrue(itemMax.text() == '{0:.3f}'.format(max))
+ self.assertTrue(itemDelta.text() == '{0:.3f}'.format(max))
+ self.assertTrue(itemCoordsMin.text() == '0.0, 0.0')
+ self.assertTrue(itemCoordsMax.text() == '127.0, 127.0')
+
+
+class TestStatsWidgetWithScatters(TestCaseQt):
+ def setUp(self):
+ TestCaseQt.setUp(self)
+ self.scatterPlot = Plot2D()
+ self.scatterPlot.addScatter([0, 1, 2, 20, 50, 60],
+ [2, 3, 4, 26, 69, 6],
+ [5, 6, 7, 10, 90, 20],
+ legend='scatter plot')
+ self.widget = StatsWidget.StatsTable(plot=self.scatterPlot)
+
+ mystats = statshandler.StatsHandler((
+ stats.StatMin(),
+ (stats.StatCoordMin(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
+ stats.StatMax(),
+ (stats.StatCoordMax(), statshandler.StatFormatter(None, qt.QTableWidgetItem)),
+ stats.StatDelta(),
+ ('std', numpy.std),
+ ('mean', numpy.mean),
+ stats.StatCOM()
+ ))
+
+ self.widget.setStats(mystats)
+
+ def tearDown(self):
+ self.scatterPlot.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.scatterPlot.close()
+ self.widget.setAttribute(qt.Qt.WA_DeleteOnClose)
+ self.widget.close()
+ self.widget = None
+ self.scatterPlot = None
+ TestCaseQt.tearDown(self)
+
+ def testStats(self):
+ columnsIndex = self.widget._columns_index
+ itemLegend = self.widget._lgdAndKindToItems[('scatter plot', 'scatter')]['legend']
+ itemMin = self.widget.item(itemLegend.row(), columnsIndex['min'])
+ itemMax = self.widget.item(itemLegend.row(), columnsIndex['max'])
+ itemDelta = self.widget.item(itemLegend.row(), columnsIndex['delta'])
+ itemCoordsMin = self.widget.item(itemLegend.row(),
+ columnsIndex['coords min'])
+ itemCoordsMax = self.widget.item(itemLegend.row(),
+ columnsIndex['coords max'])
+ self.assertTrue(itemMin.text() == '5')
+ self.assertTrue(itemMax.text() == '90')
+ self.assertTrue(itemDelta.text() == '85')
+ self.assertTrue(itemCoordsMin.text() == '0, 2')
+ self.assertTrue(itemCoordsMax.text() == '50, 69')
+
+
+class TestEmptyStatsWidget(TestCaseQt):
+ def test(self):
+ widget = StatsWidget.StatsWidget()
+ widget.show()
+
+
+def suite():
+ test_suite = unittest.TestSuite()
+ for TestClass in (TestStats, TestStatsHandler, TestStatsWidgetWithScatters,
+ TestStatsWidgetWithImages, TestStatsWidgetWithCurves,
+ TestStatsFormatter, TestEmptyStatsWidget):
+ test_suite.addTest(
+ unittest.defaultTestLoader.loadTestsFromTestCase(TestClass))
+ 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
index ec9bc7c..efba39c 100644
--- a/silx/gui/plot/test/utils.py
+++ b/silx/gui/plot/test/utils.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2016 European Synchrotron Radiation Facility
+# Copyright (c) 2016-2018 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -48,11 +48,12 @@ class PlotWidgetTestCase(TestCaseQt):
__screenshot_already_taken = False
- def __init__(self, methodName='runTest'):
+ def __init__(self, methodName='runTest', backend=None):
TestCaseQt.__init__(self, methodName=methodName)
+ self.__backend = backend
def _createPlot(self):
- return PlotWidget()
+ return PlotWidget(backend=self.__backend)
def setUp(self):
super(PlotWidgetTestCase, self).setUp()