Changes in src/sas/qtgui/Perspectives/Fitting/FittingWidget.py [40975f8:0109f2a] in sasview
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r40975f8 r0109f2a 49 49 50 50 51 51 52 TAB_MAGNETISM = 4 52 53 TAB_POLY = 3 … … 60 61 61 62 logger = logging.getLogger(__name__) 63 62 64 63 65 class ToolTippedItemModel(QtGui.QStandardItemModel): … … 219 221 # Utility variable to enable unselectable option in category combobox 220 222 self._previous_category_index = 0 221 # Utility variable for multishell display 222 self._last_model_row = 0 223 # Utility variables for multishell display 224 self._n_shells_row = 0 225 self._num_shell_params = 0 223 226 # Dictionary of {model name: model class} for the current category 224 227 self.models = {} … … 248 251 self.kernel_module_copy = None 249 252 250 # dictionaries of current params251 self.poly_params = {}252 self.magnet_params = {}253 254 253 # Page id for fitting 255 254 # To keep with previous SasView values, use 200 as the start offset … … 268 267 self.has_poly_error_column = False 269 268 self.has_magnet_error_column = False 270 271 # If the widget generated theory item, save it272 self.theory_item = None273 269 274 270 # signal communicator … … 394 390 # Tag along functionality 395 391 self.label.setText("Data loaded from: ") 396 if self.logic.data.filename: 397 self.lblFilename.setText(self.logic.data.filename) 398 else: 399 self.lblFilename.setText(self.logic.data.name) 392 self.lblFilename.setText(self.logic.data.filename) 400 393 self.updateQRange() 401 394 # Switch off Data2D control … … 530 523 # Signals from separate tabs asking for replot 531 524 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 525 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 532 526 533 527 # Signals from other widgets … … 676 670 Return list of all parameters for the current model 677 671 """ 678 return [self._model_model.item(row).text() for row in range(self._model_model.rowCount())] 672 return [self._model_model.item(row).text() 673 for row in range(self._model_model.rowCount()) 674 if self.isCheckable(row)] 679 675 680 676 def modifyViewOnRow(self, row, font=None, brush=None): … … 704 700 assert isinstance(constraint, Constraint) 705 701 assert 0 <= row <= self._model_model.rowCount() 702 assert self.isCheckable(row) 706 703 707 704 item = QtGui.QStandardItem() … … 724 721 max_col = self.lstParams.itemDelegate().param_max 725 722 for row in self.selectedParameters(): 723 assert(self.isCheckable(row)) 726 724 param = self._model_model.item(row, 0).text() 727 725 value = self._model_model.item(row, 1).text() … … 766 764 max_col = self.lstParams.itemDelegate().param_max 767 765 for row in range(self._model_model.rowCount()): 766 if not self.isCheckable(row): 767 continue 768 768 if not self.rowHasConstraint(row): 769 769 continue … … 794 794 For the given row, return its constraint, if any 795 795 """ 796 try:796 if self.isCheckable(row): 797 797 item = self._model_model.item(row, 1) 798 return item.child(0).data() 799 except AttributeError: 800 # return none when no constraints 801 return None 798 try: 799 return item.child(0).data() 800 except AttributeError: 801 # return none when no constraints 802 pass 803 return None 802 804 803 805 def rowHasConstraint(self, row): … … 805 807 Finds out if row of the main model has a constraint child 806 808 """ 807 item = self._model_model.item(row, 1) 808 if item.hasChildren(): 809 c = item.child(0).data() 810 if isinstance(c, Constraint): 811 return True 809 if self.isCheckable(row): 810 item = self._model_model.item(row, 1) 811 if item.hasChildren(): 812 c = item.child(0).data() 813 if isinstance(c, Constraint): 814 return True 812 815 return False 813 816 … … 816 819 Finds out if row of the main model has an active constraint child 817 820 """ 818 item = self._model_model.item(row, 1) 819 if item.hasChildren(): 820 c = item.child(0).data() 821 if isinstance(c, Constraint) and c.active: 822 return True 821 if self.isCheckable(row): 822 item = self._model_model.item(row, 1) 823 if item.hasChildren(): 824 c = item.child(0).data() 825 if isinstance(c, Constraint) and c.active: 826 return True 823 827 return False 824 828 … … 827 831 Finds out if row of the main model has an active, nontrivial constraint child 828 832 """ 829 item = self._model_model.item(row, 1) 830 if item.hasChildren(): 831 c = item.child(0).data() 832 if isinstance(c, Constraint) and c.func and c.active: 833 return True 833 if self.isCheckable(row): 834 item = self._model_model.item(row, 1) 835 if item.hasChildren(): 836 c = item.child(0).data() 837 if isinstance(c, Constraint) and c.func and c.active: 838 return True 834 839 return False 835 840 … … 959 964 model = self.cbModel.currentText() 960 965 961 # Assure the control is active 962 if not self.cbModel.isEnabled(): 963 return 964 # Empty combobox forced to be read 966 # empty combobox forced to be read 965 967 if not model: 966 968 return 969 # Reset structure factor 970 self.cbStructureFactor.setCurrentIndex(0) 967 971 968 972 # Reset parameters to fit … … 971 975 self.has_poly_error_column = False 972 976 973 structure = None 974 if self.cbStructureFactor.isEnabled(): 975 structure = str(self.cbStructureFactor.currentText()) 976 self.respondToModelStructure(model=model, structure_factor=structure) 977 self.respondToModelStructure(model=model, structure_factor=None) 977 978 978 979 def onSelectBatchFilename(self, data_index): … … 1117 1118 self.disableModelCombo() 1118 1119 self.enableStructureCombo() 1119 # set the index to 01120 self.cbStructureFactor.setCurrentIndex(0)1121 self.model_parameters = None1122 1120 self._model_model.clear() 1123 1121 return … … 1144 1142 model_row = item.row() 1145 1143 name_index = self._poly_model.index(model_row, 0) 1146 parameter_name = str(name_index.data()) # "distribution of sld" etc.1147 if " istribution of" in parameter_name:1144 parameter_name = str(name_index.data()).lower() # "distribution of sld" etc. 1145 if "distribution of" in parameter_name: 1148 1146 # just the last word 1149 1147 parameter_name = parameter_name.rsplit()[-1] … … 1190 1188 # Update the sasmodel 1191 1189 # PD[ratio] -> width, npts -> npts, nsigs -> nsigmas 1192 #self.kernel_module.setParam(parameter_name + '.' + delegate.columnDict()[model_column], value) 1193 key = parameter_name + '.' + delegate.columnDict()[model_column] 1194 self.poly_params[key] = value 1190 self.kernel_module.setParam(parameter_name + '.' + delegate.columnDict()[model_column], value) 1195 1191 1196 1192 # Update plot 1197 1193 self.updateData() 1194 1195 # update in param model 1196 if model_column in [delegate.poly_pd, delegate.poly_error, delegate.poly_min, delegate.poly_max]: 1197 row = self.getRowFromName(parameter_name) 1198 param_item = self._model_model.item(row) 1199 param_item.child(0).child(0, model_column).setText(item.text()) 1198 1200 1199 1201 def onMagnetModelChange(self, item): … … 1224 1226 # Unparsable field 1225 1227 return 1226 delegate = self.lstMagnetic.itemDelegate() 1227 1228 if model_column > 1: 1229 if model_column == delegate.mag_min: 1230 pos = 1 1231 elif model_column == delegate.mag_max: 1232 pos = 2 1233 elif model_column == delegate.mag_unit: 1234 pos = 0 1235 else: 1236 raise AttributeError("Wrong column in magnetism table.") 1237 # min/max to be changed in self.kernel_module.details[parameter_name] = ['Ang', 0.0, inf] 1238 self.kernel_module.details[parameter_name][pos] = value 1239 else: 1240 self.magnet_params[parameter_name] = value 1241 #self.kernel_module.setParam(parameter_name) = value 1242 # Force the chart update when actual parameters changed 1228 1229 property_index = self._magnet_model.headerData(1, model_column)-1 # Value, min, max, etc. 1230 1231 # Update the parameter value - note: this supports +/-inf as well 1232 self.kernel_module.params[parameter_name] = value 1233 1234 # min/max to be changed in self.kernel_module.details[parameter_name] = ['Ang', 0.0, inf] 1235 self.kernel_module.details[parameter_name][property_index] = value 1236 1237 # Force the chart update when actual parameters changed 1238 if model_column == 1: 1243 1239 self.recalculatePlotData() 1244 1240 … … 1501 1497 # Data going in 1502 1498 data = self.logic.data 1503 model = copy.deepcopy(self.kernel_module)1499 model = self.kernel_module 1504 1500 qmin = self.q_range_min 1505 1501 qmax = self.q_range_max 1506 # add polydisperse/magnet parameters if asked1507 self.updateKernelModelWithExtraParams(model)1508 1502 1509 1503 params_to_fit = self.main_params_to_fit … … 1515 1509 raise ValueError('Fitting requires at least one parameter to optimize.') 1516 1510 1511 # Potential smearing added 1512 # Remember that smearing_min/max can be None -> 1513 # deal with it until Python gets discriminated unions 1514 self.addWeightingToData(data) 1515 1517 1516 # Get the constraints. 1518 1517 constraints = self.getComplexConstraintsForModel() … … 1531 1530 data = GuiUtils.dataFromItem(fit_index) 1532 1531 # Potential weights added directly to data 1533 weighted_data =self.addWeightingToData(data)1532 self.addWeightingToData(data) 1534 1533 try: 1535 fitter_single.set_model(model, fit_id, params_to_fit, data= weighted_data,1534 fitter_single.set_model(model, fit_id, params_to_fit, data=data, 1536 1535 constraints=constraints) 1537 1536 except ValueError as ex: 1538 1537 raise ValueError("Setting model parameters failed with: %s" % ex) 1539 1538 1540 qmin, qmax, _ = self.logic.computeRangeFromData( weighted_data)1541 fitter_single.set_data(data= weighted_data, id=fit_id, smearer=smearer, qmin=qmin,1539 qmin, qmax, _ = self.logic.computeRangeFromData(data) 1540 fitter_single.set_data(data=data, id=fit_id, smearer=smearer, qmin=qmin, 1542 1541 qmax=qmax) 1543 1542 fitter_single.select_problem_for_fit(id=fit_id, value=1) … … 1569 1568 # internal so can use closure for param_dict 1570 1569 param_name = str(self._model_model.item(row, 0).text()) 1571 if param_name not in list(param_dict.keys()):1570 if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 1572 1571 return 1573 1572 # modify the param value … … 1581 1580 # Utility function for updateof polydispersity part of the main model 1582 1581 param_name = str(self._model_model.item(row, 0).text())+'.width' 1583 if param_name not in list(param_dict.keys()):1582 if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 1584 1583 return 1585 1584 # modify the param value … … 1930 1929 Adds weighting contribution to fitting data 1931 1930 """ 1932 new_data = copy.deepcopy(data)1933 1931 # Send original data for weighting 1934 1932 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 1935 1933 if self.is2D: 1936 new_data.err_data = weight1934 data.err_data = weight 1937 1935 else: 1938 new_data.dy = weight 1939 1940 return new_data 1936 data.dy = weight 1937 pass 1941 1938 1942 1939 def updateQRange(self): … … 1958 1955 # Crete/overwrite model items 1959 1956 self._model_model.clear() 1960 1961 # First, add parameters from the main model 1962 if model_name is not None: 1957 self._poly_model.clear() 1958 self._magnet_model.clear() 1959 1960 if model_name is None: 1961 if structure_factor not in (None, "None"): 1962 # S(Q) on its own, treat the same as a form factor 1963 self.kernel_module = None 1964 self.fromStructureFactorToQModel(structure_factor) 1965 else: 1966 # No models selected 1967 return 1968 else: 1963 1969 self.fromModelToQModel(model_name) 1964 1965 # Then, add structure factor derived parameters 1966 if structure_factor is not None and structure_factor != "None": 1967 if model_name is None: 1968 # Instantiate the current sasmodel for SF-only models 1969 self.kernel_module = self.models[structure_factor]() 1970 self.fromStructureFactorToQModel(structure_factor) 1971 else: 1972 # Allow the SF combobox visibility for the given sasmodel 1973 self.enableStructureFactorControl(structure_factor) 1974 if self.cbStructureFactor.isEnabled(): 1975 structure_factor = self.cbStructureFactor.currentText() 1970 self.addExtraShells() 1971 1972 if structure_factor not in (None, "None"): 1973 # add S(Q) 1976 1974 self.fromStructureFactorToQModel(structure_factor) 1977 1978 # Then, add multishells 1979 if model_name is not None: 1980 # Multishell models need additional treatment 1981 self.addExtraShells() 1982 1983 # Add polydispersity to the model 1984 self.poly_params = {} 1985 self.setPolyModel() 1986 # Add magnetic parameters to the model 1987 self.magnet_params = {} 1988 self.setMagneticModel() 1975 else: 1976 # enable selection of S(Q) 1977 self.enableStructureFactorControl(structure_factor) 1978 1979 # Add polydispersity to the model 1980 self.setPolyModel() 1981 # Add magnetic parameters to the model 1982 self.setMagneticModel() 1989 1983 1990 1984 # Adjust the table cells width … … 2011 2005 """ 2012 2006 name = model_name 2013 kernel_module = None2014 2007 if self.cbCategory.currentText() == CATEGORY_CUSTOM: 2015 2008 # custom kernel load requires full path … … 2017 2010 try: 2018 2011 kernel_module = generate.load_kernel_module(name) 2019 except ModuleNotFoundError as ex: 2020 pass 2021 2022 if kernel_module is None: 2023 # mismatch between "name" attribute and actual filename. 2024 curr_model = self.models[model_name] 2025 name, _ = os.path.splitext(os.path.basename(curr_model.filename)) 2026 try: 2027 kernel_module = generate.load_kernel_module(name) 2028 except ModuleNotFoundError as ex: 2029 logging.error("Can't find the model "+ str(ex)) 2030 return 2012 except ModuleNotFoundError: 2013 # maybe it's a recategorised custom model? 2014 name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py") 2015 # If this rises, it's a valid problem. 2016 kernel_module = generate.load_kernel_module(name) 2031 2017 2032 2018 if hasattr(kernel_module, 'parameters'): … … 2059 2045 self.shell_names = self.shellNamesList() 2060 2046 2061 # Update theQModel2047 # Get new rows for QModel 2062 2048 new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 2063 2049 2050 # Add heading row 2051 FittingUtilities.addHeadingRowToModel(self._model_model, model_name) 2052 2053 # Update QModel 2064 2054 for row in new_rows: 2065 2055 self._model_model.appendRow(row) 2066 # Update the counter used for multishell display2067 self._last_model_row = self._model_model.rowCount()2068 2056 2069 2057 def fromStructureFactorToQModel(self, structure_factor): … … 2071 2059 Setting model parameters into QStandardItemModel based on selected _structure factor_ 2072 2060 """ 2073 if structure_factor is None or structure_factor=="None": 2074 return 2075 structure_module = generate.load_kernel_module(structure_factor) 2076 structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) 2077 2078 structure_kernel = self.models[structure_factor]() 2079 form_kernel = self.kernel_module 2080 2081 self.kernel_module = MultiplicationModel(form_kernel, structure_kernel) 2082 2083 new_rows = FittingUtilities.addSimpleParametersToModel(structure_parameters, self.is2D) 2061 s_kernel = self.models[structure_factor]() 2062 p_kernel = self.kernel_module 2063 2064 if p_kernel is None: 2065 # Not a product model, just S(Q) 2066 self.kernel_module = s_kernel 2067 params = modelinfo.ParameterTable(self.kernel_module._model_info.parameters.kernel_parameters) 2068 new_rows = FittingUtilities.addSimpleParametersToModel(params, self.is2D) 2069 else: 2070 p_pars_len = len(p_kernel._model_info.parameters.kernel_parameters) 2071 s_pars_len = len(s_kernel._model_info.parameters.kernel_parameters) 2072 2073 self.kernel_module = MultiplicationModel(p_kernel, s_kernel) 2074 all_params = self.kernel_module._model_info.parameters.kernel_parameters 2075 all_param_names = [param.name for param in all_params] 2076 2077 # S(Q) params from the product model are not necessarily the same as those from the S(Q) model; any 2078 # conflicting names with P(Q) params will cause a rename; we also lose radius_effective (for now...) 2079 2080 # TODO: merge rest of beta approx implementation in 2081 # This is to ensure compatibility when we merge beta approx support in...! 2082 2083 # radius_effective is always s_params[0] 2084 2085 # if radius_effective_mode is in all_params, then all_params contains radius_effective and we want to 2086 # keep it in the model 2087 2088 # if radius_effective_mode is NOT in all_params, then radius_effective should NOT be kept, because the user 2089 # cannot specify it themselves; but, make sure we only remove it if it's actually there in the first place 2090 # (sasmodels master removes it already) 2091 if "radius_effective_mode" in all_param_names: 2092 # Show all parameters 2093 s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len]) 2094 s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters) 2095 else: 2096 # Ensure radius_effective is not displayed 2097 s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters[1:]) 2098 if "radius_effective" in all_param_names: 2099 s_params = modelinfo.ParameterTable(all_params[p_pars_len+1:p_pars_len+s_pars_len]) 2100 else: 2101 s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len-1]) 2102 2103 # Get new rows for QModel 2104 # Any renamed parameters are stored as data in the relevant item, for later handling 2105 new_rows = FittingUtilities.addSimpleParametersToModel(s_params, self.is2D, s_params_orig) 2106 2107 # TODO: merge rest of beta approx implementation in 2108 # These parameters are not part of P(Q) nor S(Q), but are added only to the product model (e.g. specifying 2109 # structure factor calculation mode) 2110 # product_params = all_params[p_pars_len+s_pars_len:] 2111 2112 # Add heading row 2113 FittingUtilities.addHeadingRowToModel(self._model_model, structure_factor) 2114 2115 # Update QModel 2084 2116 for row in new_rows: 2085 2117 self._model_model.appendRow(row) 2086 2118 # disable fitting of parameters not listed in self.kernel_module (probably radius_effective) 2087 if row[0].text() not in self.kernel_module.params.keys(): 2088 row_num = self._model_model.rowCount() - 1 2089 FittingUtilities.markParameterDisabled(self._model_model, row_num) 2090 2091 # Update the counter used for multishell display 2092 self._last_model_row = self._model_model.rowCount() 2119 # if row[0].text() not in self.kernel_module.params.keys(): 2120 # row_num = self._model_model.rowCount() - 1 2121 # FittingUtilities.markParameterDisabled(self._model_model, row_num) 2093 2122 2094 2123 def haveParamsToFit(self): … … 2116 2145 model_row = item.row() 2117 2146 name_index = self._model_model.index(model_row, 0) 2147 name_item = self._model_model.itemFromIndex(name_index) 2118 2148 2119 2149 # Extract changed value. … … 2124 2154 return 2125 2155 2126 parameter_name = str(self._model_model.data(name_index)) # sld, background etc. 2156 # if the item has user data, this is the actual parameter name (e.g. to handle duplicate names) 2157 if name_item.data(QtCore.Qt.UserRole): 2158 parameter_name = str(name_item.data(QtCore.Qt.UserRole)) 2159 else: 2160 parameter_name = str(self._model_model.data(name_index)) 2127 2161 2128 2162 # Update the parameter value - note: this supports +/-inf as well … … 2223 2257 name = self.nameFromData(fitted_data) 2224 2258 # Notify the GUI manager so it can create the theory model in DataExplorer 2225 self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name)2226 self.communicate.updateTheoryFromPerspectiveSignal.emit( self.theory_item)2259 new_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 2260 self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item) 2227 2261 2228 2262 def nameFromData(self, fitted_data): … … 2247 2281 return self.completed1D if isinstance(self.data, Data1D) else self.completed2D 2248 2282 2249 def updateKernelModelWithExtraParams(self, model=None):2250 """2251 Updates kernel model 'model' with extra parameters from2252 the polydisp and magnetism tab, if the tabs are enabled2253 """2254 if model is None: return2255 if not hasattr(model, 'setParam'): return2256 2257 # add polydisperse parameters if asked2258 if self.chkPolydispersity.isChecked():2259 for key, value in self.poly_params.items():2260 model.setParam(key, value)2261 # add magnetic params if asked2262 if self.chkMagnetism.isChecked():2263 for key, value in self.magnet_params.items():2264 model.setParam(key, value)2265 2266 2283 def calculateQGridForModelExt(self, data=None, model=None, completefn=None, use_threads=True): 2267 2284 """ … … 2271 2288 data = self.data 2272 2289 if model is None: 2273 model = copy.deepcopy(self.kernel_module) 2274 self.updateKernelModelWithExtraParams(model) 2275 2290 model = self.kernel_module 2276 2291 if completefn is None: 2277 2292 completefn = self.methodCompleteForData() 2278 2293 smearer = self.smearing_widget.smearer() 2279 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting)2280 2281 2294 # Awful API to a backend method. 2282 2295 calc_thread = self.methodCalculateForData()(data=data, … … 2287 2300 smearer=smearer, 2288 2301 state=None, 2289 weight= weight,2302 weight=None, 2290 2303 fid=None, 2291 2304 toggle_mode_on=False, … … 2335 2348 residuals = self.calculateResiduals(fitted_data) 2336 2349 self.model_data = fitted_data 2337 new_plots = [fitted_data] 2338 if residuals is not None: 2339 new_plots.append(residuals) 2350 2351 new_plots = [fitted_data, residuals] 2352 2353 # Create plots for intermediate product data 2354 pq_data, sq_data = self.logic.new1DProductPlots(return_data, self.tab_id) 2355 if pq_data is not None: 2356 pq_data.symbol = "Line" 2357 self.createNewIndex(pq_data) 2358 # self.communicate.plotUpdateSignal.emit([pq_data]) 2359 new_plots.append(pq_data) 2360 if sq_data is not None: 2361 sq_data.symbol = "Line" 2362 self.createNewIndex(sq_data) 2363 # self.communicate.plotUpdateSignal.emit([sq_data]) 2364 new_plots.append(sq_data) 2340 2365 2341 2366 if self.data_is_loaded: 2342 2367 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 2343 else: 2344 # delete theory items for the model, in order to get rid of any redundant items, e.g. beta(Q), S_eff(Q) 2345 self.communicate.deleteIntermediateTheoryPlotsSignal.emit(self.kernel_module.id) 2346 2347 # Create plots for intermediate product data 2348 plots = self.logic.new1DProductPlots(return_data, self.tab_id) 2349 for plot in plots: 2350 plot.symbol = "Line" 2351 self.createNewIndex(plot) 2352 new_plots.append(plot) 2353 2354 # Update/generate plots 2368 2369 # TODO: merge rest of beta approx implementation in 2370 # TODO: refactor 2371 # deal with constrained radius_effective 2372 # for row in range(self._model_model.rowCount()): 2373 # if self._model_model.item(row, 0).text() == "radius_effective_mode": 2374 # if GuiUtils.toDouble(self._model_model.item(row, 1).text()) == 0: 2375 # return 2376 # radius_effective = intermediate_ER() 2377 # if radius_effective: 2378 # for row in range(self._model_model.rowCount()): 2379 # if self._model_model.item(row, 0).text() == "radius_effective": 2380 # self._model_model.item(row, 1).setText(str(radius_effective)) 2381 # break 2382 2355 2383 for plot in new_plots: 2356 self.communicate.plotUpdateSignal.emit([plot]) 2384 if hasattr(plot, "id") and "esidual" in plot.id: 2385 # TODO: fix updates to residuals plot 2386 pass 2387 elif plot is not None: 2388 self.communicate.plotUpdateSignal.emit([plot]) 2357 2389 2358 2390 def complete2D(self, return_data): … … 2361 2393 """ 2362 2394 fitted_data = self.logic.new2DPlot(return_data) 2363 residuals =self.calculateResiduals(fitted_data)2395 self.calculateResiduals(fitted_data) 2364 2396 self.model_data = fitted_data 2365 new_plots = [fitted_data]2366 if residuals is not None:2367 new_plots.append(residuals)2368 2369 # Update/generate plots2370 for plot in new_plots:2371 self.communicate.plotUpdateSignal.emit([plot])2372 2397 2373 2398 def calculateResiduals(self, fitted_data): … … 2379 2404 2380 2405 # Modify fitted_data with weighting 2381 weighted_data =self.addWeightingToData(fitted_data)2382 2383 self.createNewIndex( weighted_data)2406 self.addWeightingToData(fitted_data) 2407 2408 self.createNewIndex(fitted_data) 2384 2409 # Calculate difference between return_data and logic.data 2385 self.chi2 = FittingUtilities.calculateChi2( weighted_data, self.logic.data)2410 self.chi2 = FittingUtilities.calculateChi2(fitted_data, self.logic.data) 2386 2411 # Update the control 2387 2412 chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 2388 2413 self.lblChi2Value.setText(chi2_repr) 2389 2414 2415 # self.communicate.plotUpdateSignal.emit([fitted_data]) 2416 2390 2417 # Plot residuals if actual data 2391 2418 if not self.data_is_loaded: 2392 2419 return 2393 2420 2394 residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data)2421 residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data) 2395 2422 residuals_plot.id = "Residual " + residuals_plot.id 2396 2423 self.createNewIndex(residuals_plot) … … 2461 2488 self._poly_model.clear() 2462 2489 2463 parameters = self.model_parameters.form_volume_parameters2464 if self.is2D:2465 parameters += self.model_parameters.orientation_parameters2466 2467 2490 [self.setPolyModelParameters(i, param) for i, param in \ 2468 enumerate(parameters) if param.polydisperse] 2469 2491 enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 2470 2492 FittingUtilities.addPolyHeadersToModel(self._poly_model) 2471 2493 … … 2500 2522 _, min, max = self.kernel_module.details[param_name] 2501 2523 2502 # Update local param dict2503 self.poly_params[param_name + '.width'] = width2504 self.poly_params[param_name + '.npts'] = npts2505 self.poly_params[param_name + '.nsigmas'] = nsigs2506 2507 2524 # Construct a row with polydisp. related variable. 2508 2525 # This will get added to the polydisp. model … … 2552 2569 def updateFunctionCaption(row): 2553 2570 # Utility function for update of polydispersity function name in the main model 2571 if not self.isCheckable(row): 2572 return 2554 2573 param_name = str(self._model_model.item(row, 0).text()) 2555 2574 if param_name != param.name: … … 2679 2698 param.units] 2680 2699 2681 self.magnet_params[param.name] = param.default2682 2683 2700 FittingUtilities.addCheckedListToModel(model, checked_list) 2684 2701 … … 2720 2737 2721 2738 self.lstParams.setIndexWidget(shell_index, func) 2722 self._ last_model_row = self._model_model.rowCount()2739 self._n_shells_row = shell_row - 1 2723 2740 2724 2741 # Set the index to the state-kept value … … 2731 2748 """ 2732 2749 # Find row location of the combobox 2733 last_row = self._last_model_row2734 remove_rows = self._ model_model.rowCount() - last_row2750 first_row = self._n_shells_row + 1 2751 remove_rows = self._num_shell_params 2735 2752 2736 2753 if remove_rows > 1: 2737 self._model_model.removeRows(last_row, remove_rows) 2738 2739 FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index) 2754 self._model_model.removeRows(first_row, remove_rows) 2755 2756 new_rows = FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index, first_row) 2757 self._num_shell_params = len(new_rows) 2758 2740 2759 self.current_shell_displayed = index 2741 2760 … … 2857 2876 # TODO: add polidyspersity and magnetism 2858 2877 2878 2859 2879 def updateUndo(self): 2860 2880 """ … … 2893 2913 if self.all_data: 2894 2914 index = self.all_data[self.data_index] 2895 else:2896 index = self.theory_item2897 2915 report_logic = ReportPageLogic(self, 2898 2916 kernel_module=self.kernel_module, … … 3018 3036 # first - regular params 3019 3037 param_list = [] 3020 3021 param_list.append(['model_name', str(self.cbModel.currentText())])3022 3038 def gatherParams(row): 3023 3039 """ … … 3106 3122 if lines[0] != 'sasview_parameter_values': 3107 3123 return False 3108 3109 model = lines[1].split(',') 3110 3111 if model[0] != 'model_name': 3112 return False 3113 3114 context['model_name'] = [model[1]] 3115 for line in lines[2:-1]: 3124 for line in lines[1:-1]: 3116 3125 if len(line) != 0: 3117 3126 item = line.split(',') … … 3139 3148 except IndexError: 3140 3149 pass 3141 3142 if str(self.cbModel.currentText()) != str(context['model_name'][0]):3143 msg = QtWidgets.QMessageBox()3144 msg.setIcon(QtWidgets.QMessageBox.Information)3145 msg.setText("The model in the clipboard is not the same as the currently loaded model. \3146 Not all parameters saved may paste correctly.")3147 msg.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)3148 result = msg.exec_()3149 if result == QtWidgets.QMessageBox.Ok:3150 pass3151 else:3152 return3153 3150 3154 3151 self.updateFullModel(context) … … 3189 3186 param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 3190 3187 self._model_model.item(row, 3+ioffset).setText(param_repr) 3191 self.setFocus()3192 3193 3188 3194 3189 # block signals temporarily, so we don't end up … … 3197 3192 self.iterateOverModel(updateFittedValues) 3198 3193 self._model_model.blockSignals(False) 3199 3200 3194 3201 3195 def updateFullPolyModel(self, param_dict): … … 3242 3236 param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 3243 3237 self._poly_model.item(row, 5+ioffset).setText(param_repr) 3244 self.setFocus()3245 3238 3246 3239 # block signals temporarily, so we don't end up … … 3250 3243 self._poly_model.blockSignals(False) 3251 3244 3245
Note: See TracChangeset
for help on using the changeset viewer.