- Timestamp:
- Mar 10, 2017 9:44:44 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:
- cd31251
- Parents:
- 5236449
- Location:
- src/sas
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/DataExplorer.py
r5236449 rcbcdd2c 73 73 self.contextMenu() 74 74 75 # Same menus for the theory view 76 self.freezeView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 77 self.freezeView.customContextMenuRequested.connect(self.onCustomContextMenu) 78 75 79 # Connect the comboboxes 76 80 self.cbSelect.currentIndexChanged.connect(self.selectData) 77 81 78 82 #self.closeEvent.connect(self.closeEvent) 79 # self.aboutToQuit.connect(self.closeEvent)83 self.currentChanged.connect(self.onTabSwitch) 80 84 self.communicator = self.parent.communicator() 81 85 self.communicator.fileReadSignal.connect(self.loadFromURL) 82 86 self.communicator.activeGraphsSignal.connect(self.updateGraphCombo) 83 87 self.communicator.activeGraphName.connect(self.updatePlotName) 84 #self.communicator.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective)85 88 self.cbgraph.editTextChanged.connect(self.enableGraphCombo) 86 89 self.cbgraph.currentIndexChanged.connect(self.enableGraphCombo) 87 90 88 91 self._perspective = self.parent.perspective() 89 self._perspective.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective)90 92 91 93 # Proxy model for showing a subset of Data1D/Data2D content … … 111 113 self.enableGraphCombo(None) 112 114 115 # Current view on model 116 self.current_view = self.treeView 117 113 118 def closeEvent(self, event): 114 119 """ … … 116 121 """ 117 122 event.ignore() 123 124 def onTabSwitch(self, index): 125 """ Callback for tab switching signal """ 126 if index == 0: 127 self.current_view = self.treeView 128 else: 129 self.current_view = self.freezeView 118 130 119 131 def displayHelp(self): … … 725 737 Show the right-click context menu in the data treeview 726 738 """ 727 index = self.treeView.indexAt(position) 739 index = self.current_view.indexAt(position) 740 proxy = self.current_view.model() 741 model = proxy.sourceModel() 742 728 743 if index.isValid(): 729 model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index))744 model_item = model.itemFromIndex(proxy.mapToSource(index)) 730 745 # Find the mapped index 731 746 orig_index = model_item.isCheckable() … … 736 751 self.actionEditMask.setEnabled(is_2D) 737 752 # Fire up the menu 738 self.context_menu.exec_(self. treeView.mapToGlobal(position))753 self.context_menu.exec_(self.current_view.mapToGlobal(position)) 739 754 740 755 def showDataInfo(self): … … 742 757 Show a simple read-only text edit with data information. 743 758 """ 744 index = self.treeView.selectedIndexes()[0] 745 model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 759 index = self.current_view.selectedIndexes()[0] 760 proxy = self.current_view.model() 761 model = proxy.sourceModel() 762 model_item = model.itemFromIndex(proxy.mapToSource(index)) 763 746 764 data = GuiUtils.dataFromItem(model_item) 747 765 if isinstance(data, Data1D): … … 769 787 Save the data points as either txt or xml 770 788 """ 771 index = self.treeView.selectedIndexes()[0] 772 model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 789 index = self.current_view.selectedIndexes()[0] 790 proxy = self.current_view.model() 791 model = proxy.sourceModel() 792 model_item = model.itemFromIndex(proxy.mapToSource(index)) 793 773 794 data = GuiUtils.dataFromItem(model_item) 774 795 if isinstance(data, Data1D): … … 781 802 Frozen plot - display an image of the plot 782 803 """ 783 index = self.treeView.selectedIndexes()[0] 784 model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 804 index = self.current_view.selectedIndexes()[0] 805 proxy = self.current_view.model() 806 model = proxy.sourceModel() 807 model_item = model.itemFromIndex(proxy.mapToSource(index)) 808 785 809 data = GuiUtils.dataFromItem(model_item) 786 810 … … 805 829 Slowish 3D plot 806 830 """ 807 index = self.treeView.selectedIndexes()[0] 808 model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 831 index = self.current_view.selectedIndexes()[0] 832 proxy = self.current_view.model() 833 model = proxy.sourceModel() 834 model_item = model.itemFromIndex(proxy.mapToSource(index)) 835 809 836 data = GuiUtils.dataFromItem(model_item) 810 837 … … 824 851 Mask Editor for 2D plots 825 852 """ 826 index = self.treeView.selectedIndexes()[0] 827 model_item = self.model.itemFromIndex(self.data_proxy.mapToSource(index)) 853 index = self.current_view.selectedIndexes()[0] 854 proxy = self.current_view.model() 855 model = proxy.sourceModel() 856 model_item = model.itemFromIndex(proxy.mapToSource(index)) 857 828 858 data = GuiUtils.dataFromItem(model_item) 829 859 -
src/sas/qtgui/GuiManager.py
r5236449 rcbcdd2c 182 182 self._current_perspective.close() 183 183 # Default perspective 184 self._current_perspective = Perspectives.PERSPECTIVES[str(perspective_name)]( self)184 self._current_perspective = Perspectives.PERSPECTIVES[str(perspective_name)](manager=self, parent=self) 185 185 self._workspace.workspace.addWindow(self._current_perspective) 186 186 self._current_perspective.show() … … 335 335 self.communicate.progressBarUpdateSignal.connect(self.updateProgressBar) 336 336 self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged) 337 self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 337 338 338 339 def addTriggers(self): … … 721 722 self.checkUpdate() 722 723 723 pass 724 724 def updateTheoryFromPerspective(self, index): 725 """ 726 Catch the theory update signal from a perspective 727 Send the request to the DataExplorer for updating the theory model. 728 """ 729 self.filesWidget.updateTheoryFromPerspective(index) 730 731 732 -
src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
r5236449 rcbcdd2c 12 12 """ 13 13 """ 14 updateTheoryFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem)15 14 name = "Fitting" # For displaying in the combo box in DataExplorer 16 15 def __init__(self, manager=None, parent=None, data=None): … … 44 43 self.setWindowTitle('Fit panel - Active Fitting Optimizer: %s' % self.optimizer) 45 44 46 self.communicate = GuiUtils.Communicate() 45 #self.communicate = GuiUtils.Communicate() 46 self.communicate = self.parent.communicator() 47 47 48 48 def addFit(self, data): … … 54 54 self.maxIndex += 1 55 55 self.addTab(tab, self.tabName()) 56 tab.signalTheory.connect(self.passSignal)57 56 58 57 def tabName(self): … … 67 66 Update local bookkeeping on tab close 68 67 """ 69 assert (len(self.tabs) >= index)68 assert len(self.tabs) >= index 70 69 # don't remove the last tab 71 70 if len(self.tabs) <= 1: … … 86 85 Pass it over to the calculator 87 86 """ 88 assert (data_item is not None)87 assert data_item is not None 89 88 90 89 if not isinstance(data_item, list): … … 98 97 self._model_item = data_item[0] 99 98 100 # Extract data on 1st child - this is the Data1D/2D component101 data = GuiUtils.dataFromItem(self._model_item)102 103 # self.model.item(WIDGETS.W_FILENAME).setData(QtCore.QVariant(self._model_item.text()))104 105 99 # Find the first unassigned tab. 106 100 # If none, open a new tab. 107 available_tabs = list(map(lambda tab: tab.acceptsData(), self.tabs))101 available_tabs = list(map(lambda tab: tab.acceptsData(), self.tabs)) 108 102 109 103 if numpy.any(available_tabs): … … 111 105 else: 112 106 self.addFit(data_item) 113 114 115 def passSignal(self, theory_item):116 """117 """118 self.updateTheoryFromPerspectiveSignal.emit(theory_item)119 120 if __name__ == "__main__":121 app = QtGui.QApplication([])122 dlg = FittingWindow()123 dlg.show()124 sys.exit(app.exec_()) -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r5236449 rcbcdd2c 7 7 import logging 8 8 import traceback 9 9 from twisted.internet import threads 10 10 11 11 from PyQt4 import QtGui … … 23 23 from sas.sascalc.dataloader.data_info import Source 24 24 from sas.sasgui.perspectives.fitting.model_thread import Calc1D 25 from sas.sasgui.perspectives.fitting.model_thread import Calc2D 25 26 26 27 from UI.FittingWidgetUI import Ui_FittingWidgetUI … … 28 29 TAB_MAGNETISM = 4 29 30 TAB_POLY = 3 30 CATEGORY_DEFAULT="Choose category..." 31 CATEGORY_DEFAULT = "Choose category..." 32 QMIN_DEFAULT = 0.0005 33 QMAX_DEFAULT = 0.5 34 NPTS_DEFAULT = 50 31 35 32 36 class FittingWidget(QtGui.QWidget, Ui_FittingWidgetUI): … … 34 38 Main widget for selecting form and structure factor models 35 39 """ 36 signalTheory = QtCore.pyqtSignal(QtGui.QStandardItem)37 38 40 def __init__(self, manager=None, parent=None, data=None, id=1): 39 41 """ … … 46 48 47 49 # Necessary globals 50 self.parent = parent 51 # SasModel is loaded 48 52 self.model_is_loaded = False 53 # Data[12]D passed and set 49 54 self.data_is_loaded = False 55 # Current SasModel in view 50 56 self.kernel_module = None 57 # Current SasModel view dimension 51 58 self.is2D = False 59 # Current SasModel is multishell 52 60 self.model_has_shells = False 61 # Utility variable to enable unselectable option in category combobox 53 62 self._previous_category_index = 0 63 # Utility variable for multishell display 54 64 self._last_model_row = 0 55 self._current_parameter_name = None65 # Dictionary of {model name: model class} for the current category 56 66 self.models = {} 57 67 … … 60 70 61 71 # Parameters 62 self.q_range_min = 0.0005 63 self.q_range_max = 0.5 64 self.npts = 20 72 self.q_range_min = QMIN_DEFAULT 73 self.q_range_max = QMAX_DEFAULT 74 self.npts = NPTS_DEFAULT 75 # Main Data[12]D holder 65 76 self._data = None 66 77 … … 68 79 self.setupUi(self) 69 80 self.setWindowTitle("Fitting") 70 self.communicate = GuiUtils.Communicate()81 self.communicate = self.parent.communicate 71 82 72 83 # Set the main models … … 74 85 self._poly_model = QtGui.QStandardItemModel() 75 86 self._magnet_model = QtGui.QStandardItemModel() 76 # Proxy model for custom views on the main _model_model77 self.proxyModel = QtGui.QSortFilterProxyModel()78 87 79 88 # Param model displayed in param list … … 124 133 def data(self, value): 125 134 """ data setter """ 135 # _index contains the QIndex with data 126 136 self._index = value 137 # _data contains the actual Data[12]D 127 138 self._data = GuiUtils.dataFromItem(value[0]) 128 139 self.data_is_loaded = True 140 # Tag along functionality 129 141 self.updateQRange() 130 142 self.cmdFit.setEnabled(True) … … 135 147 136 148 def disableModelCombo(self): 149 """ Disable the combobox """ 137 150 self.cbModel.setEnabled(False) 138 151 self.label_3.setEnabled(False) 139 152 140 153 def enableModelCombo(self): 154 """ Enable the combobox """ 141 155 self.cbModel.setEnabled(True) 142 156 self.label_3.setEnabled(True) 143 157 144 158 def disableStructureCombo(self): 159 """ Disable the combobox """ 145 160 self.cbStructureFactor.setEnabled(False) 146 161 self.label_4.setEnabled(False) 147 162 148 163 def enableStructureCombo(self): 164 """ Enable the combobox """ 149 165 self.cbStructureFactor.setEnabled(True) 150 166 self.label_4.setEnabled(True) … … 156 172 if self.data_is_loaded: 157 173 self.q_range_min, self.q_range_max, self.npts = self.computeDataRange(self.data) 158 # set Q range labels 174 # set Q range labels on the main tab 159 175 self.lblMinRangeDef.setText(str(self.q_range_min)) 160 176 self.lblMaxRangeDef.setText(str(self.q_range_max)) 161 177 # set Q range labels on the options tab 162 178 self.txtMaxRange.setText(str(self.q_range_max)) 163 179 self.txtMinRange.setText(str(self.q_range_min)) … … 176 192 self.chkMagnetism.setEnabled(False) 177 193 self.chkMagnetism.setCheckState(False) 178 # tabs194 # Tabs 179 195 self.tabFitting.setTabEnabled(TAB_POLY, False) 180 196 self.tabFitting.setTabEnabled(TAB_MAGNETISM, False) 181 197 self.lblChi2Value.setText("---") 182 183 198 # Update Q Ranges 184 199 self.updateQRange() … … 188 203 Connect GUI element signals 189 204 """ 205 # Comboboxes 190 206 self.cbStructureFactor.currentIndexChanged.connect(self.selectStructureFactor) 191 207 self.cbCategory.currentIndexChanged.connect(self.selectCategory) 192 208 self.cbModel.currentIndexChanged.connect(self.selectModel) 209 # Checkboxes 193 210 self.chk2DView.toggled.connect(self.toggle2D) 194 211 self.chkPolydispersity.toggled.connect(self.togglePoly) 195 212 self.chkMagnetism.toggled.connect(self.toggleMagnetism) 213 # Buttons 196 214 self.cmdFit.clicked.connect(self.onFit) 215 self.cmdPlot.clicked.connect(self.onPlot) 216 # Line edits 217 self.txtNpts.textChanged.connect(self.onNpts) 218 self.txtMinRange.textChanged.connect(self.onMinRange) 219 self.txtMaxRange.textChanged.connect(self.onMaxRange) 220 221 # Respond to change in parameters from the UI 222 self._model_model.itemChanged.connect(self.updateParamsFromModel) 197 223 198 224 def setDefaultStructureCombo(self): 199 # Fill in the structure factors combo box with defaults 225 """ 226 Fill in the structure factors combo box with defaults 227 """ 200 228 structure_factor_list = self.master_category_dict.pop('Structure Factor') 201 229 structure_factors = [] … … 208 236 """ 209 237 Select Category from list 210 :return:211 238 """ 212 239 category = self.cbCategory.currentText() … … 224 251 return 225 252 253 # Safely clear and enable the model combo 226 254 self.cbModel.blockSignals(True) 227 255 self.cbModel.clear() … … 231 259 232 260 self._previous_category_index = self.cbCategory.currentIndex() 261 # Retrieve the list of models 233 262 model_list = self.master_category_dict[str(category)] 234 263 models = [] 264 # Populate the models combobox 235 265 for (model, _) in model_list: 236 266 models.append(model) … … 241 271 Respond to select Model from list event 242 272 """ 243 model = self.cbModel.currentText() 244 self._current_parameter_name = model 273 model = str(self.cbModel.currentText()) 245 274 246 275 # SasModel -> QModel … … 248 277 249 278 if self._index is None: 279 # Create default datasets if no data passed 250 280 if self.is2D: 251 281 self.createDefault2dData() 252 282 else: 253 283 self.createDefault1dData() 254 self.createTheoryIndex() 284 # DESIGN: create the theory now or on Plot event? 285 #self.createTheoryIndex() 255 286 else: 256 # TODO: 2D case 287 # Create datasets and errorbars for current data 288 if self.is2D: 289 self.calculate2DForModel() 290 else: 291 self.calculate1DForModel() 257 292 # TODO: attach the chart to index 258 self.calculate1DForModel()259 293 260 294 def selectStructureFactor(self): 261 295 """ 262 296 Select Structure Factor from list 263 :param: 264 :return: 265 """ 266 model = self.cbStructureFactor.currentText() 297 """ 298 model = str(self.cbStructureFactor.currentText()) 267 299 self.setModelModel(model) 268 300 … … 275 307 self.model_enabled_dict = defaultdict(bool) 276 308 277 try: 278 categorization_file = CategoryInstaller.get_user_file() 279 if not os.path.isfile(categorization_file): 280 categorization_file = CategoryInstaller.get_default_file() 281 cat_file = open(categorization_file, 'rb') 309 categorization_file = CategoryInstaller.get_user_file() 310 if not os.path.isfile(categorization_file): 311 categorization_file = CategoryInstaller.get_default_file() 312 with open(categorization_file, 'rb') as cat_file: 282 313 self.master_category_dict = json.load(cat_file) 283 314 self.regenerateModelDict() 284 cat_file.close()285 except IOError:286 raise287 print 'Problem reading in category file.'288 print 'We even looked for it, made sure it was there.'289 print 'An existential crisis if there ever was one.'290 315 291 316 # Load the model dict … … 296 321 def regenerateModelDict(self): 297 322 """ 298 regenerates self.by_model_dict which has each model name as the323 Regenerates self.by_model_dict which has each model name as the 299 324 key and the list of categories belonging to that model 300 325 along with the enabled mapping … … 310 335 Returns a list of all multi-shell parameters in 'model' 311 336 """ 312 iter_params = list(filter(lambda par: "[" in par.name, model.iq_parameters)) 313 314 return iter_params 337 return list(filter(lambda par: "[" in par.name, model.iq_parameters)) 315 338 316 339 def getMultiplicity(self, model): … … 333 356 Adds background parameter with default values to the model 334 357 """ 335 assert(isinstance(model, QtGui.QStandardItemModel)) 336 358 assert isinstance(model, QtGui.QStandardItemModel) 337 359 checked_list = ['background', '0.001', '-inf', 'inf', '1/cm'] 338 360 self.addCheckedListToModel(model, checked_list) … … 342 364 Adds scale parameter with default values to the model 343 365 """ 344 assert(isinstance(model, QtGui.QStandardItemModel)) 345 366 assert isinstance(model, QtGui.QStandardItemModel) 346 367 checked_list = ['scale', '1.0', '0.0', 'inf', ''] 347 368 self.addCheckedListToModel(model, checked_list) 348 369 349 370 def addCheckedListToModel(self, model, param_list): 350 assert (isinstance(model, QtGui.QStandardItemModel))371 assert isinstance(model, QtGui.QStandardItemModel) 351 372 item_list = [QtGui.QStandardItem(item) for item in param_list] 352 373 item_list[0].setCheckable(True) … … 377 398 def setModelModel(self, model_name): 378 399 """ 379 Setting model parameters into table based on selected 380 :param model_name: 381 """ 400 Setting model parameters into table based on selected category 401 """ 402 assert isinstance(model_name, str) 403 382 404 # Crete/overwrite model items 383 405 self._model_model.clear() 384 model_name = str(model_name)385 406 386 407 kernel_module = generate.load_kernel_module(model_name) 387 #model_info = modelinfo.make_model_info(kernel_module)388 #self.kernel_module = _make_model_from_info(model_info)389 408 self.model_parameters = modelinfo.make_parameter_table(getattr(kernel_module, 'parameters', [])) 390 409 391 # Instantiate the current model410 # Instantiate the current sasmodel 392 411 self.kernel_module = self.models[model_name]() 393 412 … … 413 432 self.updateQRange() 414 433 434 def updateParamsFromModel(self, item): 435 """ 436 Callback method for updating the sasmodel parameters with the GUI values 437 """ 438 # Extract changed value. Assumes proper validation by QValidator/Delegate 439 value = float(item.text()) 440 model_column = item.column() 441 model_row = item.row() 442 name_index = self._model_model.index(model_row, 0) 443 parameter_name = str(self._model_model.data(name_index).toPyObject()) # sld, background etc. 444 property_name = str(self._model_model.headerData(1, model_column).toPyObject()) # Value, min, max, etc. 445 446 print "%s(%s) => %d" % (parameter_name, property_name, value) 447 self.kernel_module.params[parameter_name] = value 448 449 # min/max to be changed in self.kernel_module.details[parameter_name] = ['Ang', 0.0, inf] 450 451 # magnetic params in self.kernel_module.details['M0:parameter_name'] = value 452 # multishell params in self.kernel_module.details[??] = value 453 415 454 def computeDataRange(self, data): 416 455 """ 417 compute the minimum and the maximum range of the data456 Compute the minimum and the maximum range of the data 418 457 return the npts contains in data 419 458 """ 420 assert (data is not None)421 assert ((isinstance(data, Data1D) or isinstance(data, Data2D)))459 assert data is not None 460 assert (isinstance(data, Data1D) or isinstance(data, Data2D)) 422 461 qmin, qmax, npts = None, None, None 423 462 if isinstance(data, Data1D): … … 426 465 qmax = max(data.x) 427 466 npts = len(data.x) 428 except :467 except (ValueError, TypeError): 429 468 msg = "Unable to find min/max/length of \n data named %s" % \ 430 469 data.filename … … 436 475 x = max(numpy.fabs(data.xmin), numpy.fabs(data.xmax)) 437 476 y = max(numpy.fabs(data.ymin), numpy.fabs(data.ymax)) 438 except :477 except (ValueError, TypeError): 439 478 msg = "Unable to find min/max of \n data named %s" % \ 440 479 data.filename 441 480 raise ValueError, msg 442 qmax = math.sqrt(x * x + y * y)481 qmax = numpy.sqrt(x * x + y * y) 443 482 npts = len(data.data) 444 483 return qmin, qmax, npts … … 470 509 # Find param in volume_params 471 510 for p in parameters.form_volume_parameters: 472 if p.name == param.name: 473 item1_2 = QtGui.QStandardItem(str(p.default)) 474 item1_3 = QtGui.QStandardItem(str(p.limits[0])) 475 item1_4 = QtGui.QStandardItem(str(p.limits[1])) 476 item1_5 = QtGui.QStandardItem(p.units) 477 poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 478 break 479 511 if p.name != param.name: 512 continue 513 item1_2 = QtGui.QStandardItem(str(p.default)) 514 item1_3 = QtGui.QStandardItem(str(p.limits[0])) 515 item1_4 = QtGui.QStandardItem(str(p.limits[1])) 516 item1_5 = QtGui.QStandardItem(p.units) 517 poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 518 break 519 # Add the polydisp item as a child 480 520 item1.appendRow([poly_item]) 481 521 # Param values 482 522 item2 = QtGui.QStandardItem(str(param.default)) 523 # TODO: the error column. 524 # Either add a proxy model or a custom view delegate 525 #item_err = QtGui.QStandardItem() 483 526 item3 = QtGui.QStandardItem(str(param.limits[0])) 484 527 item4 = QtGui.QStandardItem(str(param.limits[1])) … … 486 529 model.appendRow([item1, item2, item3, item4, item5]) 487 530 531 # Update the counter used for multishell display 488 532 self._last_model_row = self._model_model.rowCount() 489 533 … … 571 615 Create a QStandardModelIndex containing default model data 572 616 """ 573 name = self. _current_parameter_name617 name = self.kernel_module.name 574 618 if self.is2D: 575 619 name += "2d" 576 620 name = "M%i [%s]" % (self.tab_id, name) 577 621 new_item = GuiUtils.createModelItemWithPlot(QtCore.QVariant(self.data), name=name) 578 self.signalTheory.emit(new_item) 622 # Notify the GUI manager so it can update the theory model in DataExplorer 623 self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item) 579 624 580 625 def onFit(self): … … 582 627 Perform fitting on the current data 583 628 """ 584 # TEST FOR DISPLAY. 585 self.calculate1DForModel() 629 #self.calculate1DForModel() 630 pass 631 632 def onPlot(self): 633 """ 634 Plot the current set of data 635 """ 636 # TODO: reimplement basepage.py/_update_paramv_on_fit 637 if self.data is None or not self._data.is_data: 638 self.createDefault2dData() if self.is2D else self.createDefault1dData() 639 self.calculate2DForModel() if self.is2D else self.calculate1DForModel() 640 641 def onNpts(self, text): 642 """ 643 Callback for number of points line edit update 644 """ 645 # assumes type/value correctness achieved with QValidator 646 try: 647 self.npts = int(text) 648 except: 649 pass 650 651 def onMinRange(self, text): 652 """ 653 Callback for minimum range of points line edit update 654 """ 655 # assumes type/value correctness achieved with QValidator 656 try: 657 self.q_range_min = float(text) 658 # set Q range labels on the main tab 659 self.lblMinRangeDef.setText(str(self.q_range_min)) 660 except: 661 pass 662 663 def onMaxRange(self, text): 664 """ 665 Callback for maximum range of points line edit update 666 """ 667 # assumes type/value correctness achieved with QValidator 668 try: 669 self.q_range_max = float(text) 670 # set Q range labels on the main tab 671 self.lblMaxRangeDef.setText(str(self.q_range_max)) 672 except: 673 pass 586 674 587 675 def calculate1DForModel(self): … … 589 677 Prepare the fitting data object, based on current ModelModel 590 678 """ 591 data = self.data 592 model = self.kernel_module 593 page_id = 0 594 qmin = self.q_range_min 595 qmax = self.q_range_max 596 smearer = None 597 state = None 598 weight = None 599 fid = None 600 toggle_mode_on = False 601 update_chisqr = False 602 source = None 603 604 self.calc_1D = Calc1D(data=data, 605 model=model, 606 page_id=page_id, 607 qmin=qmin, 608 qmax=qmax, 609 smearer=smearer, 610 state=state, 611 weight=weight, 612 fid=fid, 613 toggle_mode_on=toggle_mode_on, 679 self.calc_1D = Calc1D(data=self.data, 680 model=self.kernel_module, 681 page_id=0, 682 qmin=self.q_range_min, 683 qmax=self.q_range_max, 684 smearer=None, 685 state=None, 686 weight=None, 687 fid=None, 688 toggle_mode_on=False, 614 689 completefn=self.complete1D, 615 update_chisqr= update_chisqr,690 update_chisqr=True, 616 691 exception_handler=self.calcException, 617 source= source)618 self.calc_1D.queue()619 620 def complete1D(self, x, y, page_id, elapsed, index, model,621 weight=None, fid=None,622 toggle_mode_on=False, state=None,623 data=None, update_chisqr=True, 624 source='model', plot_result=True):692 source=None) 693 # Instead of starting the thread with 694 # self.calc_1D.queue() 695 # let's try running the async request 696 calc_thread = threads.deferToThread(self.calc_1D.compute) 697 calc_thread.addCallback(self.complete1D) 698 699 def complete1D(self, return_data): 625 700 """ 626 701 Plot the current data 627 Should be a rewrite of fitting.py/_complete1D 628 """ 629 print "THREAD FINISHED" 702 """ 703 # Unpack return data from Calc1D 704 x, y, page_id, state, weight,\ 705 fid, toggle_mode_on, \ 706 elapsed, index, model,\ 707 data, update_chisqr, source = return_data 708 709 # Create the new plot 710 new_plot = Data1D(x=x, y=y) 711 new_plot.is_data = False 712 new_plot.dy = numpy.zeros(len(y)) 713 _yaxis, _yunit = data.get_yaxis() 714 _xaxis, _xunit = data.get_xaxis() 715 new_plot.title = data.name 716 717 new_plot.group_id = data.group_id 718 if new_plot.group_id == None: 719 new_plot.group_id = data.group_id 720 new_plot.id = str(self.tab_id) + " " + data.name 721 new_plot.name = model.name + " [" + data.name + "]" 722 new_plot.xaxis(_xaxis, _xunit) 723 new_plot.yaxis(_yaxis, _yunit) 724 725 # Assign the new Data1D object-wide 726 self._data = new_plot 727 self.createTheoryIndex() 728 729 #output=self._cal_chisqr(data=data, 730 # fid=fid, 731 # weight=weight, 732 # page_id=page_id, 733 # index=index) 734 735 def calculate2DForModel(self): 736 """ 737 Prepare the fitting data object, based on current ModelModel 738 """ 739 self.calc_2D = Calc2D(data=self.data, 740 model=self.kernel_module, 741 page_id=0, 742 qmin=self.q_range_min, 743 qmax=self.q_range_max, 744 smearer=None, 745 state=None, 746 weight=None, 747 fid=None, 748 toggle_mode_on=False, 749 completefn=self.complete2D, 750 update_chisqr=True, 751 exception_handler=self.calcException, 752 source=None) 753 754 # Instead of starting the thread with 755 # self.calc_2D.queue() 756 # let's try running the async request 757 calc_thread = threads.deferToThread(self.calc_2D.compute) 758 calc_thread.addCallback(self.complete2D) 759 760 def complete2D(self, return_data): 761 """ 762 Plot the current data 763 Should be a rewrite of fitting.py/_complete2D 764 """ 765 image, data, page_id, model, state, toggle_mode_on,\ 766 elapsed, index, fid, qmin, qmax, weight, \ 767 update_chisqr, source = return_data 768 769 numpy.nan_to_num(image) 770 new_plot = Data2D(image=image, err_image=data.err_data) 771 new_plot.name = model.name + '2d' 772 new_plot.title = "Analytical model 2D " 773 new_plot.id = str(page_id) + " " + data.name 774 new_plot.group_id = str(page_id) + " Model2D" 775 new_plot.detector = data.detector 776 new_plot.source = data.source 777 new_plot.is_data = False 778 new_plot.qx_data = data.qx_data 779 new_plot.qy_data = data.qy_data 780 new_plot.q_data = data.q_data 781 new_plot.mask = data.mask 782 ## plot boundaries 783 new_plot.ymin = data.ymin 784 new_plot.ymax = data.ymax 785 new_plot.xmin = data.xmin 786 new_plot.xmax = data.xmax 787 788 title = data.title 789 790 new_plot.is_data = False 791 if data.is_data: 792 data_name = str(data.name) 793 else: 794 data_name = str(model.__class__.__name__) + '2d' 795 796 if len(title) > 1: 797 new_plot.title = "Model2D for %s " % model.name + data_name 798 new_plot.name = model.name + " [" + \ 799 data_name + "]" 800 801 # Assign the new Data2D object-wide 802 self._data = new_plot 803 self.createTheoryIndex() 804 805 #output=self._cal_chisqr(data=data, 806 # weight=weight, 807 # fid=fid, 808 # page_id=page_id, 809 # index=index) 810 # self._plot_residuals(page_id=page_id, data=data, fid=fid, 811 # index=index, weight=weight) 630 812 631 813 def calcException(self, etype, value, tb): 632 814 """ 633 """634 print "THREAD EXCEPTION"815 Something horrible happened in the deferred. Cry me a river. 816 """ 635 817 logging.error("".join(traceback.format_exception(etype, value, tb))) 636 818 msg = traceback.format_exception(etype, value, tb, limit=1) … … 640 822 Updates parameter name from <param_name>[n_shell] to <param_name>value 641 823 """ 642 assert ('[' in param_name)824 assert '[' in param_name 643 825 return param_name[:param_name.index('[')]+str(value) 644 826 … … 646 828 """ 647 829 Setting table properties 648 :param table:649 :return:650 830 """ 651 831 # Table properties … … 679 859 680 860 # Potential multishell params 681 #length_control = param.length_control682 #if length_control in param.name:683 684 861 checked_list = ["Distribution of "+param.name, str(param.default), 685 str(param.limits[0]), str(param.limits[1]),862 str(param.limits[0]), str(param.limits[1]), 686 863 "35", "3", ""] 687 864 self.addCheckedListToModel(self._poly_model, checked_list) … … 689 866 #TODO: Need to find cleaner way to input functions 690 867 func = QtGui.QComboBox() 691 func.addItems(['rectangle', 'array','lognormal','gaussian','schulz',])692 func_index = self.lstPoly.model().index(row, 6)693 self.lstPoly.setIndexWidget(func_index, func)868 func.addItems(['rectangle', 'array', 'lognormal', 'gaussian', 'schulz',]) 869 func_index = self.lstPoly.model().index(row, 6) 870 self.lstPoly.setIndexWidget(func_index, func) 694 871 695 872 self.addPolyHeadersToModel(self._poly_model) … … 767 944 # Find param in volume_params 768 945 for p in self.model_parameters.form_volume_parameters: 769 if p.name == par.name: 770 item1_2 = QtGui.QStandardItem(str(p.default)) 771 item1_3 = QtGui.QStandardItem(str(p.limits[0])) 772 item1_4 = QtGui.QStandardItem(str(p.limits[1])) 773 item1_5 = QtGui.QStandardItem(p.units) 774 poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 775 break 946 if p.name != par.name: 947 continue 948 item1_2 = QtGui.QStandardItem(str(p.default)) 949 item1_3 = QtGui.QStandardItem(str(p.limits[0])) 950 item1_4 = QtGui.QStandardItem(str(p.limits[1])) 951 item1_5 = QtGui.QStandardItem(p.units) 952 poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 953 break 776 954 item1.appendRow([poly_item]) 777 955 -
src/sas/sasgui/perspectives/fitting/model_thread.py
r934ce649 rcbcdd2c 99 99 output[index_model] = value 100 100 elapsed = time.time() - self.starttime 101 self.complete(image=output, 102 data=self.data, 103 page_id=self.page_id, 104 model=self.model, 105 state=self.state, 106 toggle_mode_on=self.toggle_mode_on, 107 elapsed=elapsed, 108 index=index_model, 109 fid=self.fid, 110 qmin=self.qmin, 111 qmax=self.qmax, 112 weight=self.weight, 113 #qstep=self.qstep, 114 update_chisqr=self.update_chisqr, 115 source=self.source) 101 #self.complete(image=output, 102 # data=self.data, 103 # page_id=self.page_id, 104 # model=self.model, 105 # state=self.state, 106 # toggle_mode_on=self.toggle_mode_on, 107 # elapsed=elapsed, 108 # index=index_model, 109 # fid=self.fid, 110 # qmin=self.qmin, 111 # qmax=self.qmax, 112 # weight=self.weight, 113 # #qstep=self.qstep, 114 # update_chisqr=self.update_chisqr, 115 # source=self.source) 116 return (output, 117 self.data, 118 self.page_id, 119 self.model, 120 self.state, 121 self.toggle_mode_on, 122 elapsed, 123 index_model, 124 self.fid, 125 self.qmin, 126 self.qmax, 127 self.weight, 128 self.update_chisqr, 129 self.source) 116 130 117 131 … … 178 192 elapsed = time.time() - self.starttime 179 193 180 self.complete(x=self.data.x[index], y=output[index], 181 page_id=self.page_id, 182 state=self.state, 183 weight=self.weight, 184 fid=self.fid, 185 toggle_mode_on=self.toggle_mode_on, 186 elapsed=elapsed, index=index, model=self.model, 187 data=self.data, 188 update_chisqr=self.update_chisqr, 189 source=self.source) 194 #self.complete(x=self.data.x[index], y=output[index], 195 # page_id=self.page_id, 196 # state=self.state, 197 # weight=self.weight, 198 # fid=self.fid, 199 # toggle_mode_on=self.toggle_mode_on, 200 # elapsed=elapsed, index=index, model=self.model, 201 # data=self.data, 202 # update_chisqr=self.update_chisqr, 203 # source=self.source) 204 return (self.data.x[index], output[index], 205 self.page_id, 206 self.state, 207 self.weight, 208 self.fid, 209 self.toggle_mode_on, 210 elapsed, index, self.model, 211 self.data, 212 self.update_chisqr, 213 self.source) 190 214 191 215 def results(self):
Note: See TracChangeset
for help on using the changeset viewer.