Changes in src/sas/qtgui/Perspectives/Fitting/FittingWidget.py [0109f2a:40975f8] in sasview
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r0109f2a r40975f8 49 49 50 50 51 52 51 TAB_MAGNETISM = 4 53 52 TAB_POLY = 3 … … 61 60 62 61 logger = logging.getLogger(__name__) 63 64 62 65 63 class ToolTippedItemModel(QtGui.QStandardItemModel): … … 221 219 # Utility variable to enable unselectable option in category combobox 222 220 self._previous_category_index = 0 223 # Utility variables for multishell display 224 self._n_shells_row = 0 225 self._num_shell_params = 0 221 # Utility variable for multishell display 222 self._last_model_row = 0 226 223 # Dictionary of {model name: model class} for the current category 227 224 self.models = {} … … 251 248 self.kernel_module_copy = None 252 249 250 # dictionaries of current params 251 self.poly_params = {} 252 self.magnet_params = {} 253 253 254 # Page id for fitting 254 255 # To keep with previous SasView values, use 200 as the start offset … … 267 268 self.has_poly_error_column = False 268 269 self.has_magnet_error_column = False 270 271 # If the widget generated theory item, save it 272 self.theory_item = None 269 273 270 274 # signal communicator … … 390 394 # Tag along functionality 391 395 self.label.setText("Data loaded from: ") 392 self.lblFilename.setText(self.logic.data.filename) 396 if self.logic.data.filename: 397 self.lblFilename.setText(self.logic.data.filename) 398 else: 399 self.lblFilename.setText(self.logic.data.name) 393 400 self.updateQRange() 394 401 # Switch off Data2D control … … 523 530 # Signals from separate tabs asking for replot 524 531 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 525 self.options_widget.plot_signal.connect(self.onOptionsUpdate)526 532 527 533 # Signals from other widgets … … 670 676 Return list of all parameters for the current model 671 677 """ 672 return [self._model_model.item(row).text() 673 for row in range(self._model_model.rowCount()) 674 if self.isCheckable(row)] 678 return [self._model_model.item(row).text() for row in range(self._model_model.rowCount())] 675 679 676 680 def modifyViewOnRow(self, row, font=None, brush=None): … … 700 704 assert isinstance(constraint, Constraint) 701 705 assert 0 <= row <= self._model_model.rowCount() 702 assert self.isCheckable(row)703 706 704 707 item = QtGui.QStandardItem() … … 721 724 max_col = self.lstParams.itemDelegate().param_max 722 725 for row in self.selectedParameters(): 723 assert(self.isCheckable(row))724 726 param = self._model_model.item(row, 0).text() 725 727 value = self._model_model.item(row, 1).text() … … 764 766 max_col = self.lstParams.itemDelegate().param_max 765 767 for row in range(self._model_model.rowCount()): 766 if not self.isCheckable(row):767 continue768 768 if not self.rowHasConstraint(row): 769 769 continue … … 794 794 For the given row, return its constraint, if any 795 795 """ 796 if self.isCheckable(row):796 try: 797 797 item = self._model_model.item(row, 1) 798 try: 799 return item.child(0).data() 800 except AttributeError: 801 # return none when no constraints 802 pass 803 return None 798 return item.child(0).data() 799 except AttributeError: 800 # return none when no constraints 801 return None 804 802 805 803 def rowHasConstraint(self, row): … … 807 805 Finds out if row of the main model has a constraint child 808 806 """ 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 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 815 812 return False 816 813 … … 819 816 Finds out if row of the main model has an active constraint child 820 817 """ 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 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 827 823 return False 828 824 … … 831 827 Finds out if row of the main model has an active, nontrivial constraint child 832 828 """ 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 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 839 834 return False 840 835 … … 964 959 model = self.cbModel.currentText() 965 960 966 # empty combobox forced to be read 961 # Assure the control is active 962 if not self.cbModel.isEnabled(): 963 return 964 # Empty combobox forced to be read 967 965 if not model: 968 966 return 969 # Reset structure factor970 self.cbStructureFactor.setCurrentIndex(0)971 967 972 968 # Reset parameters to fit … … 975 971 self.has_poly_error_column = False 976 972 977 self.respondToModelStructure(model=model, structure_factor=None) 973 structure = None 974 if self.cbStructureFactor.isEnabled(): 975 structure = str(self.cbStructureFactor.currentText()) 976 self.respondToModelStructure(model=model, structure_factor=structure) 978 977 979 978 def onSelectBatchFilename(self, data_index): … … 1118 1117 self.disableModelCombo() 1119 1118 self.enableStructureCombo() 1119 # set the index to 0 1120 self.cbStructureFactor.setCurrentIndex(0) 1121 self.model_parameters = None 1120 1122 self._model_model.clear() 1121 1123 return … … 1142 1144 model_row = item.row() 1143 1145 name_index = self._poly_model.index(model_row, 0) 1144 parameter_name = str(name_index.data()) .lower()# "distribution of sld" etc.1145 if " distribution of" in parameter_name:1146 parameter_name = str(name_index.data()) # "distribution of sld" etc. 1147 if "istribution of" in parameter_name: 1146 1148 # just the last word 1147 1149 parameter_name = parameter_name.rsplit()[-1] … … 1188 1190 # Update the sasmodel 1189 1191 # PD[ratio] -> width, npts -> npts, nsigs -> nsigmas 1190 self.kernel_module.setParam(parameter_name + '.' + delegate.columnDict()[model_column], value) 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 1191 1195 1192 1196 # Update plot 1193 1197 self.updateData() 1194 1195 # update in param model1196 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())1200 1198 1201 1199 def onMagnetModelChange(self, item): … … 1226 1224 # Unparsable field 1227 1225 return 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: 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 1239 1243 self.recalculatePlotData() 1240 1244 … … 1497 1501 # Data going in 1498 1502 data = self.logic.data 1499 model = self.kernel_module1503 model = copy.deepcopy(self.kernel_module) 1500 1504 qmin = self.q_range_min 1501 1505 qmax = self.q_range_max 1506 # add polydisperse/magnet parameters if asked 1507 self.updateKernelModelWithExtraParams(model) 1502 1508 1503 1509 params_to_fit = self.main_params_to_fit … … 1509 1515 raise ValueError('Fitting requires at least one parameter to optimize.') 1510 1516 1511 # Potential smearing added1512 # Remember that smearing_min/max can be None ->1513 # deal with it until Python gets discriminated unions1514 self.addWeightingToData(data)1515 1516 1517 # Get the constraints. 1517 1518 constraints = self.getComplexConstraintsForModel() … … 1530 1531 data = GuiUtils.dataFromItem(fit_index) 1531 1532 # Potential weights added directly to data 1532 self.addWeightingToData(data)1533 weighted_data = self.addWeightingToData(data) 1533 1534 try: 1534 fitter_single.set_model(model, fit_id, params_to_fit, data= data,1535 fitter_single.set_model(model, fit_id, params_to_fit, data=weighted_data, 1535 1536 constraints=constraints) 1536 1537 except ValueError as ex: 1537 1538 raise ValueError("Setting model parameters failed with: %s" % ex) 1538 1539 1539 qmin, qmax, _ = self.logic.computeRangeFromData( data)1540 fitter_single.set_data(data= data, id=fit_id, smearer=smearer, qmin=qmin,1540 qmin, qmax, _ = self.logic.computeRangeFromData(weighted_data) 1541 fitter_single.set_data(data=weighted_data, id=fit_id, smearer=smearer, qmin=qmin, 1541 1542 qmax=qmax) 1542 1543 fitter_single.select_problem_for_fit(id=fit_id, value=1) … … 1568 1569 # internal so can use closure for param_dict 1569 1570 param_name = str(self._model_model.item(row, 0).text()) 1570 if not self.isCheckable(row) orparam_name not in list(param_dict.keys()):1571 if param_name not in list(param_dict.keys()): 1571 1572 return 1572 1573 # modify the param value … … 1580 1581 # Utility function for updateof polydispersity part of the main model 1581 1582 param_name = str(self._model_model.item(row, 0).text())+'.width' 1582 if not self.isCheckable(row) orparam_name not in list(param_dict.keys()):1583 if param_name not in list(param_dict.keys()): 1583 1584 return 1584 1585 # modify the param value … … 1929 1930 Adds weighting contribution to fitting data 1930 1931 """ 1932 new_data = copy.deepcopy(data) 1931 1933 # Send original data for weighting 1932 1934 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 1933 1935 if self.is2D: 1934 data.err_data = weight1936 new_data.err_data = weight 1935 1937 else: 1936 data.dy = weight 1937 pass 1938 new_data.dy = weight 1939 1940 return new_data 1938 1941 1939 1942 def updateQRange(self): … … 1955 1958 # Crete/overwrite model items 1956 1959 self._model_model.clear() 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 1960 1961 # First, add parameters from the main model 1962 if model_name is not None: 1963 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() 1964 1976 self.fromStructureFactorToQModel(structure_factor) 1965 else: 1966 # No models selected 1967 return 1968 else: 1969 self.fromModelToQModel(model_name) 1977 1978 # Then, add multishells 1979 if model_name is not None: 1980 # Multishell models need additional treatment 1970 1981 self.addExtraShells() 1971 1982 1972 if structure_factor not in (None, "None"): 1973 # add S(Q) 1974 self.fromStructureFactorToQModel(structure_factor) 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() 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() 1983 1989 1984 1990 # Adjust the table cells width … … 2005 2011 """ 2006 2012 name = model_name 2013 kernel_module = None 2007 2014 if self.cbCategory.currentText() == CATEGORY_CUSTOM: 2008 2015 # custom kernel load requires full path … … 2010 2017 try: 2011 2018 kernel_module = generate.load_kernel_module(name) 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) 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 2017 2031 2018 2032 if hasattr(kernel_module, 'parameters'): … … 2045 2059 self.shell_names = self.shellNamesList() 2046 2060 2047 # Get new rows forQModel2061 # Update the QModel 2048 2062 new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 2049 2063 2050 # Add heading row2051 FittingUtilities.addHeadingRowToModel(self._model_model, model_name)2052 2053 # Update QModel2054 2064 for row in new_rows: 2055 2065 self._model_model.appendRow(row) 2066 # Update the counter used for multishell display 2067 self._last_model_row = self._model_model.rowCount() 2056 2068 2057 2069 def fromStructureFactorToQModel(self, structure_factor): … … 2059 2071 Setting model parameters into QStandardItemModel based on selected _structure factor_ 2060 2072 """ 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 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) 2116 2084 for row in new_rows: 2117 2085 self._model_model.appendRow(row) 2118 2086 # disable fitting of parameters not listed in self.kernel_module (probably radius_effective) 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) 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() 2122 2093 2123 2094 def haveParamsToFit(self): … … 2145 2116 model_row = item.row() 2146 2117 name_index = self._model_model.index(model_row, 0) 2147 name_item = self._model_model.itemFromIndex(name_index)2148 2118 2149 2119 # Extract changed value. … … 2154 2124 return 2155 2125 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)) 2126 parameter_name = str(self._model_model.data(name_index)) # sld, background etc. 2161 2127 2162 2128 # Update the parameter value - note: this supports +/-inf as well … … 2257 2223 name = self.nameFromData(fitted_data) 2258 2224 # Notify the GUI manager so it can create the theory model in DataExplorer 2259 new_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name)2260 self.communicate.updateTheoryFromPerspectiveSignal.emit( new_item)2225 self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 2226 self.communicate.updateTheoryFromPerspectiveSignal.emit(self.theory_item) 2261 2227 2262 2228 def nameFromData(self, fitted_data): … … 2281 2247 return self.completed1D if isinstance(self.data, Data1D) else self.completed2D 2282 2248 2249 def updateKernelModelWithExtraParams(self, model=None): 2250 """ 2251 Updates kernel model 'model' with extra parameters from 2252 the polydisp and magnetism tab, if the tabs are enabled 2253 """ 2254 if model is None: return 2255 if not hasattr(model, 'setParam'): return 2256 2257 # add polydisperse parameters if asked 2258 if self.chkPolydispersity.isChecked(): 2259 for key, value in self.poly_params.items(): 2260 model.setParam(key, value) 2261 # add magnetic params if asked 2262 if self.chkMagnetism.isChecked(): 2263 for key, value in self.magnet_params.items(): 2264 model.setParam(key, value) 2265 2283 2266 def calculateQGridForModelExt(self, data=None, model=None, completefn=None, use_threads=True): 2284 2267 """ … … 2288 2271 data = self.data 2289 2272 if model is None: 2290 model = self.kernel_module 2273 model = copy.deepcopy(self.kernel_module) 2274 self.updateKernelModelWithExtraParams(model) 2275 2291 2276 if completefn is None: 2292 2277 completefn = self.methodCompleteForData() 2293 2278 smearer = self.smearing_widget.smearer() 2279 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 2280 2294 2281 # Awful API to a backend method. 2295 2282 calc_thread = self.methodCalculateForData()(data=data, … … 2300 2287 smearer=smearer, 2301 2288 state=None, 2302 weight= None,2289 weight=weight, 2303 2290 fid=None, 2304 2291 toggle_mode_on=False, … … 2348 2335 residuals = self.calculateResiduals(fitted_data) 2349 2336 self.model_data = fitted_data 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) 2337 new_plots = [fitted_data] 2338 if residuals is not None: 2339 new_plots.append(residuals) 2365 2340 2366 2341 if self.data_is_loaded: 2367 2342 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_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 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 2383 2355 for plot in new_plots: 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]) 2356 self.communicate.plotUpdateSignal.emit([plot]) 2389 2357 2390 2358 def complete2D(self, return_data): … … 2393 2361 """ 2394 2362 fitted_data = self.logic.new2DPlot(return_data) 2395 self.calculateResiduals(fitted_data)2363 residuals = self.calculateResiduals(fitted_data) 2396 2364 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 plots 2370 for plot in new_plots: 2371 self.communicate.plotUpdateSignal.emit([plot]) 2397 2372 2398 2373 def calculateResiduals(self, fitted_data): … … 2404 2379 2405 2380 # Modify fitted_data with weighting 2406 self.addWeightingToData(fitted_data)2407 2408 self.createNewIndex( fitted_data)2381 weighted_data = self.addWeightingToData(fitted_data) 2382 2383 self.createNewIndex(weighted_data) 2409 2384 # Calculate difference between return_data and logic.data 2410 self.chi2 = FittingUtilities.calculateChi2( fitted_data, self.logic.data)2385 self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.logic.data) 2411 2386 # Update the control 2412 2387 chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 2413 2388 self.lblChi2Value.setText(chi2_repr) 2414 2389 2415 # self.communicate.plotUpdateSignal.emit([fitted_data])2416 2417 2390 # Plot residuals if actual data 2418 2391 if not self.data_is_loaded: 2419 2392 return 2420 2393 2421 residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data)2394 residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 2422 2395 residuals_plot.id = "Residual " + residuals_plot.id 2423 2396 self.createNewIndex(residuals_plot) … … 2488 2461 self._poly_model.clear() 2489 2462 2463 parameters = self.model_parameters.form_volume_parameters 2464 if self.is2D: 2465 parameters += self.model_parameters.orientation_parameters 2466 2490 2467 [self.setPolyModelParameters(i, param) for i, param in \ 2491 enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 2468 enumerate(parameters) if param.polydisperse] 2469 2492 2470 FittingUtilities.addPolyHeadersToModel(self._poly_model) 2493 2471 … … 2522 2500 _, min, max = self.kernel_module.details[param_name] 2523 2501 2502 # Update local param dict 2503 self.poly_params[param_name + '.width'] = width 2504 self.poly_params[param_name + '.npts'] = npts 2505 self.poly_params[param_name + '.nsigmas'] = nsigs 2506 2524 2507 # Construct a row with polydisp. related variable. 2525 2508 # This will get added to the polydisp. model … … 2569 2552 def updateFunctionCaption(row): 2570 2553 # Utility function for update of polydispersity function name in the main model 2571 if not self.isCheckable(row):2572 return2573 2554 param_name = str(self._model_model.item(row, 0).text()) 2574 2555 if param_name != param.name: … … 2698 2679 param.units] 2699 2680 2681 self.magnet_params[param.name] = param.default 2682 2700 2683 FittingUtilities.addCheckedListToModel(model, checked_list) 2701 2684 … … 2737 2720 2738 2721 self.lstParams.setIndexWidget(shell_index, func) 2739 self._ n_shells_row = shell_row - 12722 self._last_model_row = self._model_model.rowCount() 2740 2723 2741 2724 # Set the index to the state-kept value … … 2748 2731 """ 2749 2732 # Find row location of the combobox 2750 first_row = self._n_shells_row + 12751 remove_rows = self._ num_shell_params2733 last_row = self._last_model_row 2734 remove_rows = self._model_model.rowCount() - last_row 2752 2735 2753 2736 if remove_rows > 1: 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 2737 self._model_model.removeRows(last_row, remove_rows) 2738 2739 FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index) 2759 2740 self.current_shell_displayed = index 2760 2741 … … 2876 2857 # TODO: add polidyspersity and magnetism 2877 2858 2878 2879 2859 def updateUndo(self): 2880 2860 """ … … 2913 2893 if self.all_data: 2914 2894 index = self.all_data[self.data_index] 2895 else: 2896 index = self.theory_item 2915 2897 report_logic = ReportPageLogic(self, 2916 2898 kernel_module=self.kernel_module, … … 3036 3018 # first - regular params 3037 3019 param_list = [] 3020 3021 param_list.append(['model_name', str(self.cbModel.currentText())]) 3038 3022 def gatherParams(row): 3039 3023 """ … … 3122 3106 if lines[0] != 'sasview_parameter_values': 3123 3107 return False 3124 for line in lines[1:-1]: 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]: 3125 3116 if len(line) != 0: 3126 3117 item = line.split(',') … … 3148 3139 except IndexError: 3149 3140 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 pass 3151 else: 3152 return 3150 3153 3151 3154 self.updateFullModel(context) … … 3186 3189 param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 3187 3190 self._model_model.item(row, 3+ioffset).setText(param_repr) 3191 self.setFocus() 3192 3188 3193 3189 3194 # block signals temporarily, so we don't end up … … 3192 3197 self.iterateOverModel(updateFittedValues) 3193 3198 self._model_model.blockSignals(False) 3199 3194 3200 3195 3201 def updateFullPolyModel(self, param_dict): … … 3236 3242 param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 3237 3243 self._poly_model.item(row, 5+ioffset).setText(param_repr) 3244 self.setFocus() 3238 3245 3239 3246 # block signals temporarily, so we don't end up … … 3243 3250 self._poly_model.blockSignals(False) 3244 3251 3245
Note: See TracChangeset
for help on using the changeset viewer.