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

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 50bfab0 was 53c771e, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Converted unit tests

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