source: sasview/src/sas/qtgui/Plotting/UnitTesting/PlotterTest.py @ 8353d90

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 8353d90 was 53c771e, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Converted unit tests

  • Property mode set to 100755
File size: 16.3 KB
RevLine 
[6d05e1d]1import sys
2import unittest
[b2a5042]3import platform
[6d05e1d]4
[53c771e]5from PyQt5 import QtGui, QtWidgets, QtPrintSupport
6from PyQt5 import QtCore
7from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
[7fb471d]8from unittest.mock import MagicMock
9from unittest.mock import patch
[6d05e1d]10
11####### TEMP
[416fa8f]12import path_prepare
[6d05e1d]13#######
[dc5ef15]14from sas.qtgui.Plotting.PlotterData import Data1D
15from sas.qtgui.Plotting.PlotterData import Data2D
16from sas.qtgui.UnitTesting.TestUtils import WarningTestNotImplemented
[83eb5208]17from sas.qtgui.Plotting.LinearFit import LinearFit
18from sas.qtgui.Plotting.PlotProperties import PlotProperties
[6d05e1d]19
20# Tested module
[83eb5208]21import sas.qtgui.Plotting.Plotter as Plotter
[6d05e1d]22
[53c771e]23if not QtWidgets.QApplication.instance():
24    app = QtWidgets.QApplication(sys.argv)
[6d05e1d]25
[87cc73a]26
[6d05e1d]27class PlotterTest(unittest.TestCase):
28    '''Test the Plotter 1D class'''
29    def setUp(self):
30        '''create'''
[257bd57]31
[6d05e1d]32        self.plotter = Plotter.Plotter(None, quickplot=True)
33        self.data = Data1D(x=[1.0, 2.0, 3.0],
34                           y=[10.0, 11.0, 12.0],
35                           dx=[0.1, 0.2, 0.3],
36                           dy=[0.1, 0.2, 0.3])
37        self.data.title="Test data"
[aadf0af1]38        self.data.name="Test name"
[6d05e1d]39        self.data.id = 1
[b2a5042]40        self.isWindows = platform.system=="Windows"
[6d05e1d]41
42    def tearDown(self):
43        '''destroy'''
44        self.plotter = None
45
46    def testDataProperty(self):
47        """ Adding data """
48        self.plotter.data = self.data
49
50        self.assertEqual(self.plotter.data, self.data)
[aadf0af1]51        self.assertEqual(self.plotter._title, self.data.name)
[6d05e1d]52        self.assertEqual(self.plotter.xLabel, "$()$")
53        self.assertEqual(self.plotter.yLabel, "$()$")
54
[fecfe28]55    def testPlotWithErrors(self):
56        """ Look at the plotting with error bars"""
[6d05e1d]57        self.plotter.data = self.data
58        self.plotter.show()
[53c771e]59        FigureCanvas.draw_idle = MagicMock()
[6d05e1d]60
[fecfe28]61        self.plotter.plot(hide_error=False)
[6d05e1d]62
[fecfe28]63        self.assertEqual(self.plotter.ax.get_xscale(), 'log')
[53c771e]64        self.assertTrue(FigureCanvas.draw_idle.called)
65
66        self.plotter.figure.clf()
[fecfe28]67
68    def testPlotWithoutErrors(self):
69        """ Look at the plotting without error bars"""
70        self.plotter.data = self.data
71        self.plotter.show()
[53c771e]72        FigureCanvas.draw_idle = MagicMock()
[fecfe28]73
74        self.plotter.plot(hide_error=True)
75
76        self.assertEqual(self.plotter.ax.get_yscale(), 'log')
[53c771e]77        self.assertTrue(FigureCanvas.draw_idle.called)
78        self.plotter.figure.clf()
[6d05e1d]79
[749b715]80    def testPlotWithSesans(self):
81        """ Ensure that Sesans data is plotted in linear cooredinates"""
82        data = Data1D(x=[1.0, 2.0, 3.0],
83                      y=[10.0, 11.0, 12.0],
84                      dx=[0.1, 0.2, 0.3],
85                      dy=[0.1, 0.2, 0.3])
86        data.title = "Sesans data"
87        data.name = "Test Sesans"
88        data.isSesans = True
89        data.id = 2
90
91        self.plotter.data = data
92        self.plotter.show()
93        FigureCanvas.draw = MagicMock()
94
95        self.plotter.plot(hide_error=True)
96
97        self.assertEqual(self.plotter.ax.get_xscale(), 'linear')
98        self.assertEqual(self.plotter.ax.get_yscale(), 'linear')
99        self.assertTrue(FigureCanvas.draw.called)
100
[b46f285]101    def testCreateContextMenuQuick(self):
[6d05e1d]102        """ Test the right click menu """
[aadf0af1]103        self.plotter.createContextMenuQuick()
[6d05e1d]104        actions = self.plotter.contextMenu.actions()
105        self.assertEqual(len(actions), 7)
106
107        # Trigger Save Image and make sure the method is called
108        self.assertEqual(actions[0].text(), "Save Image")
109        self.plotter.toolbar.save_figure = MagicMock()
110        actions[0].trigger()
111        self.assertTrue(self.plotter.toolbar.save_figure.called)
112
113        # Trigger Print Image and make sure the method is called
114        self.assertEqual(actions[1].text(), "Print Image")
[53c771e]115        QtPrintSupport.QPrintDialog.exec_ = MagicMock(return_value=QtWidgets.QDialog.Rejected)
[6d05e1d]116        actions[1].trigger()
[53c771e]117        self.assertTrue(QtPrintSupport.QPrintDialog.exec_.called)
[6d05e1d]118
119        # Trigger Copy to Clipboard and make sure the method is called
120        self.assertEqual(actions[2].text(), "Copy to Clipboard")
121
122        # Trigger Toggle Grid and make sure the method is called
123        self.assertEqual(actions[4].text(), "Toggle Grid On/Off")
124        self.plotter.ax.grid = MagicMock()
125        actions[4].trigger()
126        self.assertTrue(self.plotter.ax.grid.called)
127
128        # Trigger Change Scale and make sure the method is called
129        self.assertEqual(actions[6].text(), "Change Scale")
[53c771e]130        self.plotter.properties.exec_ = MagicMock(return_value=QtWidgets.QDialog.Rejected)
[6d05e1d]131        actions[6].trigger()
132        self.assertTrue(self.plotter.properties.exec_.called)
133
[b2a5042]134        # Spy on cliboard's dataChanged() signal
135        if not self.isWindows:
136            return
137        self.clipboard_called = False
138        def done():
139            self.clipboard_called = True
[53c771e]140        QtCore.QObject.connect(QtWidgets.qApp.clipboard(), QtCore.SIGNAL("dataChanged()"), done)
[b2a5042]141        actions[2].trigger()
[53c771e]142        QtWidgets.qApp.processEvents()
[b2a5042]143        # Make sure clipboard got updated.
144        self.assertTrue(self.clipboard_called)
145
[b46f285]146    def testXyTransform(self):
147        """ Tests the XY transformation and new chart update """
[257bd57]148        self.plotter.plot(self.data)
[6d05e1d]149
[b46f285]150        # Transform the points
151        self.plotter.xyTransform(xLabel="x", yLabel="log10(y)")
[6d05e1d]152
[b46f285]153        # Assure new plot has correct labels
[64f1e93]154        self.assertEqual(self.plotter.ax.get_xlabel(), "$()$")
155        self.assertEqual(self.plotter.ax.get_ylabel(), "$()$")
[b46f285]156        # ... and scale
157        self.assertEqual(self.plotter.xscale, "linear")
158        self.assertEqual(self.plotter.yscale, "log")
159        # See that just one plot is present
160        self.assertEqual(len(self.plotter.plot_dict), 1)
161        self.assertEqual(len(self.plotter.ax.collections), 1)
[53c771e]162        self.plotter.figure.clf()
[64f1e93]163
[9290b1a]164    def testAddText(self):
165        """ Checks the functionality of adding text to graph """
[257bd57]166
167        self.plotter.plot(self.data)
168        self.plotter.x_click = 100.0
169        self.plotter.y_click = 100.0
170        # modify the text edit control
171        test_text = "Smoke in cabin"
172        test_font = QtGui.QFont("Arial", 16, QtGui.QFont.Bold)
173        test_color = "#00FF00"
174        self.plotter.addText.textEdit.setText(test_text)
175
176        # Return the requested font parameters
177        self.plotter.addText.font = MagicMock(return_value = test_font)
178        self.plotter.addText.color = MagicMock(return_value = test_color)
179        # Return OK from the dialog
[53c771e]180        self.plotter.addText.exec_ = MagicMock(return_value = QtWidgets.QDialog.Accepted)
[257bd57]181        # Add text to graph
182        self.plotter.onAddText()
183        self.plotter.show()
184        # Check if the text was added properly
185        self.assertEqual(len(self.plotter.textList), 1)
186        self.assertEqual(self.plotter.textList[0].get_text(), test_text)
187        self.assertEqual(self.plotter.textList[0].get_color(), test_color)
188        self.assertEqual(self.plotter.textList[0].get_fontproperties().get_family()[0], 'Arial')
189        self.assertEqual(self.plotter.textList[0].get_fontproperties().get_size(), 16)
[53c771e]190        self.plotter.figure.clf()
[9290b1a]191
192    def testOnRemoveText(self):
193        """ Cheks if annotations can be removed from the graph """
[257bd57]194
195        # Add some text
196        self.plotter.plot(self.data)
197        test_text = "Safety instructions"
198        self.plotter.addText.textEdit.setText(test_text)
199        # Return OK from the dialog
[53c771e]200        self.plotter.addText.exec_ = MagicMock(return_value = QtWidgets.QDialog.Accepted)
[257bd57]201        # Add text to graph
202        self.plotter.onAddText()
203        self.plotter.show()
204        # Check if the text was added properly
205        self.assertEqual(len(self.plotter.textList), 1)
206
207        # Now, remove the text
208        self.plotter.onRemoveText()
209
210        # And assure no text is displayed
211        self.assertEqual(self.plotter.textList, [])
212
213        # Attempt removal on empty and check
214        self.plotter.onRemoveText()
215        self.assertEqual(self.plotter.textList, [])
[53c771e]216        self.plotter.figure.clf()
[9290b1a]217
[d3ca363]218    def testOnSetGraphRange(self):
219        """ Cheks if the graph can be resized for range """
[257bd57]220        new_x = (1,2)
221        new_y = (10,11)
222        self.plotter.plot(self.data)
223        self.plotter.show()
[53c771e]224        self.plotter.setRange.exec_ = MagicMock(return_value = QtWidgets.QDialog.Accepted)
[257bd57]225        self.plotter.setRange.xrange = MagicMock(return_value = new_x)
226        self.plotter.setRange.yrange = MagicMock(return_value = new_y)
227
228        # Call the tested method
229        self.plotter.onSetGraphRange()
230        # See that ranges changed accordingly
231        self.assertEqual(self.plotter.ax.get_xlim(), new_x)
232        self.assertEqual(self.plotter.ax.get_ylim(), new_y)
[53c771e]233        self.plotter.figure.clf()
[d3ca363]234
235    def testOnResetGraphRange(self):
236        """ Cheks if the graph can be reset after resizing for range """
[257bd57]237        # New values
238        new_x = (1,2)
239        new_y = (10,11)
240        # define the plot
241        self.plotter.plot(self.data)
242        self.plotter.show()
243
244        # mock setRange methods
[53c771e]245        self.plotter.setRange.exec_ = MagicMock(return_value = QtWidgets.QDialog.Accepted)
[257bd57]246        self.plotter.setRange.xrange = MagicMock(return_value = new_x)
247        self.plotter.setRange.yrange = MagicMock(return_value = new_y)
248
249        # Change the axes range
250        self.plotter.onSetGraphRange()
251
252        # Now, reset the range back
253        self.plotter.onResetGraphRange()
254
255        # See that ranges are changed
256        self.assertNotEqual(self.plotter.ax.get_xlim(), new_x)
257        self.assertNotEqual(self.plotter.ax.get_ylim(), new_y)
[53c771e]258        self.plotter.figure.clf()
[9290b1a]259
[b46f285]260    def testOnLinearFit(self):
261        """ Checks the response to LinearFit call """
[2e3e959]262        self.plotter.plot(self.data)
263        self.plotter.show()
[53c771e]264        QtWidgets.QDialog.exec_ = MagicMock(return_value=QtWidgets.QDialog.Accepted)
[2e3e959]265
266        # Just this one plot
[7fb471d]267        self.assertEqual(len(list(self.plotter.plot_dict.keys())), 1)
[2e3e959]268        self.plotter.onLinearFit(1)
269
270        # Check that exec_ got called
[53c771e]271        self.assertTrue(QtWidgets.QDialog.exec_.called)
272        self.plotter.figure.clf()
[b46f285]273
274    def testOnRemovePlot(self):
275        """ Assure plots get removed when requested """
[2e3e959]276        # Add two plots
277        self.plotter.show()
278        self.plotter.plot(self.data)
279        data2 = Data1D(x=[1.0, 2.0, 3.0],
280                       y=[11.0, 12.0, 13.0],
281                       dx=[0.1, 0.2, 0.3],
282                       dy=[0.1, 0.2, 0.3])
283        data2.title="Test data 2"
284        data2.name="Test name 2"
285        data2.id = 2
286        self.plotter.plot(data2)
287
288        # Assure the plotter window is visible
[0268aed]289        #self.assertTrue(self.plotter.isVisible())
[2e3e959]290
291        # Assure we have two sets
[7fb471d]292        self.assertEqual(len(list(self.plotter.plot_dict.keys())), 2)
[2e3e959]293
294        # Delete one set
295        self.plotter.onRemovePlot(2)
296        # Assure we have two sets
[7fb471d]297        self.assertEqual(len(list(self.plotter.plot_dict.keys())), 1)
[2e3e959]298
299        self.plotter.manager = MagicMock()
300
301        # Delete the remaining set
302        self.plotter.onRemovePlot(1)
303        # Assure we have no plots
[7fb471d]304        self.assertEqual(len(list(self.plotter.plot_dict.keys())), 0)
[2e3e959]305        # Assure the plotter window is closed
306        self.assertFalse(self.plotter.isVisible())
[53c771e]307        self.plotter.figure.clf()
[b46f285]308
309    def testRemovePlot(self):
310        """ Test plot removal """
[2e3e959]311        # Add two plots
312        self.plotter.show()
313        self.plotter.plot(self.data)
314        data2 = Data1D(x=[1.0, 2.0, 3.0],
315                       y=[11.0, 12.0, 13.0],
316                       dx=[0.1, 0.2, 0.3],
317                       dy=[0.1, 0.2, 0.3])
318        data2.title="Test data 2"
319        data2.name="Test name 2"
320        data2.id = 2
321        data2._xaxis = "XAXIS"
322        data2._xunit = "furlong*fortnight^{-1}"
323        data2._yaxis = "YAXIS"
324        data2._yunit = "cake"
325        data2.hide_error = True
326        self.plotter.plot(data2)
327
328        # delete plot 1
329        self.plotter.removePlot(1)
330
331        # See that the labels didn't change
332        xl = self.plotter.ax.xaxis.label.get_text()
333        yl = self.plotter.ax.yaxis.label.get_text()
334        self.assertEqual(xl, "$XAXIS(furlong*fortnight^{-1})$")
335        self.assertEqual(yl, "$YAXIS(cake)$")
336        # The hide_error flag should also remain
337        self.assertTrue(self.plotter.plot_dict[2].hide_error)
[53c771e]338        self.plotter.figure.clf()
[b46f285]339
340    def testOnToggleHideError(self):
341        """ Test the error bar toggle on plots """
[2e3e959]342        # Add two plots
343        self.plotter.show()
344        self.plotter.plot(self.data)
345        data2 = Data1D(x=[1.0, 2.0, 3.0],
346                       y=[11.0, 12.0, 13.0],
347                       dx=[0.1, 0.2, 0.3],
348                       dy=[0.1, 0.2, 0.3])
349        data2.title="Test data 2"
350        data2.name="Test name 2"
351        data2.id = 2
352        data2._xaxis = "XAXIS"
353        data2._xunit = "furlong*fortnight^{-1}"
354        data2._yaxis = "YAXIS"
355        data2._yunit = "cake"
356        error_status = True
357        data2.hide_error = error_status
358        self.plotter.plot(data2)
359
360        # Reverse the toggle
361        self.plotter.onToggleHideError(2)
362        # See that the labels didn't change
363        xl = self.plotter.ax.xaxis.label.get_text()
364        yl = self.plotter.ax.yaxis.label.get_text()
365        self.assertEqual(xl, "$XAXIS(furlong*fortnight^{-1})$")
366        self.assertEqual(yl, "$YAXIS(cake)$")
367        # The hide_error flag should toggle
368        self.assertEqual(self.plotter.plot_dict[2].hide_error, not error_status)
[53c771e]369        self.plotter.figure.clf()
[b46f285]370
371    def testOnFitDisplay(self):
372        """ Test the fit line display on the chart """
[2e3e959]373        self.assertIsInstance(self.plotter.fit_result, Data1D)
374        self.assertEqual(self.plotter.fit_result.symbol, 13)
375        self.assertEqual(self.plotter.fit_result.name, "Fit")
376
377        # fudge some init data
378        fit_data = [[0.0,0.0], [5.0,5.0]]
379        # Call the method
380        self.plotter.plot = MagicMock()
381        self.plotter.onFitDisplay(fit_data)
382        self.assertTrue(self.plotter.plot.called)
383        # Look at arguments passed to .plot()
384        self.plotter.plot.assert_called_with(data=self.plotter.fit_result,
385                                             hide_error=True, marker='-')
[53c771e]386        self.plotter.figure.clf()
[87cc73a]387
388    def testReplacePlot(self):
389        """ Test the plot refresh functionality """
[2e3e959]390        # Add original data
391        self.plotter.show()
392        self.plotter.plot(self.data)
393        # See the default labels
394        xl = self.plotter.ax.xaxis.label.get_text()
395        yl = self.plotter.ax.yaxis.label.get_text()
396        self.assertEqual(xl, "$()$")
397        self.assertEqual(yl, "$()$")
398
399        # Prepare new data
400        data2 = Data1D(x=[1.0, 2.0, 3.0],
401                       y=[11.0, 12.0, 13.0],
402                       dx=[0.1, 0.2, 0.3],
403                       dy=[0.1, 0.2, 0.3])
404        data2.title="Test data 2"
405        data2.name="Test name 2"
406        data2.id = 2
407        data2._xaxis = "XAXIS"
408        data2._xunit = "furlong*fortnight^{-1}"
409        data2._yaxis = "YAXIS"
410        data2._yunit = "cake"
411        error_status = True
412        data2.hide_error = error_status
413
414        # Replace data in plot
415        self.plotter.replacePlot(1, data2)
416
417        # See that the labels changed
418        xl = self.plotter.ax.xaxis.label.get_text()
419        yl = self.plotter.ax.yaxis.label.get_text()
420        self.assertEqual(xl, "$XAXIS(furlong*fortnight^{-1})$")
421        self.assertEqual(yl, "$YAXIS(cake)$")
422        # The hide_error flag should be as set
423        self.assertEqual(self.plotter.plot_dict[2].hide_error, error_status)
[53c771e]424        self.plotter.figure.clf()
[87cc73a]425
[83eb5208]426    def notestOnModifyPlot(self):
[87cc73a]427        """ Test the functionality for changing plot properties """
[2e3e959]428        # Prepare new data
429        data2 = Data1D(x=[1.0, 2.0, 3.0],
430                       y=[11.0, 12.0, 13.0],
431                       dx=[0.1, 0.2, 0.3],
432                       dy=[0.1, 0.2, 0.3])
433        data2.title="Test data 2"
434        data2.name="Test name 2"
435        data2.id = 2
436        data2.custom_color = None
437        data2.symbol = 1
438        data2.markersize = 11
439
440        self.plotter.plot(data2)
441
[83eb5208]442        with patch('sas.qtgui.Plotting.PlotProperties.PlotProperties') as mock:
[2e3e959]443            instance = mock.return_value
[53c771e]444            QtWidgets.QDialog.exec_ = MagicMock(return_value=QtWidgets.QDialog.Accepted)
[2e3e959]445            instance.symbol.return_value = 7
446
447            self.plotter.onModifyPlot(2)
[53c771e]448        self.plotter.figure.clf()
[2e3e959]449
[b46f285]450
[6d05e1d]451if __name__ == "__main__":
452    unittest.main()
Note: See TracBrowser for help on using the repository browser.