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

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 7969b9c was 7fb471d, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Update for unit tests and minor functionality quirks

  • Property mode set to 100644
File size: 19.8 KB
Line 
1import sys
2import time
3import numpy
4import unittest
5from PyQt4 import QtGui
6from PyQt4.QtTest import QTest
7
8from PyQt4.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_qt4agg 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 QtGui.QApplication.instance():
27    app = QtGui.QApplication(sys.argv)
28
29
30class GenericScatteringCalculatorTest(unittest.TestCase):
31    """Test the GenericScatteringCalculator"""
32    def setUp(self):
33        """Create the GenericScatteringCalculator"""
34        class dummy_manager(object):
35            def communicator(self):
36                return Communicate()
37
38        self.widget = GenericScatteringCalculator(dummy_manager())
39
40    def tearDown(self):
41        """Destroy the GenericScatteringCalculator"""
42        self.widget.close()
43        self.widget = None
44
45
46    def testDefaults(self):
47        """Test the GUI in its default state"""
48        self.assertIsInstance(self.widget, QtGui.QWidget)
49        self.assertEqual(self.widget.windowTitle(), "Generic SAS Calculator")
50
51        self.assertIn('trigger_plot_3d', dir(self.widget))
52
53        # Buttons
54        self.assertEqual(self.widget.txtData.text(), "Default SLD Profile")
55        self.assertEqual(self.widget.cmdLoad.text(), "Load")
56        self.assertEqual(self.widget.cmdDraw.text(), "Draw")
57        self.assertEqual(self.widget.cmdCompute.text(), "Compute")
58        self.assertEqual(self.widget.cmdReset.text(), "Reset")
59        self.assertEqual(self.widget.cmdClose.text(), "Close")
60        self.assertEqual(self.widget.cmdHelp.text(), "Help")
61        self.assertEqual(self.widget.cmdDrawpoints.text(), "Draw Points")
62        self.assertEqual(self.widget.cmdSave.text(), "Save SLD Data")
63
64        self.assertEqual(self.widget.txtBackground.text(), '0.0')
65        self.assertEqual(self.widget.txtScale.text(), '1.0')
66        self.assertEqual(self.widget.txtSolventSLD.text(), '0.0')
67        self.assertEqual(self.widget.txtTotalVolume.text(), '216000.0')
68        self.assertEqual(self.widget.txtUpFracIn.text(), '1.0')
69        self.assertEqual(self.widget.txtUpFracOut.text(), '1.0')
70        self.assertEqual(self.widget.txtUpTheta.text(), '0.0')
71        self.assertEqual(self.widget.txtNoQBins.text(), '50')
72        self.assertEqual(self.widget.txtQxMax.text(), '0.3')
73        self.assertEqual(self.widget.txtNoPixels.text(), '1000')
74        self.assertEqual(self.widget.txtMx.text(), '0')
75        self.assertEqual(self.widget.txtMy.text(), '0')
76        self.assertEqual(self.widget.txtMz.text(), '0')
77        self.assertEqual(self.widget.txtNucl.text(), '6.97e-06')
78        self.assertEqual(self.widget.txtXnodes.text(), '10')
79        self.assertEqual(self.widget.txtYnodes.text(), '10')
80        self.assertEqual(self.widget.txtZnodes.text(), '10')
81        self.assertEqual(self.widget.txtXstepsize.text(), '6')
82        self.assertEqual(self.widget.txtYstepsize.text(), '6')
83        self.assertEqual(self.widget.txtZstepsize.text(), '6')
84
85        # Comboboxes
86        self.assertFalse(self.widget.cbOptionsCalc.isVisible())
87        self.assertFalse(self.widget.cbOptionsCalc.isEditable())
88        self.assertEqual(self.widget.cbOptionsCalc.count(), 2)
89        self.assertEqual(self.widget.cbOptionsCalc.currentIndex(), 0)
90        self.assertListEqual([self.widget.cbOptionsCalc.itemText(i) for i in
91                              range(self.widget.cbOptionsCalc.count())],
92                             ['Fixed orientation', 'Debye full avg.'])
93
94        self.assertEqual(self.widget.cbShape.count(), 2)
95        self.assertEqual(self.widget.cbShape.currentIndex(), 0)
96        self.assertListEqual([self.widget.cbShape.itemText(i) for i in
97                              range(self.widget.cbShape.count())],
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.onHelp()
108
109    def testValidator(self):
110        """ Test the inputs when validators had been defined """
111        # Background, Volume and Scale should be positive
112        txtEdit_positive = [self.widget.txtBackground,
113                            self.widget.txtTotalVolume,
114                            self.widget.txtScale]
115
116        for item in txtEdit_positive:
117            item.setText('-1')
118            state = item.validator().validate(item.text(), 0)[0]
119            self.assertEqual(state, QtGui.QValidator.Invalid)
120
121        for item in txtEdit_positive:
122            item.setText('2')
123            state = item.validator().validate(item.text(), 0)[0]
124            self.assertEqual(state, QtGui.QValidator.Acceptable)
125
126        for item in txtEdit_positive:
127            item.setText('abc')
128            state = item.validator().validate(item.text(), 0)[0]
129            self.assertEqual(state, QtGui.QValidator.Invalid)
130
131        # Fraction of spin up between 0 and 1
132        txtEdit_0_1 = [self.widget.txtUpFracIn, self.widget.txtUpFracOut]
133
134        for item in txtEdit_0_1:
135            item.setText('-1.04546')
136            state = item.validator().validate(item.text(), 0)[0]
137            self.assertEqual(state, QtGui.QValidator.Invalid)
138
139        for item in txtEdit_0_1:
140            item.setText('2.00000')
141            state = item.validator().validate(item.text(), 0)[0]
142            self.assertEqual(state, QtGui.QValidator.Invalid)
143
144        for item in txtEdit_0_1:
145            item.setText('0.000000005')
146            state = item.validator().validate(item.text(), 0)[0]
147            self.assertEqual(state, QtGui.QValidator.Acceptable)
148
149        # Test text edits related to Q:
150        # 0< Qmax < 1000, 2 <= Qbins <= 1000
151        txtEdit_q_values = [self.widget.txtNoQBins, self.widget.txtQxMax]
152        for item in txtEdit_q_values:
153            item.setText('-1.01')
154            state = item.validator().validate(item.text(), 0)[0]
155            self.assertEqual(state, QtGui.QValidator.Invalid)
156
157        for item in txtEdit_q_values:
158            item.setText('1500.01')
159            state = item.validator().validate(item.text(), 0)[0]
160            self.assertEqual(state, QtGui.QValidator.Invalid)
161
162        self.widget.txtNoQBins.setText('1.5')
163        self.assertEqual(
164            self.widget.txtNoQBins.validator().validate(item.text(), 0)[0],
165            QtGui.QValidator.Invalid)
166
167        self.widget.txtQxMax.setText('1.5')
168        self.assertEqual(
169            self.widget.txtQxMax.validator().validate(item.text(), 0)[0],
170            QtGui.QValidator.Acceptable)
171
172    def testLoadedSLDData(self):
173        """
174        Load sld data and check modifications of GUI
175        """
176        filename = os.path.join("UnitTesting", "sld_file.sld")
177        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)
178        self.widget.loadFile()
179
180        # check modification of text in Load button
181        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
182        # wait a bit for data to be loaded
183        time.sleep(0.1)
184        # check updated values in ui, read from loaded file
185        self.assertEqual(self.widget.txtData.text(), 'sld_file.sld')
186        self.assertEqual(self.widget.txtTotalVolume.text(), '402408.0')
187        self.assertEqual(self.widget.txtNoPixels.text(), '552')
188        self.assertFalse(self.widget.txtNoPixels.isEnabled())
189
190        # check disabled TextEdits according to data format
191        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
192        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
193        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
194        self.assertFalse(self.widget.txtNoPixels.isEnabled())
195
196        # check enabled draw buttons
197        self.assertTrue(self.widget.cmdDraw.isEnabled())
198        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
199        self.widget.show()
200        self.assertTrue(self.widget.isVisible())
201        self.assertFalse(self.widget.cbOptionsCalc.isVisible())
202
203        # check that text of loadButton is back to initial state
204        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
205        # check values and enabled / disabled for
206        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
207        self.assertFalse(self.widget.txtMx.isEnabled())
208        self.assertAlmostEqual(float(self.widget.txtMx.text()), 8.0795e-07, 4)
209        self.assertFalse(self.widget.txtMy.isEnabled())
210        self.assertAlmostEqual(float(self.widget.txtMy.text()), 8.0795e-07, 4)
211        self.assertFalse(self.widget.txtMz.isEnabled())
212        self.assertAlmostEqual(float(self.widget.txtMz.text()), 3.1739e-07, 4)
213        self.assertTrue(self.widget.txtNucl.isEnabled())
214        self.assertEqual(self.widget.txtNucl.text(), '0')
215
216        self.assertFalse(self.widget.txtXnodes.isEnabled())
217        self.assertEqual(self.widget.txtXnodes.text(), '10')
218        self.assertFalse(self.widget.txtYnodes.isEnabled())
219        self.assertEqual(self.widget.txtYnodes.text(), '10')
220        self.assertFalse(self.widget.txtZnodes.isEnabled())
221        self.assertEqual(self.widget.txtZnodes.text(), '10')
222
223        self.assertFalse(self.widget.txtXstepsize.isEnabled())
224        self.assertEqual(self.widget.txtXstepsize.text(), '9')
225        self.assertFalse(self.widget.txtYstepsize.isEnabled())
226        self.assertEqual(self.widget.txtYstepsize.text(), '9')
227        self.assertFalse(self.widget.txtZstepsize.isEnabled())
228        self.assertEqual(self.widget.txtZstepsize.text(), '9')
229
230        self.assertTrue(self.widget.sld_data.is_data)
231
232        # self.assertTrue(self.widget.trigger_plot_3d)
233
234
235    def testLoadedPDBButton(self):
236        """
237        Load pdb data and check modifications of GUI
238        """
239        filename = os.path.join("UnitTesting", "diamdsml.pdb")
240
241        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)
242        self.widget.loadFile()
243
244        # check modification of text in Load button
245        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
246
247        time.sleep(1)
248        # check updated values in ui, read from loaded file
249        # TODO to be changed
250        self.assertEqual(self.widget.txtData.text(), 'diamdsml.pdb')
251        self.assertEqual(self.widget.txtTotalVolume.text(), '170.950584161')
252        self.assertEqual(self.widget.txtNoPixels.text(), '18')
253
254        # check disabled TextEdits according to data format
255        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
256        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
257        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
258        self.assertFalse(self.widget.txtNoPixels.isEnabled())
259        # check enabled draw buttons
260        self.assertTrue(self.widget.cmdDraw.isEnabled())
261        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
262        # fixed orientation
263        self.widget.show()
264        self.assertTrue(self.widget.isVisible())
265        self.assertTrue(self.widget.cbOptionsCalc.isVisible())
266        # check that text of loadButton is back to initial state
267        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
268        self.assertTrue(self.widget.cmdLoad.isEnabled())
269
270        # check values and enabled / disabled for
271        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
272        self.assertFalse(self.widget.txtMx.isEnabled())
273        self.assertEqual(self.widget.txtMx.text(), '0')
274        self.assertFalse(self.widget.txtMy.isEnabled())
275        self.assertEqual(self.widget.txtMy.text(), '0')
276        self.assertFalse(self.widget.txtMz.isEnabled())
277        self.assertEqual(self.widget.txtMz.text(), '0')
278        self.assertFalse(self.widget.txtNucl.isEnabled())
279        self.assertAlmostEqual(float(self.widget.txtNucl.text()), 7.0003e-06, 4)
280
281        self.assertFalse(self.widget.txtXnodes.isEnabled())
282        self.assertEqual(self.widget.txtXnodes.text(), 'NaN')
283        self.assertFalse(self.widget.txtYnodes.isEnabled())
284        self.assertEqual(self.widget.txtYnodes.text(), 'NaN')
285        self.assertFalse(self.widget.txtZnodes.isEnabled())
286        self.assertEqual(self.widget.txtZnodes.text(), 'NaN')
287
288        self.assertFalse(self.widget.txtXstepsize.isEnabled())
289        self.assertEqual(self.widget.txtXstepsize.text(), 'NaN')
290        self.assertFalse(self.widget.txtYstepsize.isEnabled())
291        self.assertEqual(self.widget.txtYstepsize.text(), 'NaN')
292        self.assertFalse(self.widget.txtZstepsize.isEnabled())
293        self.assertEqual(self.widget.txtZstepsize.text(), 'NaN')
294
295        self.assertTrue(self.widget.sld_data.is_data)
296
297    # TODO
298    def testLoadedOMFButton(self):
299        """
300        Load omf data and check modifications of GUI
301        """
302        filename = os.path.join("UnitTesting", "A_Raw_Example-1.omf")
303
304        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)
305        self.widget.loadFile()
306        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
307        time.sleep(2)
308
309        self.assertEqual(self.widget.txtData.text(), 'A_Raw_Example-1.omf')
310        self.assertEqual(self.widget.txtTotalVolume.text(), '128000000.0')
311        self.assertEqual(self.widget.txtNoPixels.text(), '16000')
312
313        # check disabled TextEdits according to data format
314        self.assertFalse(self.widget.txtUpFracIn.isEnabled())
315        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
316        self.assertFalse(self.widget.txtUpFracOut.isEnabled())
317        self.assertFalse(self.widget.txtNoPixels.isEnabled())
318
319        # check enabled draw buttons
320        self.assertTrue(self.widget.cmdDraw.isEnabled())
321        self.assertTrue(self.widget.cmdDrawpoints.isEnabled())
322
323        # check that text of loadButton is back to initial state
324        self.assertEqual(self.widget.cmdLoad.text(), 'Load')
325        self.assertTrue(self.widget.cmdLoad.isEnabled())
326
327        # check values and enabled / disabled for
328        # Mx,y,z x,y,znodes and x,y,zstepsize buttons
329        self.assertFalse(self.widget.txtMx.isEnabled())
330        self.assertAlmostEqual(float(self.widget.txtMx.text()), 7.855e-09, 4)
331        self.assertFalse(self.widget.txtMy.isEnabled())
332        self.assertAlmostEqual(float(self.widget.txtMy.text()), 4.517e-08, 4)
333        self.assertFalse(self.widget.txtMz.isEnabled())
334        self.assertAlmostEqual(float(self.widget.txtMz.text()), 9.9511e-10, 4)
335        self.assertTrue(self.widget.txtNucl.isEnabled())
336        self.assertEqual(self.widget.txtNucl.text(), '0')
337
338        self.assertFalse(self.widget.txtXnodes.isEnabled())
339        self.assertEqual(self.widget.txtXnodes.text(), '40')
340        self.assertFalse(self.widget.txtYnodes.isEnabled())
341        self.assertEqual(self.widget.txtYnodes.text(), '40')
342        self.assertFalse(self.widget.txtZnodes.isEnabled())
343        self.assertEqual(self.widget.txtZnodes.text(), '10')
344
345        self.assertFalse(self.widget.txtXstepsize.isEnabled())
346        self.assertEqual(self.widget.txtXstepsize.text(), '20')
347        self.assertFalse(self.widget.txtYstepsize.isEnabled())
348        self.assertEqual(self.widget.txtYstepsize.text(), '20')
349        self.assertFalse(self.widget.txtZstepsize.isEnabled())
350        self.assertEqual(self.widget.txtZstepsize.text(), '20')
351
352    def testReset(self):
353        """
354        Test reset button when GUI has been modified
355        """
356        # modify gui
357        self.widget.txtBackground.setText('50.0')
358        # apply reset
359        self.widget.onReset()
360        # check that we get back to the initial state
361        self.assertEqual(self.widget.txtBackground.text(), '0.0')
362
363    # TODO check plots
364    def testCompute(self):
365        """
366        Test compute button
367        """
368        # load data
369        filename = os.path.join("UnitTesting", "diamdsml.pdb")
370
371        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)
372        self.widget.loadFile()
373        time.sleep(1)
374        QTest.mouseClick(self.widget.cmdCompute, Qt.LeftButton)
375        # check modification of text of Compute button
376        self.assertEqual(self.widget.cmdCompute.text(), 'Wait...')
377        self.assertFalse(self.widget.cmdCompute.isEnabled())
378
379        #self.widget.complete([numpy.ones(1), numpy.zeros(1), numpy.zeros(1)], update=None)
380        #self.assertEqual(self.widget.cmdCompute.text(), 'Compute')
381        #self.assertTrue(self.widget.cmdCompute.isEnabled())
382
383    # TODO
384    def testDrawButton(self):
385        """
386        Test Draw buttons for 3D plots with and without arrows
387        """
388        self.assertFalse(self.widget.cmdDraw.isEnabled())
389        filename = os.path.join("UnitTesting", "diamdsml.pdb")
390        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)
391        self.widget.loadFile()
392        self.assertEqual(self.widget.cmdLoad.text(), 'Loading...')
393        time.sleep(1)
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
410        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename)
411        self.widget.loadFile()
412
413        time.sleep(0.1)
414
415        filename1 = "test"
416        QtGui.QFileDialog.getSaveFileName = MagicMock(return_value=filename1)
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.