source: sasview/src/sas/qtgui/Plotting/UnitTesting/PlotterTest.py @ 3e8dee3

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 3e8dee3 was 3e8dee3, checked in by Piotr Rozyczko <rozyczko@…>, 6 years ago

Converted unit tests

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