source: sasview/src/sas/qtgui/Calculators/UnitTesting/GenericScatteringCalculatorTest.py

ESS_GUI
Last change on this file was c02721c4, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 5 years ago

Unit test update after latest round of commits.

  • Property mode set to 100644
File size: 20.4 KB
Line 
1import sys
2import time
3import numpy
4import unittest
5from PyQt5 import QtGui, QtWidgets
6from PyQt5.QtTest import QTest
7
8from PyQt5.QtCore import Qt
9from unittest.mock import MagicMock
10from unittest.mock import patch
11
12# set up import paths
13import path_prepare
14
15from mpl_toolkits.mplot3d import Axes3D
16from UnitTesting.TestUtils import QtSignalSpy
17from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
18from sas.qtgui.Calculators.GenericScatteringCalculator import GenericScatteringCalculator
19from sas.qtgui.Calculators.GenericScatteringCalculator import Plotter3D
20
21from sas.qtgui.MainWindow.DataManager import DataManager
22from sas.qtgui.MainWindow.GuiManager import GuiManager
23from sas.qtgui.Utilities.GuiUtils import *
24from sas.sascalc.calculator import sas_gen
25
26if not QtWidgets.QApplication.instance():
27    app = QtWidgets.QApplication(sys.argv)
28
29class GenericScatteringCalculatorTest(unittest.TestCase):
30    """Test the GenericScatteringCalculator"""
31    def setUp(self):
32        """Create the GenericScatteringCalculator"""
33        class dummy_manager(object):
34            def communicator(self):
35                return Communicate()
36
37        self.widget = GenericScatteringCalculator(dummy_manager())
38
39    def tearDown(self):
40        """Destroy the GenericScatteringCalculator"""
41        self.widget.close()
42        self.widget = None
43
44
45    def testDefaults(self):
46        """Test the GUI in its default state"""
47        self.assertIsInstance(self.widget, QtWidgets.QWidget)
48        self.assertEqual(self.widget.windowTitle(), "Generic Scattering Calculator")
49
50        self.assertIn('trigger_plot_3d', dir(self.widget))
51
52        # Buttons
53        self.assertEqual(self.widget.txtData.text(), "Default SLD Profile")
54        self.assertEqual(self.widget.cmdLoad.text(), "Load")
55        self.assertEqual(self.widget.cmdDraw.text(), "Draw")
56        self.assertEqual(self.widget.cmdCompute.text(), "Compute")
57        self.assertEqual(self.widget.cmdReset.text(), "Reset")
58        self.assertEqual(self.widget.cmdClose.text(), "Close")
59        self.assertEqual(self.widget.cmdHelp.text(), "Help")
60        self.assertEqual(self.widget.cmdDrawpoints.text(), "Draw Points")
61        self.assertEqual(self.widget.cmdSave.text(), "Save SLD Data")
62
63        self.assertEqual(self.widget.txtBackground.text(), '0.0')
64        self.assertEqual(self.widget.txtScale.text(), '1.0')
65        self.assertEqual(self.widget.txtSolventSLD.text(), '0.0')
66        self.assertEqual(self.widget.txtTotalVolume.text(), '216000.0')
67        self.assertEqual(self.widget.txtUpFracIn.text(), '1.0')
68        self.assertEqual(self.widget.txtUpFracOut.text(), '1.0')
69        self.assertEqual(self.widget.txtUpTheta.text(), '0.0')
70        self.assertEqual(self.widget.txtNoQBins.text(), '50')
71        self.assertEqual(self.widget.txtQxMax.text(), '0.3')
72        self.assertEqual(self.widget.txtNoPixels.text(), '1000')
73        self.assertEqual(self.widget.txtMx.text(), '0')
74        self.assertEqual(self.widget.txtMy.text(), '0')
75        self.assertEqual(self.widget.txtMz.text(), '0')
76        self.assertEqual(self.widget.txtNucl.text(), '6.97e-06')
77        self.assertEqual(self.widget.txtXnodes.text(), '10')
78        self.assertEqual(self.widget.txtYnodes.text(), '10')
79        self.assertEqual(self.widget.txtZnodes.text(), '10')
80        self.assertEqual(self.widget.txtXstepsize.text(), '6')
81        self.assertEqual(self.widget.txtYstepsize.text(), '6')
82        self.assertEqual(self.widget.txtZstepsize.text(), '6')
83
84        # Comboboxes
85        self.assertFalse(self.widget.cbOptionsCalc.isVisible())
86        self.assertFalse(self.widget.cbOptionsCalc.isEditable())
87        self.assertEqual(self.widget.cbOptionsCalc.count(), 2)
88        self.assertEqual(self.widget.cbOptionsCalc.currentIndex(), 0)
89        self.assertListEqual([self.widget.cbOptionsCalc.itemText(i) for i in
90                              range(self.widget.cbOptionsCalc.count())],
91                             ['Fixed orientation', 'Debye full avg.'])
92
93        self.assertEqual(self.widget.cbShape.count(), 1)
94        self.assertEqual(self.widget.cbShape.currentIndex(), 0)
95        self.assertListEqual([self.widget.cbShape.itemText(i) for i in
96                              range(self.widget.cbShape.count())],
97                             ['Rectangular'])
98                             #['Rectangular', 'Ellipsoid'])
99        self.assertFalse(self.widget.cbShape.isEditable())
100        # disable buttons
101        self.assertFalse(self.widget.cmdSave.isEnabled())
102        self.assertFalse(self.widget.cmdDraw.isEnabled())
103        self.assertFalse(self.widget.cmdDrawpoints.isEnabled())
104
105    def testHelpButton(self):
106        """ Assure help file is shown """
107        self.widget.manager.showHelp = MagicMock()
108        self.widget.onHelp()
109        self.assertTrue(self.widget.manager.showHelp.called_once())
110        args = self.widget.manager.showHelp.call_args
111        self.assertIn('sas_calculator_help.html', args[0][0])
112
113    def testValidator(self):
114        """ Test the inputs when validators had been defined """
115        # Background, Volume and Scale should be positive
116        txtEdit_positive = [self.widget.txtBackground,
117                            self.widget.txtTotalVolume,
118                            self.widget.txtScale]
119
120        for item in txtEdit_positive:
121            item.setText('-1')
122            state = item.validator().validate(item.text(), 0)[0]
123            self.assertEqual(state, QtGui.QValidator.Invalid)
124
125        for item in txtEdit_positive:
126            item.setText('2')
127            state = item.validator().validate(item.text(), 0)[0]
128            self.assertEqual(state, QtGui.QValidator.Acceptable)
129
130        for item in txtEdit_positive:
131            item.setText('abc')
132            state = item.validator().validate(item.text(), 0)[0]
133            self.assertEqual(state, QtGui.QValidator.Invalid)
134
135        # Fraction of spin up between 0 and 1
136        txtEdit_0_1 = [self.widget.txtUpFracIn, self.widget.txtUpFracOut]
137
138        for item in txtEdit_0_1:
139            item.setText('-1.04546')
140            state = item.validator().validate(item.text(), 0)[0]
141            self.assertEqual(state, QtGui.QValidator.Invalid)
142
143        for item in txtEdit_0_1:
144            item.setText('2.00000')
145            state = item.validator().validate(item.text(), 0)[0]
146            self.assertEqual(state, QtGui.QValidator.Invalid)
147
148        for item in txtEdit_0_1:
149            item.setText('0.000000005')
150            state = item.validator().validate(item.text(), 0)[0]
151            self.assertEqual(state, QtGui.QValidator.Acceptable)
152
153        # Test text edits related to Q:
154        # 0< Qmax < 1000, 2 <= Qbins <= 1000
155        txtEdit_q_values = [self.widget.txtNoQBins, self.widget.txtQxMax]
156        for item in txtEdit_q_values:
157            item.setText('-1.01')
158            state = item.validator().validate(item.text(), 0)[0]
159            self.assertEqual(state, QtGui.QValidator.Invalid)
160
161        for item in txtEdit_q_values:
162            item.setText('1500.01')
163            state = item.validator().validate(item.text(), 0)[0]
164            self.assertEqual(state, QtGui.QValidator.Invalid)
165
166        self.widget.txtNoQBins.setText('1.5')
167        self.assertEqual(
168            self.widget.txtNoQBins.validator().validate(item.text(), 0)[0],
169            QtGui.QValidator.Invalid)
170
171        self.widget.txtQxMax.setText('1.5')
172        self.assertEqual(
173            self.widget.txtQxMax.validator().validate(item.text(), 0)[0],
174            QtGui.QValidator.Acceptable)
175
176    def testLoadedSLDData(self):
177        """
178        Load sld data and check modifications of GUI
179        """
180        filename = os.path.join("UnitTesting", "sld_file.sld")
181        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
182        self.widget.loadFile()
183
184        # check modification of text in Load button
185        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
186        # wait a bit for data to be loaded
187        time.sleep(0.1)
188        QtWidgets.qApp.processEvents()
189
190        # check updated values in ui, read from loaded file
191        self.assertEqual(self.widget.txtData.text(), 'sld_file.sld')
192        self.assertEqual(self.widget.txtTotalVolume.text(), '402408.0')
193        self.assertEqual(self.widget.txtNoPixels.text(), '552')
194        self.assertFalse(self.widget.txtNoPixels.isEnabled())
195
196        # check disabled TextEdits according to data format
197        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
198        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
199        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
200        self.assertFalse(self.widget.txtNoPixels.isEnabled())
201
202        # check enabled draw buttons
203        self.assertTrue(self.widget.cmdDraw.isEnabled())
204        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
205        self.widget.show()
206        self.assertTrue(self.widget.isVisible())
207        self.assertFalse(self.widget.cbOptionsCalc.isVisible())
208
209        # check that text of loadButton is back to initial state
210        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
211        # check values and enabled / disabled for
212        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
213        self.assertFalse(self.widget.txtMx.isEnabled())
214        self.assertAlmostEqual(float(self.widget.txtMx.text()), 8.0795e-07, 4)
215        self.assertFalse(self.widget.txtMy.isEnabled())
216        self.assertAlmostEqual(float(self.widget.txtMy.text()), 8.0795e-07, 4)
217        self.assertFalse(self.widget.txtMz.isEnabled())
218        self.assertAlmostEqual(float(self.widget.txtMz.text()), 3.1739e-07, 4)
219        self.assertTrue(self.widget.txtNucl.isEnabled())
220        self.assertEqual(self.widget.txtNucl.text(), '0')
221
222        self.assertFalse(self.widget.txtXnodes.isEnabled())
223        self.assertEqual(self.widget.txtXnodes.text(), '10')
224        self.assertFalse(self.widget.txtYnodes.isEnabled())
225        self.assertEqual(self.widget.txtYnodes.text(), '10')
226        self.assertFalse(self.widget.txtZnodes.isEnabled())
227        self.assertEqual(self.widget.txtZnodes.text(), '10')
228
229        self.assertFalse(self.widget.txtXstepsize.isEnabled())
230        self.assertEqual(self.widget.txtXstepsize.text(), '9')
231        self.assertFalse(self.widget.txtYstepsize.isEnabled())
232        self.assertEqual(self.widget.txtYstepsize.text(), '9')
233        self.assertFalse(self.widget.txtZstepsize.isEnabled())
234        self.assertEqual(self.widget.txtZstepsize.text(), '9')
235
236        self.assertTrue(self.widget.sld_data.is_data)
237
238        # self.assertTrue(self.widget.trigger_plot_3d)
239
240
241    def testLoadedPDBButton(self):
242        """
243        Load pdb data and check modifications of GUI
244        """
245        filename = os.path.join("UnitTesting", "diamdsml.pdb")
246
247        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
248        self.widget.loadFile()
249
250        # check modification of text in Load button
251        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
252
253        time.sleep(1)
254        QtWidgets.qApp.processEvents()
255
256        # check updated values in ui, read from loaded file
257        # TODO to be changed
258        self.assertEqual(self.widget.txtData.text(), 'diamdsml.pdb')
259        self.assertAlmostEqual(float(self.widget.txtTotalVolume.text()), 170.95058, 5)
260        self.assertEqual(self.widget.txtNoPixels.text(), '18')
261
262        # check disabled TextEdits according to data format
263        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
264        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
265        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
266        self.assertFalse(self.widget.txtNoPixels.isEnabled())
267        # check enabled draw buttons
268        self.assertTrue(self.widget.cmdDraw.isEnabled())
269        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
270        # fixed orientation
271        self.widget.show()
272        self.assertTrue(self.widget.isVisible())
273        self.assertTrue(self.widget.cbOptionsCalc.isVisible())
274        # check that text of loadButton is back to initial state
275        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
276        self.assertTrue(self.widget.cmdLoad.isEnabled())
277
278        # check values and enabled / disabled for
279        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
280        self.assertFalse(self.widget.txtMx.isEnabled())
281        self.assertEqual(self.widget.txtMx.text(), '0')
282        self.assertFalse(self.widget.txtMy.isEnabled())
283        self.assertEqual(self.widget.txtMy.text(), '0')
284        self.assertFalse(self.widget.txtMz.isEnabled())
285        self.assertEqual(self.widget.txtMz.text(), '0')
286        self.assertFalse(self.widget.txtNucl.isEnabled())
287        self.assertAlmostEqual(float(self.widget.txtNucl.text()), 7.0003e-06, 4)
288
289        self.assertFalse(self.widget.txtXnodes.isEnabled())
290        self.assertEqual(self.widget.txtXnodes.text(), 'NaN')
291        self.assertFalse(self.widget.txtYnodes.isEnabled())
292        self.assertEqual(self.widget.txtYnodes.text(), 'NaN')
293        self.assertFalse(self.widget.txtZnodes.isEnabled())
294        self.assertEqual(self.widget.txtZnodes.text(), 'NaN')
295
296        self.assertFalse(self.widget.txtXstepsize.isEnabled())
297        self.assertEqual(self.widget.txtXstepsize.text(), 'NaN')
298        self.assertFalse(self.widget.txtYstepsize.isEnabled())
299        self.assertEqual(self.widget.txtYstepsize.text(), 'NaN')
300        self.assertFalse(self.widget.txtZstepsize.isEnabled())
301        self.assertEqual(self.widget.txtZstepsize.text(), 'NaN')
302
303        self.assertTrue(self.widget.sld_data.is_data)
304
305    # TODO
306    def testLoadedOMFButton(self):
307        """
308        Load omf data and check modifications of GUI
309        """
310        filename = os.path.join("UnitTesting", "A_Raw_Example-1.omf")
311
312        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
313        self.widget.loadFile()
314        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
315        time.sleep(2)
316        QtWidgets.qApp.processEvents()
317
318        self.assertEqual(self.widget.txtData.text(), 'A_Raw_Example-1.omf')
319        self.assertEqual(self.widget.txtTotalVolume.text(), '128000000.0')
320        self.assertEqual(self.widget.txtNoPixels.text(), '16000')
321
322        # check disabled TextEdits according to data format
323        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
324        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
325        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
326        self.assertFalse(self.widget.txtNoPixels.isEnabled())
327
328        # check enabled draw buttons
329        self.assertTrue(self.widget.cmdDraw.isEnabled())
330        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
331
332        # check that text of loadButton is back to initial state
333        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
334        self.assertTrue(self.widget.cmdLoad.isEnabled())
335
336        # check values and enabled / disabled for
337        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
338        self.assertFalse(self.widget.txtMx.isEnabled())
339        self.assertAlmostEqual(float(self.widget.txtMx.text()), 7.855e-09, 4)
340        self.assertFalse(self.widget.txtMy.isEnabled())
341        self.assertAlmostEqual(float(self.widget.txtMy.text()), 4.517e-08, 4)
342        self.assertFalse(self.widget.txtMz.isEnabled())
343        self.assertAlmostEqual(float(self.widget.txtMz.text()), 9.9511e-10, 4)
344        self.assertTrue(self.widget.txtNucl.isEnabled())
345        self.assertEqual(self.widget.txtNucl.text(), '0')
346
347        self.assertFalse(self.widget.txtXnodes.isEnabled())
348        self.assertEqual(self.widget.txtXnodes.text(), '40')
349        self.assertFalse(self.widget.txtYnodes.isEnabled())
350        self.assertEqual(self.widget.txtYnodes.text(), '40')
351        self.assertFalse(self.widget.txtZnodes.isEnabled())
352        self.assertEqual(self.widget.txtZnodes.text(), '10')
353
354        self.assertFalse(self.widget.txtXstepsize.isEnabled())
355        self.assertEqual(self.widget.txtXstepsize.text(), '20')
356        self.assertFalse(self.widget.txtYstepsize.isEnabled())
357        self.assertEqual(self.widget.txtYstepsize.text(), '20')
358        self.assertFalse(self.widget.txtZstepsize.isEnabled())
359        self.assertEqual(self.widget.txtZstepsize.text(), '20')
360
361    def testReset(self):
362        """
363        Test reset button when GUI has been modified
364        """
365        # modify gui
366        self.widget.txtBackground.setText('50.0')
367        # apply reset
368        self.widget.onReset()
369        # check that we get back to the initial state
370        self.assertEqual(self.widget.txtBackground.text(), '0.0')
371
372    # TODO check plots
373    def testCompute(self):
374        """
375        Test compute button
376        """
377        # load data
378        filename = os.path.join("UnitTesting", "diamdsml.pdb")
379
380        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
381        self.widget.loadFile()
382        time.sleep(1)
383        QTest.mouseClick(self.widget.cmdCompute, Qt.LeftButton)
384        # check modification of text of Compute button
385        self.assertEqual(self.widget.cmdCompute.text(), 'Wait...')
386        self.assertFalse(self.widget.cmdCompute.isEnabled())
387
388        #self.widget.complete([numpy.ones(1), numpy.zeros(1), numpy.zeros(1)], update=None)
389        #self.assertEqual(self.widget.cmdCompute.text(), 'Compute')
390        #self.assertTrue(self.widget.cmdCompute.isEnabled())
391
392    # TODO
393    def testDrawButton(self):
394        """
395        Test Draw buttons for 3D plots with and without arrows
396        """
397        self.assertFalse(self.widget.cmdDraw.isEnabled())
398        filename = os.path.join("UnitTesting", "diamdsml.pdb")
399        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename,''])
400        self.widget.loadFile()
401        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
402        time.sleep(1)
403        QtWidgets.qApp.processEvents()
404
405        self.assertTrue(self.widget.cmdDraw.isEnabled())
406        QTest.mouseClick(self.widget.cmdDraw, Qt.LeftButton)
407
408        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
409        QTest.mouseClick(self.widget.cmdDrawpoints, Qt.LeftButton)
410
411    def testCloseButton(self):
412        closeButton = self.widget.cmdClose
413        QTest.mouseClick(closeButton, Qt.LeftButton)
414
415    def testSaveFile(self):
416        """
417        Test Save feature to .sld file
418        """
419        filename = os.path.join("UnitTesting", "sld_file.sld")
420
421        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
422        self.widget.loadFile()
423
424        time.sleep(0.1)
425        QtWidgets.qApp.processEvents()
426
427        filename1 = "test"
428        QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=[filename1, ''])
429
430        #QTest.mouseClick(self.widget.cmdSave, Qt.LeftButton)
431        self.widget.onSaveFile()
432        QtWidgets.qApp.processEvents()
433
434        self.assertTrue(os.path.isfile(filename1 + '.sld'))
435        self.assertTrue(os.path.getsize(filename1 + '.sld') > 0)
436
437        os.remove("test.sld")
438
439
440class Plotter3DTest(unittest.TestCase):
441    """ Test 3D plots in real space.
442    The implementation is temporarily in the same script as the Generic SAS
443    calculator"""
444    def setUp(self):
445        """create"""
446        parent_test = MagicMock()
447        self.plotter = Plotter3D(parent=parent_test, graph_title='test')
448        self.data = sas_gen.MagSLD(numpy.array([1.0, 2.0, 3.0, 4.0]),
449                                   numpy.array([10.0, 11.0, 12.0, 13.0]),
450                                   numpy.array([0.1, 0.2, 0.3, 0.4]),
451                                   numpy.zeros(4),
452                                   numpy.zeros(4),
453                                   numpy.zeros(4),
454                                   numpy.zeros(4))
455        self.data.sld_n = [0, 6.97e-06, 6.97e-06, 6.97e-06]
456        self.data.set_pix_type('pixel')
457        self.data.pix_symbol = numpy.repeat('pixel', 4)
458
459    def tearDown(self):
460        """ Destroy"""
461        self.plotter = None
462        self.data = None
463
464    def testDataProperty(self):
465        self.plotter.data = self.data
466        self.assertEqual(self.plotter.data, self.data)
467        self.assertTrue(self.plotter.graph_title, 'test')
468        self.assertFalse(self.plotter.data.has_conect)
469
470    def testShowNoPlot(self):
471        FigureCanvas.draw_idle = MagicMock()
472        FigureCanvas.draw = MagicMock()
473        self.plotter.showPlot(data=None)
474        self.assertFalse(FigureCanvas.draw_idle.called)
475        self.assertFalse(FigureCanvas.draw.called)
476
477    def testShow3DPlot(self):
478        FigureCanvas.draw = MagicMock()
479        Axes3D.plot = MagicMock()
480
481        self.plotter.data = self.data
482        self.plotter.showPlot(data=self.plotter.data)
483        self.assertTrue(Axes3D.plot.called)
484        self.assertTrue(FigureCanvas.draw.called)
485
486
487if __name__ == "__main__":
488    unittest.main()
Note: See TracBrowser for help on using the repository browser.