- Timestamp:
- May 2, 2017 9:04:48 AM (8 years ago)
- Branches:
- ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- 02ddfb4
- Parents:
- 0a6e097
- Location:
- src/sas/qtgui
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/MainWindow/DataExplorer.py
r83eb5208 rd48cc19 433 433 self.chkBatch.setEnabled(self.parent.perspective().allowBatch()) 434 434 435 def displayData(self, data_list): 436 """ 437 Forces display of charts for the given filename 438 """ 439 # Assure no multiple plots for the same ID 440 plot_to_show = data_list[0] 441 for plot in PlotHelper.currentPlots(): 442 if plot == plot_to_show.id: 443 return 444 445 new_plot = Plotter(self) 446 # Now query the model item for available plots 447 filename = plot_to_show.filename 448 model = self.model if plot_to_show.is_data else self.theory_model 449 plots = GuiUtils.plotsFromFilename(filename, model) 450 for plot in plots: 451 new_plot.plot(plot) 452 self.plotAdd(new_plot) 453 435 454 def newPlot(self): 436 455 """ -
src/sas/qtgui/MainWindow/GuiManager.py
r28a09b0 rd48cc19 335 335 self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged) 336 336 self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 337 self.communicate.plotRequestedSignal.connect(self.showPlot) 337 338 338 339 def addTriggers(self): … … 727 728 self.filesWidget.updateTheoryFromPerspective(index) 728 729 729 730 730 def showPlot(self, plot): 731 """ 732 Pass the show plot request to the data explorer 733 """ 734 if hasattr(self, "filesWidget"): 735 self.filesWidget.displayData(plot) 736 -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
r180bd54 rd48cc19 262 262 residuals.y = -y 263 263 else: 264 # TODO: fix case where applying new data from file on top of existing model data 264 265 y = (fn - gn[index][0]) / en 265 266 residuals.y = y -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r61a92d4 rd48cc19 74 74 self.weighting = 0 75 75 76 # Data for chosen model 77 self.model_data = None 78 76 79 # Which tab is this widget displayed in? 77 80 self.tab_id = id … … 250 253 """ 251 254 self.cmdFit.setEnabled(False) 252 self.cmdPlot.setEnabled( True)255 self.cmdPlot.setEnabled(False) 253 256 self.options_widget.cmdComputePoints.setVisible(False) # probably redundant 254 257 self.chkPolydispersity.setEnabled(True) … … 305 308 self.has_error_column = False 306 309 310 # Set enablement on calculate/plot 311 self.cmdPlot.setEnabled(True) 312 307 313 # SasModel -> QModel 308 314 self.SASModelToQModel(model) 309 315 310 316 if self.data_is_loaded: 317 self.cmdPlot.setText("Show Plot") 311 318 self.calculateQGridForModel() 312 319 else: 320 self.cmdPlot.setText("Calculate") 313 321 # Create default datasets if no data passed 314 322 self.createDefaultDataset() … … 569 577 Plot the current set of data 570 578 """ 579 # Regardless of previous state, this should now be `plot show` functionality only 580 self.cmdPlot.setText("Show Plot") 581 self.recalculatePlotData() 582 self.showPlot() 583 584 def recalculatePlotData(self): 585 """ 586 Generate a new dataset for model 587 """ 571 588 if not self.data_is_loaded: 572 589 self.createDefaultDataset() 573 590 self.calculateQGridForModel() 591 592 def showPlot(self): 593 """ 594 Show the current plot in MPL 595 """ 596 # Show the chart if ready 597 data_to_show = self.data if self.data_is_loaded else self.model_data 598 if data_to_show is not None: 599 self.communicate.plotRequestedSignal.emit([data_to_show]) 574 600 575 601 def onOptionsUpdate(self): … … 582 608 self.lblMinRangeDef.setText(str(self.q_range_min)) 583 609 self.lblMaxRangeDef.setText(str(self.q_range_max)) 584 self. onPlot()610 self.recalculatePlotData() 585 611 586 612 def setDefaultStructureCombo(self): … … 766 792 # Force the chart update when actual parameters changed 767 793 if model_column == 1: 768 self. onPlot()794 self.recalculatePlotData() 769 795 770 796 def checkboxSelected(self, item): … … 891 917 Plot the current 1D data 892 918 """ 893 fitted_plot = self.logic.new1DPlot(return_data, self.tab_id) 894 self.calculateResiduals(fitted_plot) 919 fitted_data = self.logic.new1DPlot(return_data, self.tab_id) 920 self.calculateResiduals(fitted_data) 921 self.model_data = fitted_data 895 922 896 923 def complete2D(self, return_data): … … 900 927 fitted_data = self.logic.new2DPlot(return_data) 901 928 self.calculateResiduals(fitted_data) 929 self.model_data = fitted_data 902 930 903 931 def calculateResiduals(self, fitted_data): … … 914 942 self.lblChi2Value.setText(chi2_repr) 915 943 944 self.communicate.plotUpdateSignal.emit([fitted_data]) 945 916 946 # Plot residuals if actual data 917 947 if self.data_is_loaded: … … 920 950 self.createNewIndex(residuals_plot) 921 951 self.communicate.plotUpdateSignal.emit([residuals_plot]) 922 923 self.communicate.plotUpdateSignal.emit([fitted_data])924 952 925 953 def calcException(self, etype, value, tb): -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
r83eb5208 rd48cc19 1 1 import sys 2 2 import unittest 3 import time 3 4 4 5 from PyQt4 import QtGui … … 21 22 22 23 class dummy_manager(object): 23 def communicate(self): 24 return Communicate() 24 communicate = Communicate() 25 25 26 26 class FittingWidgetTest(unittest.TestCase): … … 80 80 self.assertFalse(widget_with_data.acceptsData()) 81 81 82 def notestSelectModel(self):82 def testSelectModel(self): 83 83 """ 84 84 Test if models have been loaded properly 85 :return:86 85 """ 87 86 fittingWindow = self.widget … … 280 279 pass 281 280 282 def notestCreateTheoryIndex(self):281 def testCreateTheoryIndex(self): 283 282 """ 284 283 Test the data->QIndex conversion … … 292 291 293 292 # Create the index 294 self.widget.createTheoryIndex() 295 296 # Check the signal sent 297 print spy 298 299 # Check the index 293 self.widget.createTheoryIndex(Data1D(x=[1,2], y=[1,2])) 294 295 # Make sure the signal has been emitted 296 self.assertEqual(spy.count(), 1) 297 298 # Check the argument type 299 self.assertIsInstance(spy.called()[0]['args'][0], QtGui.QStandardItem) 300 300 301 301 def testCalculateQGridForModel(self): … … 305 305 # Mock the thread creation 306 306 threads.deferToThread = MagicMock() 307 # Model for theory 308 self.widget.SASModelToQModel("cylinder") 307 309 # Call the tested method 308 310 self.widget.calculateQGridForModel() 311 time.sleep(1) 309 312 # Test the mock 310 313 self.assertTrue(threads.deferToThread.called) 311 314 self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, "compute") 312 315 313 def testComplete1D(self): 314 """ 315 Check that a new 1D plot is generated 316 """ 317 # TODO when chisqr method coded 318 pass 319 320 def testComplete2D(self): 321 """ 322 Check that a new 2D plot is generated 323 """ 324 # TODO when chisqr method coded 325 pass 316 def testCalculateResiduals(self): 317 """ 318 Check that the residuals are calculated and plots updated 319 """ 320 test_data = Data1D(x=[1,2], y=[1,2]) 321 322 # Model for theory 323 self.widget.SASModelToQModel("cylinder") 324 # Invoke the tested method 325 self.widget.calculateResiduals(test_data) 326 # Check the Chi2 value - should be undetermined 327 self.assertEqual(self.widget.lblChi2Value.text(), '---') 328 329 # Force same data into logic 330 self.widget.logic.data = test_data 331 self.widget.calculateResiduals(test_data) 332 # Now, the difference is 0, as data is the same 333 self.assertEqual(self.widget.lblChi2Value.text(), '0') 334 335 # Change data 336 test_data_2 = Data1D(x=[1,2], y=[2.1,3.49]) 337 self.widget.logic.data = test_data_2 338 self.widget.calculateResiduals(test_data) 339 # Now, the difference is non-zero 340 self.assertEqual(float(self.widget.lblChi2Value.text()), 1.715) 326 341 327 342 def testSetPolyModel(self): … … 410 425 self.assertEqual(self.widget._model_model.rowCount(), last_row) 411 426 427 def testPlotTheory(self): 428 """ 429 See that theory item can produce a chart 430 """ 431 # By default, the compute/plot button is disabled 432 self.assertFalse(self.widget.cmdPlot.isEnabled()) 433 self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 434 435 # Assign a model 436 self.widget.show() 437 # Change the category index so we have a model available 438 category_index = self.widget.cbCategory.findText("Sphere") 439 self.widget.cbCategory.setCurrentIndex(category_index) 440 441 # Check the enablement/text 442 self.assertTrue(self.widget.cmdPlot.isEnabled()) 443 self.assertEqual(self.widget.cmdPlot.text(), 'Calculate') 444 445 # Spying on plot update signal 446 spy = QtSignalSpy(self.widget, self.widget.communicate.plotRequestedSignal) 447 448 # Press Calculate 449 QtTest.QTest.mouseClick(self.widget.cmdPlot, QtCore.Qt.LeftButton) 450 451 # Observe cmdPlot caption change 452 self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 453 454 # Make sure the signal has NOT been emitted 455 self.assertEqual(spy.count(), 0) 456 457 # Click again 458 QtTest.QTest.mouseClick(self.widget.cmdPlot, QtCore.Qt.LeftButton) 459 460 # This time, we got the update signal 461 self.assertEqual(spy.count(), 0) 462 463 def testPlotData(self): 464 """ 465 See that data item can produce a chart 466 """ 467 # By default, the compute/plot button is disabled 468 self.assertFalse(self.widget.cmdPlot.isEnabled()) 469 self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 470 471 self.widget.show() 472 473 # Set data 474 test_data = Data1D(x=[1,2], y=[1,2]) 475 476 # Force same data into logic 477 self.widget.logic.data = test_data 478 self.widget.data_is_loaded = True 479 480 # Change the category index so we have a model available 481 category_index = self.widget.cbCategory.findText("Sphere") 482 self.widget.cbCategory.setCurrentIndex(category_index) 483 484 # Check the enablement/text 485 self.assertTrue(self.widget.cmdPlot.isEnabled()) 486 self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 487 488 # Spying on plot update signal 489 spy = QtSignalSpy(self.widget, self.widget.communicate.plotRequestedSignal) 490 491 # Press Calculate 492 QtTest.QTest.mouseClick(self.widget.cmdPlot, QtCore.Qt.LeftButton) 493 494 # Observe cmdPlot caption did not change 495 self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 496 497 # Make sure the signal has been emitted == new plot 498 self.assertEqual(spy.count(), 1) 499 412 500 413 501 if __name__ == "__main__": -
src/sas/qtgui/Utilities/GuiUtils.py
r83eb5208 rd48cc19 229 229 # New plot requested from the GUI manager 230 230 # Old "NewPlotEvent" 231 plotRequestedSignal = QtCore.pyqtSignal( str)231 plotRequestedSignal = QtCore.pyqtSignal(list) 232 232 233 233 # Plot update requested from a perspective … … 323 323 item.appendRow(object_item) 324 324 325 def plotsFromFilename(filename, model_item): 326 """ 327 Returns the list of plots for the item with text=filename in the model 328 """ 329 assert isinstance(model_item, QtGui.QStandardItemModel) 330 assert isinstance(filename, basestring) 331 332 plot_data = [] 333 # Iterate over model looking for named items 334 for index in range(model_item.rowCount()): 335 item = model_item.item(index) 336 if str(item.text()) == filename: 337 # TODO: assure item type is correct (either data1/2D or Plotter) 338 plot_data.append(item.child(0).data().toPyObject()) 339 # Going 1 level deeper only 340 for index_2 in range(item.rowCount()): 341 item_2 = item.child(index_2) 342 if item_2 and item_2.isCheckable(): 343 # TODO: assure item type is correct (either data1/2D or Plotter) 344 plot_data.append(item_2.child(0).data().toPyObject()) 345 346 return plot_data 325 347 326 348 def plotsFromCheckedItems(model_item):
Note: See TracChangeset
for help on using the changeset viewer.