Changeset 02c11b04 in sasview for src/sas/qtgui
- Timestamp:
- Oct 26, 2017 3:34:19 AM (7 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:
- 9e54199
- Parents:
- 9ea43c82 (diff), f629e62f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Location:
- src/sas/qtgui
- Files:
-
- 3 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/MainWindow/GuiManager.py
rf0bb711 r9863343 384 384 self._workspace.actionCombine_Batch_Fit.triggered.connect(self.actionCombine_Batch_Fit) 385 385 self._workspace.actionFit_Options.triggered.connect(self.actionFit_Options) 386 self._workspace.actionGPU_Options.triggered.connect(self.actionGPU_Options) 386 387 self._workspace.actionFit_Results.triggered.connect(self.actionFit_Results) 387 388 self._workspace.actionChain_Fitting.triggered.connect(self.actionChain_Fitting) … … 620 621 pass 621 622 623 def actionGPU_Options(self): 624 """ 625 Load the OpenCL selection dialog if the fitting perspective is active 626 """ 627 if hasattr(self._current_perspective, "gpu_options_widget"): 628 self._current_perspective.gpu_options_widget.show() 629 pass 630 622 631 def actionFit_Results(self): 623 632 """ -
src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
rb00414d r06ce180 25 25 <y>0</y> 26 26 <width>915</width> 27 <height>2 1</height>27 <height>26</height> 28 28 </rect> 29 29 </property> … … 103 103 <addaction name="separator"/> 104 104 <addaction name="actionFit_Options"/> 105 <addaction name="actionGPU_Options"/> 105 106 <addaction name="actionFit_Results"/> 106 107 <addaction name="separator"/> … … 499 500 </property> 500 501 </action> 502 <action name="actionGPU_Options"> 503 <property name="text"> 504 <string>GPU Options</string> 505 </property> 506 <property name="softKeyRole"> 507 <enum>QAction::NoSoftKey</enum> 508 </property> 509 </action> 501 510 </widget> 502 511 <resources/> -
src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
r377ade1 r14fa542 11 11 from sas.qtgui.Perspectives.Fitting.FittingWidget import FittingWidget 12 12 from sas.qtgui.Perspectives.Fitting.FittingOptions import FittingOptions 13 from sas.qtgui.Perspectives.Fitting.GPUOptions import GPUOptions 13 14 from sas.qtgui.Perspectives.Fitting import ModelUtilities 14 15 … … 60 61 # Listen to GUI Manager signal updating fit options 61 62 self.fit_options_widget.fit_option_changed.connect(self.onFittingOptionsChange) 63 64 # GPU Options 65 self.gpu_options_widget = GPUOptions(self) 62 66 63 67 self.menu_manager = ModelUtilities.ModelManager() -
src/sas/qtgui/MainWindow/DataExplorer.py
r1420066 r88e1f57 463 463 Forces display of charts for the given filename 464 464 """ 465 # Assure no multiple plots for the same ID466 465 plot_to_show = data_list[0] 467 if plot_to_show.id in PlotHelper.currentPlots(): 468 return469 470 # Now query the model item for available plots466 467 # passed plot is used ONLY to figure out its title, 468 # so all the charts related by it can be pulled from 469 # the data explorer indices. 471 470 filename = plot_to_show.filename 472 471 model = self.model if plot_to_show.is_data else self.theory_model 472 473 # Now query the model item for available plots 473 474 plots = GuiUtils.plotsFromFilename(filename, model) 475 item = GuiUtils.itemFromFilename(filename, model) 476 477 new_plots = [] 474 478 for plot in plots: 475 479 plot_id = plot.id … … 477 481 self.active_plots[plot_id].replacePlot(plot_id, plot) 478 482 else: 479 self.plotData([(None, plot)]) 483 # 'sophisticated' test to generate standalone plot for residuals 484 if 'esiduals' in plot.title: 485 self.plotData([(item, plot)]) 486 else: 487 new_plots.append((item, plot)) 488 489 if new_plots: 490 self.plotData(new_plots) 480 491 481 492 def addDataPlot2D(self, plot_set, item): … … 487 498 plot2D.plot(plot_set) 488 499 self.addPlot(plot2D) 500 self.active_plots[plot2D.data.id] = plot2D 489 501 #============================================ 490 502 # Experimental hook for silx charts … … 507 519 # Call show on requested plots 508 520 # All same-type charts in one plot 509 #if isinstance(plot_set, Data1D):510 # new_plot = Plotter(self)511 512 521 for item, plot_set in plots: 513 522 if isinstance(plot_set, Data1D): … … 515 524 new_plot = Plotter(self) 516 525 new_plot.plot(plot_set) 526 # active_plots may contain multiple charts 527 self.active_plots[plot_set.id] = new_plot 517 528 elif isinstance(plot_set, Data2D): 518 529 self.addDataPlot2D(plot_set, item) … … 556 567 557 568 # Update the active chart list 558 self.active_plots[new_plot.data.id] = new_plot569 #self.active_plots[new_plot.data.id] = new_plot 559 570 560 571 def appendPlot(self): -
src/sas/qtgui/MainWindow/UnitTesting/DataExplorerTest.py
rf4a1433 rf7d14a1 25 25 import sas.qtgui.Plotting.PlotHelper as PlotHelper 26 26 27 #if not QApplication.instance():28 app = QApplication(sys.argv)27 if not QApplication.instance(): 28 app = QApplication(sys.argv) 29 29 30 30 class DataExplorerTest(unittest.TestCase): … … 37 37 def allowBatch(self): 38 38 return False 39 def setData(self, data_item=None ):39 def setData(self, data_item=None, is_batch=False): 40 40 return None 41 41 def title(self): … … 170 170 171 171 # Populate the model 172 #filename = ["cyl_400_20.txt", "P123_D2O_10_percent.dat", "cyl_400_20.txt"] 173 filename = ["cyl_400_20.txt", "cyl_400_20.txt", "P123_D2O_10_percent.dat"] 172 filename = ["cyl_400_20.txt", "cyl_400_20.txt", "cyl_400_20.txt"] 174 173 self.form.readData(filename) 175 176 self.form.show()177 app.exec_()178 174 179 175 # Assure the model contains three items -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
ra95c44b rd0dfcb2 8 8 from sas.qtgui.Plotting.PlotterData import Data1D 9 9 from sas.qtgui.Plotting.PlotterData import Data2D 10 11 model_header_captions = ['Parameter', 'Value', 'Min', 'Max', 'Units'] 12 13 model_header_tooltips = ['Select parameter for fitting', 14 'Enter parameter value', 15 'Enter minimum value for parameter', 16 'Enter maximum value for parameter', 17 'Unit of the parameter'] 18 19 poly_header_captions = ['Parameter', 'PD[ratio]', 'Min', 'Max', 'Npts', 'Nsigs', 20 'Function', 'Filename'] 21 22 poly_header_tooltips = ['Select parameter for fitting', 23 'Enter polydispersity ratio (STD/mean). ' 24 'STD: standard deviation from the mean value', 25 'Enter minimum value for parameter', 26 'Enter maximum value for parameter', 27 'Enter number of points for parameter', 28 'Enter number of sigmas parameter', 29 'Select distribution function', 30 'Select filename with user-definable distribution'] 31 32 error_tooltip = 'Error value for fitted parameter' 33 header_error_caption = 'Error' 10 34 11 35 def replaceShellName(param_name, value): … … 131 155 Adds predefined headers to the model 132 156 """ 133 model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 134 model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("Value")) 135 model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 136 model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 137 model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("Units")) 138 139 model.header_tooltips = ['Select parameter for fitting', 140 'Enter parameter value', 141 'Enter minimum value for parameter', 142 'Enter maximum value for parameter', 143 'Unit of the parameter'] 157 for i, item in enumerate(model_header_captions): 158 model.setHeaderData(i, QtCore.Qt.Horizontal, QtCore.QVariant(item)) 159 160 model.header_tooltips = model_header_tooltips 161 144 162 def addErrorHeadersToModel(model): 145 163 """ 146 164 Adds predefined headers to the model 147 165 """ 148 model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 149 model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("Value")) 150 model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Error")) 151 model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 152 model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 153 model.setHeaderData(5, QtCore.Qt.Horizontal, QtCore.QVariant("Units")) 154 155 model.header_tooltips = ['Select parameter for fitting', 156 'Enter parameter value', 157 'Error value for fitted parameter', 158 'Enter minimum value for parameter', 159 'Enter maximum value for parameter', 160 'Unit of the parameter'] 166 model_header_error_captions = model_header_captions 167 model_header_error_captions.insert(2, header_error_caption) 168 for i, item in enumerate(model_header_error_captions): 169 model.setHeaderData(i, QtCore.Qt.Horizontal, QtCore.QVariant(item)) 170 171 model_header_error_tooltips = model_header_tooltips 172 model_header_error_tooltips.insert(2, error_tooltip) 173 model.header_tooltips = model_header_error_tooltips 161 174 162 175 def addPolyHeadersToModel(model): … … 164 177 Adds predefined headers to the model 165 178 """ 166 model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 167 model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("PD[ratio]")) 168 model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 169 model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 170 model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("Npts")) 171 model.setHeaderData(5, QtCore.Qt.Horizontal, QtCore.QVariant("Nsigs")) 172 model.setHeaderData(6, QtCore.Qt.Horizontal, QtCore.QVariant("Function")) 173 model.setHeaderData(7, QtCore.Qt.Horizontal, QtCore.QVariant("Filename")) 174 175 model.header_tooltips = ['Select parameter for fitting', 176 'Enter polydispersity ratio (STD/mean). ' 177 'STD: standard deviation from the mean value', 178 'Enter minimum value for parameter', 179 'Enter maximum value for parameter', 180 'Enter number of points for parameter', 181 'Enter number of sigmas parameter', 182 'Select distribution function', 183 'Select filename with user-definable distribution'] 179 for i, item in enumerate(poly_header_captions): 180 model.setHeaderData(i, QtCore.Qt.Horizontal, QtCore.QVariant(item)) 181 182 model.header_tooltips = poly_header_tooltips 183 184 184 185 185 def addErrorPolyHeadersToModel(model): … … 187 187 Adds predefined headers to the model 188 188 """ 189 model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 190 model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("PD[ratio]")) 191 model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Error")) 192 model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 193 model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 194 model.setHeaderData(5, QtCore.Qt.Horizontal, QtCore.QVariant("Npts")) 195 model.setHeaderData(6, QtCore.Qt.Horizontal, QtCore.QVariant("Nsigs")) 196 model.setHeaderData(7, QtCore.Qt.Horizontal, QtCore.QVariant("Function")) 197 model.setHeaderData(8, QtCore.Qt.Horizontal, QtCore.QVariant("Filename")) 198 199 model.header_tooltips = ['Select parameter for fitting', 200 'Enter polydispersity ratio (STD/mean). ' 201 'STD: standard deviation from the mean value', 202 'Error value for fitted parameter', 203 'Enter minimum value for parameter', 204 'Enter maximum value for parameter', 205 'Enter number of points for parameter', 206 'Enter number of sigmas parameter', 207 'Select distribution function', 208 'Select filename with user-definable distribution'] 189 poly_header_error_captions = poly_header_captions 190 poly_header_error_captions.insert(2, header_error_caption) 191 for i, item in enumerate(poly_header_error_captions): 192 model.setHeaderData(i, QtCore.Qt.Horizontal, QtCore.QVariant(item)) 193 194 poly_header_error_tooltips = poly_header_tooltips 195 poly_header_error_tooltips.insert(2, error_tooltip) 196 model.header_tooltips = poly_header_error_tooltips 209 197 210 198 def addShellsToModel(parameters, model, index): -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
ra95c44b re00b76e 13 13 from PyQt4 import QtWebKit 14 14 15 from sasmodels import product 15 16 from sasmodels import generate 16 17 from sasmodels import modelinfo … … 52 53 53 54 class ToolTippedItemModel(QtGui.QStandardItemModel): 54 55 def __init__(self, parent = None): 55 """ 56 Subclass from QStandardItemModel to allow displaying tooltips in 57 QTableView model. 58 """ 59 def __init__(self, parent=None): 56 60 QtGui.QStandardItemModel.__init__(self,parent) 57 61 58 62 def headerData(self, section, orientation, role): 59 63 """ 64 Displays tooltip for each column's header 65 :param section: 66 :param orientation: 67 :param role: 68 :return: 69 """ 60 70 if role == QtCore.Qt.ToolTipRole: 61 71 if orientation == QtCore.Qt.Horizontal: … … 136 146 def data(self, value): 137 147 """ data setter """ 148 # Value is either a list of indices for batch fitting or a simple index 149 # for standard fitting. Assure we have a list, regardless. 138 150 if isinstance(value, list): 139 151 self.is_batch_fitting = True … … 149 161 150 162 # Update logics with data items 163 # Logics.data contains only a single Data1D/Data2D object 151 164 self.logic.data = GuiUtils.dataFromItem(value[0]) 152 165 … … 154 167 self.is2D = True if isinstance(self.logic.data, Data2D) else False 155 168 169 # Let others know we're full of data now 156 170 self.data_is_loaded = True 157 171 … … 333 347 self.chk2DView.setVisible(False) 334 348 self.chkMagnetism.setEnabled(self.is2D) 349 self.tabFitting.setTabEnabled(TAB_MAGNETISM, self.is2D) 335 350 # Combo box or label for file name" 336 351 if self.is_batch_fitting: … … 344 359 # Similarly on other tabs 345 360 self.options_widget.setEnablementOnDataLoad() 361 362 # Reload the model 363 self.onSelectModel() 346 364 347 365 # Smearing tab … … 626 644 return 627 645 628 property_index = self._magnet_model.headerData( 1, model_column).toInt()[0]-1 # Value, min, max, etc.646 property_index = self._magnet_model.headerData(0, 1, model_column).toInt()[0]-1 # Value, min, max, etc. 629 647 630 648 # Update the parameter value - note: this supports +/-inf as well … … 1038 1056 # Regardless of previous state, this should now be `plot show` functionality only 1039 1057 self.cmdPlot.setText("Show Plot") 1040 if not self.data_is_loaded:1041 1058 # Force data recalculation so existing charts are updated 1059 self.recalculatePlotData() 1042 1060 self.showPlot() 1043 1061 … … 1253 1271 structure_module = generate.load_kernel_module(structure_factor) 1254 1272 structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) 1273 structure_kernel = self.models[structure_factor]() 1274 1275 self.kernel_module._model_info = product.make_product_info(self.kernel_module._model_info, structure_kernel._model_info) 1255 1276 1256 1277 new_rows = FittingUtilities.addSimpleParametersToModel(structure_parameters, self.is2D) -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
rc7358b2 r9ea43c82 20 20 from sas.qtgui.Plotting.PlotterData import Data2D 21 21 22 if not QtGui.QApplication.instance():23 22 #if not QtGui.QApplication.instance(): 23 app = QtGui.QApplication(sys.argv) 24 24 25 25 class dummy_manager(object): … … 100 100 delegate = fittingWindow.lstPoly.itemDelegate() 101 101 self.assertEqual(len(delegate.POLYDISPERSE_FUNCTIONS), 5) 102 self.assertEqual(delegate.editableParameters(), [ 2, 3, 4, 5])102 self.assertEqual(delegate.editableParameters(), [1, 2, 3, 4, 5]) 103 103 self.assertEqual(delegate.poly_function, 6) 104 self.assertIsInstance(delegate.combo_updated, QtCore.pyqtBoundSignal) 105 106 def testSelectMagnetism(self): 107 """ 108 Test if models have been loaded properly 109 """ 110 fittingWindow = self.widget 111 112 self.assertIsInstance(fittingWindow.lstMagnetic.itemDelegate(), QtGui.QStyledItemDelegate) 113 #Test loading from json categories 114 fittingWindow.SASModelToQModel("cylinder") 115 mag_index = fittingWindow.lstMagnetic.model().index(0,0) 116 self.assertEqual(str(mag_index.data().toString()), "up:frac_i") 117 mag_index = fittingWindow.lstMagnetic.model().index(1,0) 118 self.assertEqual(str(mag_index.data().toString()), "up:frac_f") 119 mag_index = fittingWindow.lstMagnetic.model().index(2,0) 120 self.assertEqual(str(mag_index.data().toString()), "up:angle") 121 mag_index = fittingWindow.lstMagnetic.model().index(3,0) 122 self.assertEqual(str(mag_index.data().toString()), "M0:sld") 123 mag_index = fittingWindow.lstMagnetic.model().index(4,0) 124 self.assertEqual(str(mag_index.data().toString()), "mtheta:sld") 125 mag_index = fittingWindow.lstMagnetic.model().index(5,0) 126 self.assertEqual(str(mag_index.data().toString()), "mphi:sld") 127 mag_index = fittingWindow.lstMagnetic.model().index(6,0) 128 self.assertEqual(str(mag_index.data().toString()), "M0:sld_solvent") 129 mag_index = fittingWindow.lstMagnetic.model().index(7,0) 130 self.assertEqual(str(mag_index.data().toString()), "mtheta:sld_solvent") 131 mag_index = fittingWindow.lstMagnetic.model().index(8,0) 132 self.assertEqual(str(mag_index.data().toString()), "mphi:sld_solvent") 133 134 # test the delegate a bit 135 delegate = fittingWindow.lstMagnetic.itemDelegate() 136 self.assertEqual(delegate.editableParameters(), [1, 2, 3]) 104 137 self.assertIsInstance(delegate.combo_updated, QtCore.pyqtBoundSignal) 105 138 … … 784 817 self.assertEqual(self.widget.cbModel.currentText(), 'onion') 785 818 self.assertTrue(self.widget.chkPolydispersity.isChecked()) 819 #Check if polidispersity tab is available 820 self.assertTrue(self.widget.tabFitting.isTabEnabled(3)) 821 822 #Check if magnetism box and tab are disabled when 1D data is loaded 823 self.assertFalse(self.widget.chkMagnetism.isEnabled()) 824 self.assertFalse(self.widget.tabFitting.isTabEnabled(4)) 825 826 def testReadFitPage2D(self): 827 """ 828 Read in the fitpage object and restore state 829 """ 830 # Set data 831 832 test_data = Data2D(image=[1.0, 2.0, 3.0], 833 err_image=[0.01, 0.02, 0.03], 834 qx_data=[0.1, 0.2, 0.3], 835 qy_data=[0.1, 0.2, 0.3], 836 xmin=0.1, xmax=0.3, ymin=0.1, ymax=0.3, 837 mask=[True, True, True]) 838 839 # Force same data into logic 840 self.widget.logic.data = test_data 841 self.widget.data_is_loaded = True 842 843 #item = QtGui.QStandardItem() 844 #updateModelItem(item, [test_data], "test") 845 # Force same data into logic 846 #self.widget.logic.data = item 847 #self.widget.data_is_loaded = True 848 849 category_index = self.widget.cbCategory.findText("Cylinder") 850 self.widget.cbCategory.setCurrentIndex(category_index) 851 852 # Test no fitting params 853 self.widget.parameters_to_fit = ['scale'] 854 855 # Invoke the tested method 856 fp = self.widget.currentState() 857 858 # Prepare modified fit page 859 fp.current_model = 'cylinder' 860 fp.is_polydisperse = True 861 fp.is_magnetic = True 862 fp.is2D = True 863 864 # Read in modified state 865 self.widget.readFitPage(fp) 866 867 # Check if the widget got updated accordingly 868 self.assertEqual(self.widget.cbModel.currentText(), 'cylinder') 869 self.assertTrue(self.widget.chkPolydispersity.isChecked()) 870 self.assertTrue(self.widget.chkPolydispersity.isEnabled()) 871 #Check if polidispersity tab is available 872 self.assertTrue(self.widget.tabFitting.isTabEnabled(3)) 873 874 #Check if magnetism box and tab are disabled when 1D data is loaded 875 self.assertTrue(self.widget.chkMagnetism.isChecked()) 876 self.assertTrue(self.widget.chkMagnetism.isEnabled()) 877 self.assertTrue(self.widget.tabFitting.isTabEnabled(4)) 786 878 787 879 def testCurrentState(self): -
src/sas/qtgui/Perspectives/Fitting/ViewDelegate.py
r16afe01 r02f1d12 128 128 129 129 def editableParameters(self): 130 return [self.poly_ min, self.poly_max, self.poly_npts, self.poly_nsigs]130 return [self.poly_pd, self.poly_min, self.poly_max, self.poly_npts, self.poly_nsigs] 131 131 132 132 def columnDict(self): … … 219 219 220 220 def editableParameters(self): 221 return [self.mag_ min, self.mag_max]221 return [self.mag_value, self.mag_min, self.mag_max] 222 222 223 223 def addErrorColumn(self): -
src/sas/qtgui/Utilities/GuiUtils.py
rf0bb711 r88e1f57 313 313 # Append the new row to the main item 314 314 item.appendRow(object_item) 315 316 def itemFromFilename(filename, model_item): 317 """ 318 Returns the model item text=filename in the model 319 """ 320 assert isinstance(model_item, QtGui.QStandardItemModel) 321 assert isinstance(filename, basestring) 322 323 # Iterate over model looking for named items 324 item = list(filter(lambda i: str(i.text()) == filename, 325 [model_item.item(index) for index in range(model_item.rowCount())])) 326 return item[0] if len(item)>0 else None 315 327 316 328 def plotsFromFilename(filename, model_item):
Note: See TracChangeset
for help on using the changeset viewer.