Changes in src/sas/qtgui/Perspectives/Fitting/FittingWidget.py [8b480d27:e4c475b7] in sasview
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r8b480d27 re4c475b7 24 24 import sas.qtgui.Utilities.GuiUtils as GuiUtils 25 25 import sas.qtgui.Utilities.LocalConfig as LocalConfig 26 from sas.qtgui.Utilities.GridPanel import BatchOutputPanel27 26 from sas.qtgui.Utilities.CategoryInstaller import CategoryInstaller 28 27 from sas.qtgui.Plotting.PlotterData import Data1D … … 37 36 from sas.qtgui.Perspectives.Fitting.FittingLogic import FittingLogic 38 37 from sas.qtgui.Perspectives.Fitting import FittingUtilities 39 from sas.qtgui.Perspectives.Fitting import ModelUtilities40 38 from sas.qtgui.Perspectives.Fitting.SmearingWidget import SmearingWidget 41 39 from sas.qtgui.Perspectives.Fitting.OptionsWidget import OptionsWidget … … 52 50 CATEGORY_DEFAULT = "Choose category..." 53 51 CATEGORY_STRUCTURE = "Structure Factor" 54 CATEGORY_CUSTOM = "Plugin Models"55 52 STRUCTURE_DEFAULT = "None" 56 53 … … 86 83 constraintAddedSignal = QtCore.pyqtSignal(list) 87 84 newModelSignal = QtCore.pyqtSignal() 88 fittingFinishedSignal = QtCore.pyqtSignal(tuple)89 batchFittingFinishedSignal = QtCore.pyqtSignal(tuple)90 91 85 def __init__(self, parent=None, data=None, tab_id=1): 92 86 … … 217 211 self.page_stack = [] 218 212 self.all_data = [] 219 # custom plugin models220 # {model.name:model}221 self.custom_models = self.customModels()222 213 # Polydisp widget table default index for function combobox 223 214 self.orig_poly_index = 3 … … 424 415 self.onSelectModel() 425 416 426 @classmethod427 def customModels(cls):428 """ Reads in file names in the custom plugin directory """429 return ModelUtilities._find_models()430 431 417 def initializeControls(self): 432 418 """ … … 479 465 self._poly_model.itemChanged.connect(self.onPolyModelChange) 480 466 self._magnet_model.itemChanged.connect(self.onMagnetModelChange) 481 self.lstParams.selectionModel().selectionChanged.connect(self.onSelectionChanged)482 483 # Local signals484 self.batchFittingFinishedSignal.connect(self.batchFitComplete)485 self.fittingFinishedSignal.connect(self.fitComplete)486 467 487 468 # Signals from separate tabs asking for replot 488 469 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 489 490 # Signals from other widgets491 self.communicate.customModelDirectoryChanged.connect(self.onCustomModelChange)492 470 493 471 def modelName(self): … … 598 576 # widget.params[0] is the parameter we're constraining 599 577 constraint.param = mc_widget.params[0] 600 # parametershould have the model name preamble578 # Function should have the model name preamble 601 579 model_name = self.kernel_module.name 602 # param_used is the parameter we're using in constraining function 603 param_used = mc_widget.params[1] 604 # Replace param_used with model_name.param_used 605 updated_param_used = model_name + "." + param_used 606 new_func = c_text.replace(param_used, updated_param_used) 607 constraint.func = new_func 580 constraint.func = model_name + "." + c_text 608 581 # Which row is the constrained parameter in? 609 582 row = self.getRowFromName(constraint.param) … … 704 677 Delete constraints from selected parameters. 705 678 """ 706 params = [s.data() for s in self.lstParams.selectionModel().selectedRows() 707 if self.isCheckable(s.row())] 708 for param in params: 709 self.deleteConstraintOnParameter(param=param) 679 self.deleteConstraintOnParameter(param=None) 710 680 711 681 def deleteConstraintOnParameter(self, param=None): … … 716 686 max_col = self.lstParams.itemDelegate().param_max 717 687 for row in range(self._model_model.rowCount()): 718 if not self.rowHasConstraint(row):719 continue720 688 # Get the Constraint object from of the model item 721 689 item = self._model_model.item(row, 1) 722 constraint = self.getConstraintForRow(row) 690 if not item.hasChildren(): 691 continue 692 constraint = item.child(0).data() 723 693 if constraint is None: 724 694 continue … … 846 816 return constraints 847 817 848 def getConstraintsForFitting(self):849 """850 Return a list of constraints in format ready for use in fiting851 """852 # Get constraints853 constraints = self.getComplexConstraintsForModel()854 # See if there are any constraints across models855 multi_constraints = [cons for cons in constraints if self.isConstraintMultimodel(cons[1])]856 857 if multi_constraints:858 # Let users choose what to do859 msg = "The current fit contains constraints relying on other fit pages.\n"860 msg += "Parameters with those constraints are:\n" +\861 '\n'.join([cons[0] for cons in multi_constraints])862 msg += "\n\nWould you like to remove these constraints or cancel fitting?"863 msgbox = QtWidgets.QMessageBox(self)864 msgbox.setIcon(QtWidgets.QMessageBox.Warning)865 msgbox.setText(msg)866 msgbox.setWindowTitle("Existing Constraints")867 # custom buttons868 button_remove = QtWidgets.QPushButton("Remove")869 msgbox.addButton(button_remove, QtWidgets.QMessageBox.YesRole)870 button_cancel = QtWidgets.QPushButton("Cancel")871 msgbox.addButton(button_cancel, QtWidgets.QMessageBox.RejectRole)872 retval = msgbox.exec_()873 if retval == QtWidgets.QMessageBox.RejectRole:874 # cancel fit875 raise ValueError("Fitting cancelled")876 else:877 # remove constraint878 for cons in multi_constraints:879 self.deleteConstraintOnParameter(param=cons[0])880 # re-read the constraints881 constraints = self.getComplexConstraintsForModel()882 883 return constraints884 885 818 def showModelDescription(self): 886 819 """ … … 941 874 self.respondToModelStructure(model=model, structure_factor=structure) 942 875 943 def onCustomModelChange(self):944 """945 Reload the custom model combobox946 """947 self.custom_models = self.customModels()948 self.readCustomCategoryInfo()949 # See if we need to update the combo in-place950 if self.cbCategory.currentText() != CATEGORY_CUSTOM: return951 952 current_text = self.cbModel.currentText()953 self.cbModel.blockSignals(True)954 self.cbModel.clear()955 self.cbModel.blockSignals(False)956 self.enableModelCombo()957 self.disableStructureCombo()958 # Retrieve the list of models959 model_list = self.master_category_dict[CATEGORY_CUSTOM]960 # Populate the models combobox961 self.cbModel.addItems(sorted([model for (model, _) in model_list]))962 new_index = self.cbModel.findText(current_text)963 if new_index != -1:964 self.cbModel.setCurrentIndex(self.cbModel.findText(current_text))965 966 def onSelectionChanged(self):967 """968 React to parameter selection969 """970 rows = self.lstParams.selectionModel().selectedRows()971 # Clean previous messages972 self.communicate.statusBarUpdateSignal.emit("")973 if len(rows) == 1:974 # Show constraint, if present975 row = rows[0].row()976 if self.rowHasConstraint(row):977 func = self.getConstraintForRow(row).func978 if func is not None:979 self.communicate.statusBarUpdateSignal.emit("Active constrain: "+func)980 981 876 def replaceConstraintName(self, old_name, new_name=""): 982 877 """ … … 991 886 new_func = func.replace(old_name, new_name) 992 887 self._model_model.item(row, 1).child(0).data().func = new_func 993 994 def isConstraintMultimodel(self, constraint):995 """996 Check if the constraint function text contains current model name997 """998 current_model_name = self.kernel_module.name999 if current_model_name in constraint:1000 return False1001 else:1002 return True1003 888 1004 889 def updateData(self): … … 1220 1105 except ValueError as ex: 1221 1106 # This should not happen! GUI explicitly forbids this situation 1222 self.communicate.statusBarUpdateSignal.emit( str(ex))1107 self.communicate.statusBarUpdateSignal.emit('Fitting attempt without parameters.') 1223 1108 return 1224 1109 1225 1110 # Create the fitting thread, based on the fitter 1226 completefn = self.batchFit tingCompleted if self.is_batch_fitting else self.fittingCompleted1111 completefn = self.batchFitComplete if self.is_batch_fitting else self.fitComplete 1227 1112 1228 1113 calc_fit = FitThread(handler=handler, … … 1261 1146 pass 1262 1147 1263 def batchFittingCompleted(self, result):1264 """1265 Send the finish message from calculate threads to main thread1266 """1267 self.batchFittingFinishedSignal.emit(result)1268 1269 1148 def batchFitComplete(self, result): 1270 1149 """ … … 1273 1152 #re-enable the Fit button 1274 1153 self.setFittingStopped() 1275 # Show the grid panel1276 self.grid_window = BatchOutputPanel(parent=self, output_data=result[0])1277 self.grid_window.show()1278 1279 def fittingCompleted(self, result):1280 """1281 Send the finish message from calculate threads to main thread1282 """1283 self.fittingFinishedSignal.emit(result)1284 1154 1285 1155 def fitComplete(self, result): … … 1292 1162 1293 1163 if result is None: 1294 msg = "Fitting failed ."1164 msg = "Fitting failed after: %s s.\n" % GuiUtils.formatNumber(elapsed) 1295 1165 self.communicate.statusBarUpdateSignal.emit(msg) 1296 1166 return … … 1358 1228 smearing, accuracy, smearing_min, smearing_max = self.smearing_widget.state() 1359 1229 1360 # Get the constraints.1361 1230 constraints = self.getComplexConstraintsForModel() 1362 if fitter is None:1363 # For single fits - check for inter-model constraints1364 constraints = self.getConstraintsForFitting()1365 1366 1231 smearer = None 1367 1232 handler = None … … 1377 1242 constraints=constraints) 1378 1243 except ValueError as ex: 1379 raise ValueError("Setting model parameters failed with: %s" % ex) 1244 logging.error("Setting model parameters failed with: %s" % ex) 1245 return 1380 1246 1381 1247 qmin, qmax, _ = self.logic.computeRangeFromData(data) … … 1543 1409 if not dict: 1544 1410 return 1545 if self._m agnet_model.rowCount() == 0:1411 if self._model_model.rowCount() == 0: 1546 1412 return 1547 1413 … … 1689 1555 self.models[model.name] = model 1690 1556 1691 self.readCustomCategoryInfo()1692 1693 def readCustomCategoryInfo(self):1694 """1695 Reads the custom model category1696 """1697 #Looking for plugins1698 self.plugins = list(self.custom_models.values())1699 plugin_list = []1700 for name, plug in self.custom_models.items():1701 self.models[name] = plug1702 plugin_list.append([name, True])1703 self.master_category_dict[CATEGORY_CUSTOM] = plugin_list1704 1705 1557 def regenerateModelDict(self): 1706 1558 """ … … 1810 1662 Setting model parameters into QStandardItemModel based on selected _model_ 1811 1663 """ 1812 name = model_name 1813 if self.cbCategory.currentText() == CATEGORY_CUSTOM: 1814 # custom kernel load requires full path 1815 name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py") 1816 kernel_module = generate.load_kernel_module(name) 1664 kernel_module = generate.load_kernel_module(model_name) 1817 1665 self.model_parameters = modelinfo.make_parameter_table(getattr(kernel_module, 'parameters', [])) 1818 1666
Note: See TracChangeset
for help on using the changeset viewer.