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

ESS_GUIESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since 63467b6 was 30e0be0, checked in by Piotr Rozyczko <piotr.rozyczko@…>, 6 years ago

Updates to the scattering calculator SASVIEW-1147

  • Property mode set to 100644
File size: 20.1 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 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(), 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        # check updated values in ui, read from loaded file
189        self.assertEqual(self.widget.txtData.text(), 'sld_file.sld')
190        self.assertEqual(self.widget.txtTotalVolume.text(), '402408.0')
191        self.assertEqual(self.widget.txtNoPixels.text(), '552')
192        self.assertFalse(self.widget.txtNoPixels.isEnabled())
193
194        # check disabled TextEdits according to data format
195        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
196        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
197        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
198        self.assertFalse(self.widget.txtNoPixels.isEnabled())
199
200        # check enabled draw buttons
201        self.assertTrue(self.widget.cmdDraw.isEnabled())
202        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
203        self.widget.show()
204        self.assertTrue(self.widget.isVisible())
205        self.assertFalse(self.widget.cbOptionsCalc.isVisible())
206
207        # check that text of loadButton is back to initial state
208        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
209        # check values and enabled / disabled for
210        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
211        self.assertFalse(self.widget.txtMx.isEnabled())
212        self.assertAlmostEqual(float(self.widget.txtMx.text()), 8.0795e-07, 4)
213        self.assertFalse(self.widget.txtMy.isEnabled())
214        self.assertAlmostEqual(float(self.widget.txtMy.text()), 8.0795e-07, 4)
215        self.assertFalse(self.widget.txtMz.isEnabled())
216        self.assertAlmostEqual(float(self.widget.txtMz.text()), 3.1739e-07, 4)
217        self.assertTrue(self.widget.txtNucl.isEnabled())
218        self.assertEqual(self.widget.txtNucl.text(), '0')
219
220        self.assertFalse(self.widget.txtXnodes.isEnabled())
221        self.assertEqual(self.widget.txtXnodes.text(), '10')
222        self.assertFalse(self.widget.txtYnodes.isEnabled())
223        self.assertEqual(self.widget.txtYnodes.text(), '10')
224        self.assertFalse(self.widget.txtZnodes.isEnabled())
225        self.assertEqual(self.widget.txtZnodes.text(), '10')
226
227        self.assertFalse(self.widget.txtXstepsize.isEnabled())
228        self.assertEqual(self.widget.txtXstepsize.text(), '9')
229        self.assertFalse(self.widget.txtYstepsize.isEnabled())
230        self.assertEqual(self.widget.txtYstepsize.text(), '9')
231        self.assertFalse(self.widget.txtZstepsize.isEnabled())
232        self.assertEqual(self.widget.txtZstepsize.text(), '9')
233
234        self.assertTrue(self.widget.sld_data.is_data)
235
236        # self.assertTrue(self.widget.trigger_plot_3d)
237
238
239    def testLoadedPDBButton(self):
240        """
241        Load pdb data and check modifications of GUI
242        """
243        filename = os.path.join("UnitTesting", "diamdsml.pdb")
244
245        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
246        self.widget.loadFile()
247
248        # check modification of text in Load button
249        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
250
251        time.sleep(1)
252        # check updated values in ui, read from loaded file
253        # TODO to be changed
254        self.assertEqual(self.widget.txtData.text(), 'diamdsml.pdb')
255        self.assertEqual(self.widget.txtTotalVolume.text(), '170.950584161')
256        self.assertEqual(self.widget.txtNoPixels.text(), '18')
257
258        # check disabled TextEdits according to data format
259        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
260        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
261        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
262        self.assertFalse(self.widget.txtNoPixels.isEnabled())
263        # check enabled draw buttons
264        self.assertTrue(self.widget.cmdDraw.isEnabled())
265        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
266        # fixed orientation
267        self.widget.show()
268        self.assertTrue(self.widget.isVisible())
269        self.assertTrue(self.widget.cbOptionsCalc.isVisible())
270        # check that text of loadButton is back to initial state
271        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
272        self.assertTrue(self.widget.cmdLoad.isEnabled())
273
274        # check values and enabled / disabled for
275        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
276        self.assertFalse(self.widget.txtMx.isEnabled())
277        self.assertEqual(self.widget.txtMx.text(), '0')
278        self.assertFalse(self.widget.txtMy.isEnabled())
279        self.assertEqual(self.widget.txtMy.text(), '0')
280        self.assertFalse(self.widget.txtMz.isEnabled())
281        self.assertEqual(self.widget.txtMz.text(), '0')
282        self.assertFalse(self.widget.txtNucl.isEnabled())
283        self.assertAlmostEqual(float(self.widget.txtNucl.text()), 7.0003e-06, 4)
284
285        self.assertFalse(self.widget.txtXnodes.isEnabled())
286        self.assertEqual(self.widget.txtXnodes.text(), 'NaN')
287        self.assertFalse(self.widget.txtYnodes.isEnabled())
288        self.assertEqual(self.widget.txtYnodes.text(), 'NaN')
289        self.assertFalse(self.widget.txtZnodes.isEnabled())
290        self.assertEqual(self.widget.txtZnodes.text(), 'NaN')
291
292        self.assertFalse(self.widget.txtXstepsize.isEnabled())
293        self.assertEqual(self.widget.txtXstepsize.text(), 'NaN')
294        self.assertFalse(self.widget.txtYstepsize.isEnabled())
295        self.assertEqual(self.widget.txtYstepsize.text(), 'NaN')
296        self.assertFalse(self.widget.txtZstepsize.isEnabled())
297        self.assertEqual(self.widget.txtZstepsize.text(), 'NaN')
298
299        self.assertTrue(self.widget.sld_data.is_data)
300
301    # TODO
302    def testLoadedOMFButton(self):
303        """
304        Load omf data and check modifications of GUI
305        """
306        filename = os.path.join("UnitTesting", "A_Raw_Example-1.omf")
307
308        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
309        self.widget.loadFile()
310        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
311        time.sleep(2)
312
313        self.assertEqual(self.widget.txtData.text(), 'A_Raw_Example-1.omf')
314        self.assertEqual(self.widget.txtTotalVolume.text(), '128000000.0')
315        self.assertEqual(self.widget.txtNoPixels.text(), '16000')
316
317        # check disabled TextEdits according to data format
318        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
319        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
320        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
321        self.assertFalse(self.widget.txtNoPixels.isEnabled())
322
323        # check enabled draw buttons
324        self.assertTrue(self.widget.cmdDraw.isEnabled())
325        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
326
327        # check that text of loadButton is back to initial state
328        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
329        self.assertTrue(self.widget.cmdLoad.isEnabled())
330
331        # check values and enabled / disabled for
332        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
333        self.assertFalse(self.widget.txtMx.isEnabled())
334        self.assertAlmostEqual(float(self.widget.txtMx.text()), 7.855e-09, 4)
335        self.assertFalse(self.widget.txtMy.isEnabled())
336        self.assertAlmostEqual(float(self.widget.txtMy.text()), 4.517e-08, 4)
337        self.assertFalse(self.widget.txtMz.isEnabled())
338        self.assertAlmostEqual(float(self.widget.txtMz.text()), 9.9511e-10, 4)
339        self.assertTrue(self.widget.txtNucl.isEnabled())
340        self.assertEqual(self.widget.txtNucl.text(), '0')
341
342        self.assertFalse(self.widget.txtXnodes.isEnabled())
343        self.assertEqual(self.widget.txtXnodes.text(), '40')
344        self.assertFalse(self.widget.txtYnodes.isEnabled())
345        self.assertEqual(self.widget.txtYnodes.text(), '40')
346        self.assertFalse(self.widget.txtZnodes.isEnabled())
347        self.assertEqual(self.widget.txtZnodes.text(), '10')
348
349        self.assertFalse(self.widget.txtXstepsize.isEnabled())
350        self.assertEqual(self.widget.txtXstepsize.text(), '20')
351        self.assertFalse(self.widget.txtYstepsize.isEnabled())
352        self.assertEqual(self.widget.txtYstepsize.text(), '20')
353        self.assertFalse(self.widget.txtZstepsize.isEnabled())
354        self.assertEqual(self.widget.txtZstepsize.text(), '20')
355
356    def testReset(self):
357        """
358        Test reset button when GUI has been modified
359        """
360        # modify gui
361        self.widget.txtBackground.setText('50.0')
362        # apply reset
363        self.widget.onReset()
364        # check that we get back to the initial state
365        self.assertEqual(self.widget.txtBackground.text(), '0.0')
366
367    # TODO check plots
368    def testCompute(self):
369        """
370        Test compute button
371        """
372        # load data
373        filename = os.path.join("UnitTesting", "diamdsml.pdb")
374
375        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
376        self.widget.loadFile()
377        time.sleep(1)
378        QTest.mouseClick(self.widget.cmdCompute, Qt.LeftButton)
379        # check modification of text of Compute button
380        self.assertEqual(self.widget.cmdCompute.text(), 'Wait...')
381        self.assertFalse(self.widget.cmdCompute.isEnabled())
382
383        #self.widget.complete([numpy.ones(1), numpy.zeros(1), numpy.zeros(1)], update=None)
384        #self.assertEqual(self.widget.cmdCompute.text(), 'Compute')
385        #self.assertTrue(self.widget.cmdCompute.isEnabled())
386
387    # TODO
388    def testDrawButton(self):
389        """
390        Test Draw buttons for 3D plots with and without arrows
391        """
392        self.assertFalse(self.widget.cmdDraw.isEnabled())
393        filename = os.path.join("UnitTesting", "diamdsml.pdb")
394        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename,''])
395        self.widget.loadFile()
396        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
397        time.sleep(1)
398
399        self.assertTrue(self.widget.cmdDraw.isEnabled())
400        QTest.mouseClick(self.widget.cmdDraw, Qt.LeftButton)
401
402        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
403        QTest.mouseClick(self.widget.cmdDrawpoints, Qt.LeftButton)
404
405    def testCloseButton(self):
406        closeButton = self.widget.cmdClose
407        QTest.mouseClick(closeButton, Qt.LeftButton)
408
409    def testSaveFile(self):
410        """
411        Test Save feature to .sld file
412        """
413        filename = os.path.join("UnitTesting", "sld_file.sld")
414
415        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=[filename, ''])
416        self.widget.loadFile()
417
418        time.sleep(0.1)
419
420        filename1 = "test"
421        QtWidgets.QFileDialog.getSaveFileName = MagicMock(return_value=[filename1, ''])
422
423        QTest.mouseClick(self.widget.cmdSave, Qt.LeftButton)
424        self.widget.onSaveFile()
425        self.assertTrue(os.path.isfile(filename1 + '.sld'))
426        self.assertTrue(os.path.getsize(filename1 + '.sld') > 0)
427
428        os.remove("test.sld")
429
430
431class Plotter3DTest(unittest.TestCase):
432    """ Test 3D plots in real space.
433    The implementation is temporarily in the same script as the Generic SAS
434    calculator"""
435    def setUp(self):
436        """create"""
437        parent_test = MagicMock()
438        self.plotter = Plotter3D(parent=parent_test, graph_title='test')
439        self.data = sas_gen.MagSLD(numpy.array([1.0, 2.0, 3.0, 4.0]),
440                                   numpy.array([10.0, 11.0, 12.0, 13.0]),
441                                   numpy.array([0.1, 0.2, 0.3, 0.4]),
442                                   numpy.zeros(4),
443                                   numpy.zeros(4),
444                                   numpy.zeros(4),
445                                   numpy.zeros(4))
446        self.data.sld_n = [0, 6.97e-06, 6.97e-06, 6.97e-06]
447        self.data.set_pix_type('pixel')
448        self.data.pix_symbol = numpy.repeat('pixel', 4)
449
450    def tearDown(self):
451        """ Destroy"""
452        self.plotter = None
453        self.data = None
454
455    def testDataProperty(self):
456        self.plotter.data = self.data
457        self.assertEqual(self.plotter.data, self.data)
458        self.assertTrue(self.plotter.graph_title, 'test')
459        self.assertFalse(self.plotter.data.has_conect)
460
461    def testShowNoPlot(self):
462        FigureCanvas.draw_idle = MagicMock()
463        FigureCanvas.draw = MagicMock()
464        self.plotter.showPlot(data=None)
465        self.assertFalse(FigureCanvas.draw_idle.called)
466        self.assertFalse(FigureCanvas.draw.called)
467
468    def testShow3DPlot(self):
469        FigureCanvas.draw = MagicMock()
470        Axes3D.plot = MagicMock()
471
472        self.plotter.data = self.data
473        self.plotter.showPlot(data=self.plotter.data)
474        self.assertTrue(Axes3D.plot.called)
475        self.assertTrue(FigureCanvas.draw.called)
476
477
478if __name__ == "__main__":
479    unittest.main()
Note: See TracBrowser for help on using the repository browser.