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__.py6
-rw-r--r--silx/gui/plot/test/testColormap.py76
-rw-r--r--silx/gui/plot/test/testColormapDialog.py321
-rw-r--r--silx/gui/plot/test/testColors.py4
-rw-r--r--silx/gui/plot/test/testComplexImageView.py4
-rw-r--r--silx/gui/plot/test/testCurvesROIWidget.py19
-rw-r--r--silx/gui/plot/test/testItem.py20
-rw-r--r--silx/gui/plot/test/testMaskToolsWidget.py9
-rw-r--r--silx/gui/plot/test/testPlotTools.py4
-rw-r--r--silx/gui/plot/test/testPlotWidget.py22
-rw-r--r--silx/gui/plot/test/testPlotWidgetNoBackend.py4
-rw-r--r--silx/gui/plot/test/testProfile.py4
-rw-r--r--silx/gui/plot/test/testSaveAction.py97
-rw-r--r--silx/gui/plot/test/testScatterMaskToolsWidget.py9
-rw-r--r--silx/gui/plot/test/testUtilsAxis.py23
-rw-r--r--silx/gui/plot/test/utils.py127
16 files changed, 590 insertions, 159 deletions
diff --git a/silx/gui/plot/test/__init__.py b/silx/gui/plot/test/__init__.py
index 07338b6..154a70a 100644
--- a/silx/gui/plot/test/__init__.py
+++ b/silx/gui/plot/test/__init__.py
@@ -24,7 +24,7 @@
# ###########################################################################*/
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "04/08/2017"
+__date__ = "28/11/2017"
import unittest
@@ -52,6 +52,7 @@ from . import testUtilsAxis
from . import testLimitConstraints
from . import testComplexImageView
from . import testImageView
+from . import testSaveAction
def suite():
@@ -79,5 +80,6 @@ def suite():
testUtilsAxis.suite(),
testLimitConstraints.suite(),
testComplexImageView.suite(),
- testImageView.suite()])
+ testImageView.suite(),
+ testSaveAction.suite()])
return test_suite
diff --git a/silx/gui/plot/test/testColormap.py b/silx/gui/plot/test/testColormap.py
index aa285d3..4888a7c 100644
--- a/silx/gui/plot/test/testColormap.py
+++ b/silx/gui/plot/test/testColormap.py
@@ -29,12 +29,14 @@ from __future__ import absolute_import
__authors__ = ["H.Payno"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "17/01/2018"
import unittest
import numpy
-from silx.test.utils import ParametricTestCase
+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):
@@ -134,14 +136,11 @@ class TestDictAPI(unittest.TestCase):
'autoscale': False
}
with self.assertRaises(ValueError):
- colormapObject = Colormap._fromDict(clm_dict)
+ 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
@@ -277,10 +276,73 @@ class TestObjectAPI(ParametricTestCase):
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):
+ for ui in (TestDictAPI, TestObjectAPI, TestPreferredColormaps):
test_suite.addTest(
unittest.defaultTestLoader.loadTestsFromTestCase(ui))
diff --git a/silx/gui/plot/test/testColormapDialog.py b/silx/gui/plot/test/testColormapDialog.py
index d016548..8087369 100644
--- a/silx/gui/plot/test/testColormapDialog.py
+++ b/silx/gui/plot/test/testColormapDialog.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
@@ -26,7 +26,7 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "17/01/2018"
import doctest
@@ -35,6 +35,12 @@ 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
@@ -58,9 +64,320 @@ 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
diff --git a/silx/gui/plot/test/testColors.py b/silx/gui/plot/test/testColors.py
index 18f0902..4d617eb 100644
--- a/silx/gui/plot/test/testColors.py
+++ b/silx/gui/plot/test/testColors.py
@@ -26,13 +26,13 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "05/12/2016"
+__date__ = "17/01/2018"
import numpy
import unittest
-from silx.test.utils import ParametricTestCase
+from silx.utils.testutils import ParametricTestCase
from silx.gui.plot import Colors
from silx.gui.plot.Colormap import Colormap
diff --git a/silx/gui/plot/test/testComplexImageView.py b/silx/gui/plot/test/testComplexImageView.py
index f8ec370..1933a95 100644
--- a/silx/gui/plot/test/testComplexImageView.py
+++ b/silx/gui/plot/test/testComplexImageView.py
@@ -26,14 +26,14 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "14/09/2017"
+__date__ = "17/01/2018"
import unittest
import logging
import numpy
-from silx.test.utils import ParametricTestCase
+from silx.utils.testutils import ParametricTestCase
from silx.gui.plot import ComplexImageView
from .utils import PlotWidgetTestCase
diff --git a/silx/gui/plot/test/testCurvesROIWidget.py b/silx/gui/plot/test/testCurvesROIWidget.py
index 716960a..0fd2456 100644
--- a/silx/gui/plot/test/testCurvesROIWidget.py
+++ b/silx/gui/plot/test/testCurvesROIWidget.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
@@ -24,9 +24,9 @@
# ###########################################################################*/
"""Basic tests for CurvesROIWidget"""
-__authors__ = ["T. Vincent"]
+__authors__ = ["T. Vincent", "P. Knobel"]
__license__ = "MIT"
-__date__ = "15/05/2017"
+__date__ = "16/11/2017"
import logging
@@ -105,6 +105,19 @@ class TestCurvesROIWidget(TestCaseQt):
del self.tmpFile
+ def testMiddleMarker(self):
+ """Test with middle marker enabled"""
+ self.widget.roiWidget.setMiddleROIMarkerFlag(True)
+
+ # Add a ROI
+ self.mouseClick(self.widget.roiWidget.addButton, qt.Qt.LeftButton)
+
+ xleftMarker = self.plot._getMarker(legend='ROI min').getXPosition()
+ xMiddleMarker = self.plot._getMarker(legend='ROI middle').getXPosition()
+ xRightMarker = self.plot._getMarker(legend='ROI max').getXPosition()
+ self.assertAlmostEqual(xMiddleMarker,
+ xleftMarker + (xRightMarker - xleftMarker) / 2.)
+
def testCalculation(self):
x = numpy.arange(100.)
y = numpy.arange(100.)
diff --git a/silx/gui/plot/test/testItem.py b/silx/gui/plot/test/testItem.py
index 8c15bb7..1ba09c6 100644
--- a/silx/gui/plot/test/testItem.py
+++ b/silx/gui/plot/test/testItem.py
@@ -58,7 +58,7 @@ class TestSigItemChangedSignal(PlotWidgetTestCase):
curve.setData(numpy.arange(100), numpy.arange(100))
# SymbolMixIn
- curve.setSymbol('o')
+ curve.setSymbol('Circle')
curve.setSymbol('d')
curve.setSymbolSize(20)
@@ -220,10 +220,28 @@ class TestSigItemChangedSignal(PlotWidgetTestCase):
(ItemChangedType.DATA,)])
+class TestSymbol(PlotWidgetTestCase):
+ """Test item's symbol """
+
+ def test(self):
+ """Test sigItemChanged for curve"""
+ self.plot.addCurve(numpy.arange(10), numpy.arange(10), legend='test')
+ curve = self.plot.getCurve('test')
+
+ # SymbolMixIn
+ curve.setSymbol('o')
+ name = curve.getSymbolName()
+ self.assertEqual('Circle', name)
+
+ name = curve.getSymbolName('d')
+ self.assertEqual('Diamond', name)
+
+
def suite():
test_suite = unittest.TestSuite()
loadTests = unittest.defaultTestLoader.loadTestsFromTestCase
test_suite.addTest(loadTests(TestSigItemChangedSignal))
+ test_suite.addTest(loadTests(TestSymbol))
return test_suite
diff --git a/silx/gui/plot/test/testMaskToolsWidget.py b/silx/gui/plot/test/testMaskToolsWidget.py
index 191bbe0..40c1db3 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__ = "01/09/2017"
+__date__ = "17/01/2018"
import logging
@@ -36,7 +36,8 @@ import unittest
import numpy
from silx.gui import qt
-from silx.test.utils import temp_dir, ParametricTestCase
+from silx.test.utils import temp_dir
+from silx.utils.testutils import ParametricTestCase
from silx.gui.test.utils import getQToolButtonFromAction
from silx.gui.plot import PlotWindow, MaskToolsWidget
from .utils import PlotWidgetTestCase
@@ -84,8 +85,10 @@ class TestMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase):
pos0 = xCenter, yCenter
pos1 = xCenter + offset, yCenter + offset
+ self.mouseMove(plot, pos=(0, 0))
self.mouseMove(plot, pos=pos0)
self.mousePress(plot, qt.Qt.LeftButton, pos=pos0)
+ self.mouseMove(plot, pos=(0, 0))
self.mouseMove(plot, pos=pos1)
self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos1)
@@ -194,7 +197,7 @@ class TestMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase):
self.assertIsNot(toolButton, None)
self.mouseClick(toolButton, qt.Qt.LeftButton)
- self.maskWidget.pencilSpinBox.setValue(10)
+ self.maskWidget.pencilSpinBox.setValue(30)
self.qapp.processEvents()
# mask
diff --git a/silx/gui/plot/test/testPlotTools.py b/silx/gui/plot/test/testPlotTools.py
index a08a18a..3d5849f 100644
--- a/silx/gui/plot/test/testPlotTools.py
+++ b/silx/gui/plot/test/testPlotTools.py
@@ -26,13 +26,13 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "01/09/2017"
+__date__ = "17/01/2018"
import numpy
import unittest
-from silx.test.utils import ParametricTestCase, TestLogging
+from silx.utils.testutils import ParametricTestCase, TestLogging
from silx.gui.test.utils import (
qWaitForWindowExposedAndActivate, TestCaseQt, getQToolButtonFromAction)
from silx.gui import qt
diff --git a/silx/gui/plot/test/testPlotWidget.py b/silx/gui/plot/test/testPlotWidget.py
index ccee428..72617e5 100644
--- a/silx/gui/plot/test/testPlotWidget.py
+++ b/silx/gui/plot/test/testPlotWidget.py
@@ -26,17 +26,17 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "01/09/2017"
+__date__ = "26/01/2018"
import unittest
import logging
import numpy
-from silx.test.utils import ParametricTestCase
+from silx.utils.testutils 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 testutils
from silx.utils import deprecation
from silx.gui import qt
@@ -77,9 +77,9 @@ class TestPlotWidget(PlotWidgetTestCase, ParametricTestCase):
self.assertEqual(self.plot.getYAxis().getLabel(), ylabel)
def _checkLimits(self,
- expectedXLim=None,
- expectedYLim=None,
- expectedRatio=None):
+ expectedXLim=None,
+ expectedYLim=None,
+ expectedRatio=None):
"""Assert that limits are as expected"""
xlim = self.plot.getXAxis().getLimits()
ylim = self.plot.getYAxis().getLimits()
@@ -132,13 +132,11 @@ class TestPlotWidget(PlotWidgetTestCase, ParametricTestCase):
# 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
+ listener.clear() # Clean-up received signal
self.plot.resize(200, 200)
self.qapp.processEvents()
-
self.assertNotEqual(listener.callCount(), 0)
@@ -723,7 +721,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase):
if getter is not None:
self.assertEqual(getter(), expected)
- @utils.test_logging(deprecation.depreclog.name, warning=2)
+ @testutils.test_logging(deprecation.depreclog.name, warning=2)
def testOldPlotAxis_Logarithmic(self):
"""Test silx API prior to silx 0.6"""
x = self.plot.getXAxis()
@@ -762,7 +760,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase):
self.assertEqual(self.plot.isYAxisLogarithmic(), False)
self.assertEqual(listener.arguments(callIndex=-1), ("y", False))
- @utils.test_logging(deprecation.depreclog.name, warning=2)
+ @testutils.test_logging(deprecation.depreclog.name, warning=2)
def testOldPlotAxis_AutoScale(self):
"""Test silx API prior to silx 0.6"""
x = self.plot.getXAxis()
@@ -801,7 +799,7 @@ class TestPlotAxes(TestCaseQt, ParametricTestCase):
self.assertEqual(self.plot.isYAxisAutoScale(), True)
self.assertEqual(listener.arguments(callIndex=-1), ("y", True))
- @utils.test_logging(deprecation.depreclog.name, warning=1)
+ @testutils.test_logging(deprecation.depreclog.name, warning=1)
def testOldPlotAxis_Inverted(self):
"""Test silx API prior to silx 0.6"""
x = self.plot.getXAxis()
diff --git a/silx/gui/plot/test/testPlotWidgetNoBackend.py b/silx/gui/plot/test/testPlotWidgetNoBackend.py
index 3094a20..0d0ddc4 100644
--- a/silx/gui/plot/test/testPlotWidgetNoBackend.py
+++ b/silx/gui/plot/test/testPlotWidgetNoBackend.py
@@ -26,12 +26,12 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "27/06/2017"
+__date__ = "17/01/2018"
import unittest
from functools import reduce
-from silx.test.utils import ParametricTestCase
+from silx.utils.testutils import ParametricTestCase
import numpy
diff --git a/silx/gui/plot/test/testProfile.py b/silx/gui/plot/test/testProfile.py
index 43d3329..28d9669 100644
--- a/silx/gui/plot/test/testProfile.py
+++ b/silx/gui/plot/test/testProfile.py
@@ -26,12 +26,12 @@
__authors__ = ["T. Vincent", "P. Knobel"]
__license__ = "MIT"
-__date__ = "23/02/2017"
+__date__ = "17/01/2018"
import numpy
import unittest
-from silx.test.utils import ParametricTestCase
+from silx.utils.testutils import ParametricTestCase
from silx.gui.test.utils import (
TestCaseQt, getQToolButtonFromAction)
from silx.gui import qt
diff --git a/silx/gui/plot/test/testSaveAction.py b/silx/gui/plot/test/testSaveAction.py
new file mode 100644
index 0000000..4dfe373
--- /dev/null
+++ b/silx/gui/plot/test/testSaveAction.py
@@ -0,0 +1,97 @@
+# 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 the plot's save action (consistency of output)"""
+
+__authors__ = ["P. Knobel"]
+__license__ = "MIT"
+__date__ = "28/11/2017"
+
+
+import unittest
+import tempfile
+import os
+
+from silx.gui.plot import PlotWidget
+from silx.gui.plot.actions.io import SaveAction
+
+
+class TestSaveAction(unittest.TestCase):
+
+ def setUp(self):
+ self.plot = PlotWidget(backend='none')
+ self.saveAction = SaveAction(plot=self.plot)
+
+ self.tempdir = tempfile.mkdtemp()
+ self.out_fname = os.path.join(self.tempdir, "out.dat")
+
+ def tearDown(self):
+ os.unlink(self.out_fname)
+ os.rmdir(self.tempdir)
+
+ def testSaveMultipleCurvesAsSpec(self):
+ """Test that labels are properly used."""
+ self.plot.setGraphXLabel("graph x label")
+ self.plot.setGraphYLabel("graph y label")
+
+ self.plot.addCurve([0, 1], [1, 2], "curve with labels",
+ xlabel="curve0 X", ylabel="curve0 Y")
+ self.plot.addCurve([-1, 3], [-6, 2], "curve with X label",
+ xlabel="curve1 X")
+ self.plot.addCurve([-2, 0], [8, 12], "curve with Y label",
+ ylabel="curve2 Y")
+ self.plot.addCurve([3, 1], [7, 6], "curve with no labels")
+
+ self.saveAction._saveCurves(self.out_fname,
+ SaveAction.ALL_CURVES_FILTERS[0]) # "All curves as SpecFile (*.dat)"
+
+ with open(self.out_fname, "rb") as f:
+ file_content = f.read()
+ if hasattr(file_content, "decode"):
+ file_content = file_content.decode()
+
+ # case with all curve labels specified
+ self.assertIn("#S 1 curve0 Y", file_content)
+ self.assertIn("#L curve0 X curve0 Y", file_content)
+
+ # graph X&Y labels are used when no curve label is specified
+ self.assertIn("#S 2 graph y label", file_content)
+ self.assertIn("#L curve1 X graph y label", file_content)
+
+ self.assertIn("#S 3 curve2 Y", file_content)
+ self.assertIn("#L graph x label curve2 Y", file_content)
+
+ self.assertIn("#S 4 graph y label", file_content)
+ self.assertIn("#L graph x label graph y label", file_content)
+
+
+def suite():
+ test_suite = unittest.TestSuite()
+ test_suite.addTest(
+ unittest.defaultTestLoader.loadTestsFromTestCase(TestSaveAction))
+ return test_suite
+
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='suite')
diff --git a/silx/gui/plot/test/testScatterMaskToolsWidget.py b/silx/gui/plot/test/testScatterMaskToolsWidget.py
index 178274a..0342c8f 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__ = "01/09/2017"
+__date__ = "17/01/2018"
import logging
@@ -36,7 +36,8 @@ import unittest
import numpy
from silx.gui import qt
-from silx.test.utils import temp_dir, ParametricTestCase
+from silx.test.utils import temp_dir
+from silx.utils.testutils import ParametricTestCase
from silx.gui.test.utils import getQToolButtonFromAction
from silx.gui.plot import PlotWindow, ScatterMaskToolsWidget
from .utils import PlotWidgetTestCase
@@ -86,8 +87,10 @@ class TestScatterMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase):
pos0 = xCenter, yCenter
pos1 = xCenter + offset, yCenter + offset
+ self.mouseMove(plot, pos=(0, 0))
self.mouseMove(plot, pos=pos0)
self.mousePress(plot, qt.Qt.LeftButton, pos=pos0)
+ self.mouseMove(plot, pos=(0, 0))
self.mouseMove(plot, pos=pos1)
self.mouseRelease(plot, qt.Qt.LeftButton, pos=pos1)
@@ -197,7 +200,7 @@ class TestScatterMaskToolsWidget(PlotWidgetTestCase, ParametricTestCase):
self.assertIsNot(toolButton, None)
self.mouseClick(toolButton, qt.Qt.LeftButton)
- self.maskWidget.pencilSpinBox.setValue(10)
+ self.maskWidget.pencilSpinBox.setValue(30)
self.qapp.processEvents()
# mask
diff --git a/silx/gui/plot/test/testUtilsAxis.py b/silx/gui/plot/test/testUtilsAxis.py
index 6702b00..3f19dcd 100644
--- a/silx/gui/plot/test/testUtilsAxis.py
+++ b/silx/gui/plot/test/testUtilsAxis.py
@@ -26,18 +26,20 @@
__authors__ = ["V. Valls"]
__license__ = "MIT"
-__date__ = "04/08/2017"
+__date__ = "14/02/2018"
import unittest
from silx.gui.plot import PlotWidget
+from silx.gui.test.utils import TestCaseQt
from silx.gui.plot.utils.axis import SyncAxes
-class TestAxisSync(unittest.TestCase):
+class TestAxisSync(TestCaseQt):
"""Tests AxisSync class"""
def setUp(self):
+ TestCaseQt.setUp(self)
self.plot1 = PlotWidget()
self.plot2 = PlotWidget()
self.plot3 = PlotWidget()
@@ -46,6 +48,7 @@ class TestAxisSync(unittest.TestCase):
self.plot1 = None
self.plot2 = None
self.plot3 = None
+ TestCaseQt.tearDown(self)
def testMoveFirstAxis(self):
"""Test synchronization after construction"""
@@ -85,6 +88,22 @@ class TestAxisSync(unittest.TestCase):
self.assertNotEqual(self.plot2.getXAxis().getLimits(), (10, 500))
self.assertNotEqual(self.plot3.getXAxis().getLimits(), (10, 500))
+ def testAxisDestruction(self):
+ """Test synchronization when an axis disappear"""
+ _sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
+
+ # Destroy the plot is possible
+ import weakref
+ plot = weakref.ref(self.plot2)
+ self.plot2 = None
+ result = self.qWaitForDestroy(plot)
+ if not result:
+ # We can't test
+ self.skipTest("Object not destroyed")
+
+ self.plot1.getXAxis().setLimits(10, 500)
+ self.assertEqual(self.plot3.getXAxis().getLimits(), (10, 500))
+
def testStop(self):
"""Test synchronization after calling stop"""
sync = SyncAxes([self.plot1.getXAxis(), self.plot2.getXAxis(), self.plot3.getXAxis()])
diff --git a/silx/gui/plot/test/utils.py b/silx/gui/plot/test/utils.py
index ef547c6..ec9bc7c 100644
--- a/silx/gui/plot/test/utils.py
+++ b/silx/gui/plot/test/utils.py
@@ -26,17 +26,15 @@
__authors__ = ["T. Vincent"]
__license__ = "MIT"
-__date__ = "01/09/2017"
+__date__ = "26/01/2018"
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__)
@@ -48,9 +46,10 @@ class PlotWidgetTestCase(TestCaseQt):
plot attribute is the PlotWidget created for the test.
"""
+ __screenshot_already_taken = False
+
def __init__(self, methodName='runTest'):
TestCaseQt.__init__(self, methodName=methodName)
- self.__mousePos = None
def _createPlot(self):
return PlotWidget()
@@ -79,116 +78,16 @@ class PlotWidgetTestCase(TestCaseQt):
logger.error("Plot is still alive")
def tearDown(self):
+ if not self._currentTestSucceeded():
+ # MPL is the only widget which uses the real system mouse.
+ # In case of a the windows is outside of the screen, minimzed,
+ # overlapped by a system popup, the MPL widget will not receive the
+ # mouse event.
+ # Taking a screenshot help debuging this cases in the continuous
+ # integration environement.
+ if not PlotWidgetTestCase.__screenshot_already_taken:
+ PlotWidgetTestCase.__screenshot_already_taken = True
+ self.logScreenShot()
self.qapp.processEvents()
self._waitForPlotClosed()
super(PlotWidgetTestCase, self).tearDown()
-
- 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)