Changeset 6da3e3d in sasview for src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
- Timestamp:
- Sep 6, 2018 3:27:00 AM (6 years ago)
- Branches:
- ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- f84d793, 47471ec
- Parents:
- 0eff615 (diff), 605d944 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r0eff615 r6da3e3d 60 60 61 61 logger = logging.getLogger(__name__) 62 63 62 64 63 class ToolTippedItemModel(QtGui.QStandardItemModel): … … 225 224 self.models = {} 226 225 # Parameters to fit 227 self.parameters_to_fit = None 226 self.main_params_to_fit = [] 227 self.poly_params_to_fit = [] 228 self.magnet_params_to_fit = [] 229 228 230 # Fit options 229 231 self.q_range_min = 0.005 … … 263 265 self.has_magnet_error_column = False 264 266 267 # If the widget generated theory item, save it 268 self.theory_item = None 269 265 270 # signal communicator 266 271 self.communicate = self.parent.communicate … … 385 390 # Tag along functionality 386 391 self.label.setText("Data loaded from: ") 387 self.lblFilename.setText(self.logic.data.filename) 392 if self.logic.data.filename: 393 self.lblFilename.setText(self.logic.data.filename) 394 else: 395 self.lblFilename.setText(self.logic.data.name) 388 396 self.updateQRange() 389 397 # Switch off Data2D control … … 517 525 518 526 # Signals from separate tabs asking for replot 519 self.options_widget.plot_signal.connect(self.onOptionsUpdate)520 527 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 521 528 … … 948 955 model = self.cbModel.currentText() 949 956 950 # empty combobox forced to be read 957 # Assure the control is active 958 if not self.cbModel.isEnabled(): 959 return 960 # Empty combobox forced to be read 951 961 if not model: 952 962 return 953 # Reset structure factor954 self.cbStructureFactor.setCurrentIndex(0)955 963 956 964 # Reset parameters to fit 957 self. parameters_to_fit = None965 self.resetParametersToFit() 958 966 self.has_error_column = False 959 967 self.has_poly_error_column = False 960 968 961 self.respondToModelStructure(model=model, structure_factor=None) 969 structure = None 970 if self.cbStructureFactor.isEnabled(): 971 structure = str(self.cbStructureFactor.currentText()) 972 self.respondToModelStructure(model=model, structure_factor=structure) 962 973 963 974 def onSelectBatchFilename(self, data_index): … … 979 990 980 991 # Reset parameters to fit 981 self. parameters_to_fit = None992 self.resetParametersToFit() 982 993 self.has_error_column = False 983 994 self.has_poly_error_column = False 984 995 985 996 self.respondToModelStructure(model=model, structure_factor=structure) 997 998 def resetParametersToFit(self): 999 """ 1000 Clears the list of parameters to be fitted 1001 """ 1002 self.main_params_to_fit = [] 1003 self.poly_params_to_fit = [] 1004 self.magnet_params_to_fit = [] 986 1005 987 1006 def onCustomModelChange(self): … … 1094 1113 self.disableModelCombo() 1095 1114 self.enableStructureCombo() 1115 # set the index to 0 1116 self.cbStructureFactor.setCurrentIndex(0) 1117 self.model_parameters = None 1096 1118 self._model_model.clear() 1097 1119 return … … 1118 1140 model_row = item.row() 1119 1141 name_index = self._poly_model.index(model_row, 0) 1120 parameter_name = str(name_index.data()) .lower()# "distribution of sld" etc.1121 if " distribution of" in parameter_name:1142 parameter_name = str(name_index.data()) # "distribution of sld" etc. 1143 if "istribution of" in parameter_name: 1122 1144 # just the last word 1123 1145 parameter_name = parameter_name.rsplit()[-1] … … 1131 1153 parameter_name = parameter_name + '.width' 1132 1154 if value == QtCore.Qt.Checked: 1133 self.p arameters_to_fit.append(parameter_name)1155 self.poly_params_to_fit.append(parameter_name) 1134 1156 else: 1135 if parameter_name in self.p arameters_to_fit:1136 self.p arameters_to_fit.remove(parameter_name)1137 self.cmdFit.setEnabled(self. parameters_to_fit != [] and self.logic.data_is_loaded)1157 if parameter_name in self.poly_params_to_fit: 1158 self.poly_params_to_fit.remove(parameter_name) 1159 self.cmdFit.setEnabled(self.haveParamsToFit()) 1138 1160 1139 1161 elif model_column in [delegate.poly_min, delegate.poly_max]: … … 1187 1209 value = item.checkState() 1188 1210 if value == QtCore.Qt.Checked: 1189 self. parameters_to_fit.append(parameter_name)1211 self.magnet_params_to_fit.append(parameter_name) 1190 1212 else: 1191 if parameter_name in self. parameters_to_fit:1192 self. parameters_to_fit.remove(parameter_name)1193 self.cmdFit.setEnabled(self. parameters_to_fit != [] and self.logic.data_is_loaded)1213 if parameter_name in self.magnet_params_to_fit: 1214 self.magnet_params_to_fit.remove(parameter_name) 1215 self.cmdFit.setEnabled(self.haveParamsToFit()) 1194 1216 # Update state stack 1195 1217 self.updateUndo() … … 1476 1498 qmin = self.q_range_min 1477 1499 qmax = self.q_range_max 1478 params_to_fit = self.parameters_to_fit 1500 1501 params_to_fit = self.main_params_to_fit 1502 if self.chkPolydispersity.isChecked(): 1503 params_to_fit += self.poly_params_to_fit 1504 if self.chkMagnetism.isChecked(): 1505 params_to_fit += self.magnet_params_to_fit 1479 1506 if not params_to_fit: 1480 1507 raise ValueError('Fitting requires at least one parameter to optimize.') 1481 1482 # Potential smearing added1483 # Remember that smearing_min/max can be None ->1484 # deal with it until Python gets discriminated unions1485 self.addWeightingToData(data)1486 1508 1487 1509 # Get the constraints. … … 1501 1523 data = GuiUtils.dataFromItem(fit_index) 1502 1524 # Potential weights added directly to data 1503 self.addWeightingToData(data)1525 weighted_data = self.addWeightingToData(data) 1504 1526 try: 1505 fitter_single.set_model(model, fit_id, params_to_fit, data= data,1527 fitter_single.set_model(model, fit_id, params_to_fit, data=weighted_data, 1506 1528 constraints=constraints) 1507 1529 except ValueError as ex: 1508 1530 raise ValueError("Setting model parameters failed with: %s" % ex) 1509 1531 1510 qmin, qmax, _ = self.logic.computeRangeFromData( data)1511 fitter_single.set_data(data= data, id=fit_id, smearer=smearer, qmin=qmin,1532 qmin, qmax, _ = self.logic.computeRangeFromData(weighted_data) 1533 fitter_single.set_data(data=weighted_data, id=fit_id, smearer=smearer, qmin=qmin, 1512 1534 qmax=qmax) 1513 1535 fitter_single.select_problem_for_fit(id=fit_id, value=1) … … 1900 1922 Adds weighting contribution to fitting data 1901 1923 """ 1924 new_data = copy.deepcopy(data) 1902 1925 # Send original data for weighting 1903 1926 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 1904 1927 if self.is2D: 1905 data.err_data = weight1928 new_data.err_data = weight 1906 1929 else: 1907 data.dy = weight 1908 pass 1930 new_data.dy = weight 1931 1932 return new_data 1909 1933 1910 1934 def updateQRange(self): … … 1940 1964 # Allow the SF combobox visibility for the given sasmodel 1941 1965 self.enableStructureFactorControl(structure_factor) 1966 if self.cbStructureFactor.isEnabled(): 1967 structure_factor = self.cbStructureFactor.currentText() 1968 self.fromStructureFactorToQModel(structure_factor) 1942 1969 1943 1970 # Then, add multishells … … 1974 2001 """ 1975 2002 name = model_name 2003 kernel_module = None 1976 2004 if self.cbCategory.currentText() == CATEGORY_CUSTOM: 1977 2005 # custom kernel load requires full path … … 1979 2007 try: 1980 2008 kernel_module = generate.load_kernel_module(name) 1981 except ModuleNotFoundError: 1982 # maybe it's a recategorised custom model? 1983 name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py") 1984 # If this rises, it's a valid problem. 1985 kernel_module = generate.load_kernel_module(name) 2009 except ModuleNotFoundError as ex: 2010 pass 2011 2012 if kernel_module is None: 2013 # mismatch between "name" attribute and actual filename. 2014 curr_model = self.models[model_name] 2015 name, _ = os.path.splitext(os.path.basename(curr_model.filename)) 2016 try: 2017 kernel_module = generate.load_kernel_module(name) 2018 except ModuleNotFoundError as ex: 2019 logging.error("Can't find the model "+ str(ex)) 2020 return 1986 2021 1987 2022 if hasattr(kernel_module, 'parameters'): … … 2026 2061 Setting model parameters into QStandardItemModel based on selected _structure factor_ 2027 2062 """ 2063 if structure_factor is None or structure_factor=="None": 2064 return 2028 2065 structure_module = generate.load_kernel_module(structure_factor) 2029 2066 structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) … … 2045 2082 self._last_model_row = self._model_model.rowCount() 2046 2083 2084 def haveParamsToFit(self): 2085 """ 2086 Finds out if there are any parameters ready to be fitted 2087 """ 2088 return (self.main_params_to_fit!=[] 2089 or self.poly_params_to_fit!=[] 2090 or self.magnet_params_to_fit != []) and \ 2091 self.logic.data_is_loaded 2092 2047 2093 def onMainParamsChange(self, item): 2048 2094 """ … … 2053 2099 if model_column == 0: 2054 2100 self.checkboxSelected(item) 2055 self.cmdFit.setEnabled(self. parameters_to_fit != [] and self.logic.data_is_loaded)2101 self.cmdFit.setEnabled(self.haveParamsToFit()) 2056 2102 # Update state stack 2057 2103 self.updateUndo() … … 2112 2158 # Convert to proper indices and set requested enablement 2113 2159 self.setParameterSelection(status) 2114 #[self._model_model.item(row, 0).setCheckState(status) for row in self.selectedParameters()]2115 2160 self._model_model.blockSignals(False) 2116 2161 2117 2162 # update the list of parameters to fit 2118 main_params = self.checkedListFromModel(self._model_model) 2119 poly_params = self.checkedListFromModel(self._poly_model) 2120 magnet_params = self.checkedListFromModel(self._magnet_model) 2121 2122 # Retrieve poly params names 2123 poly_params = [param.rsplit()[-1] + '.width' for param in poly_params] 2124 2125 self.parameters_to_fit = main_params + poly_params + magnet_params 2163 self.main_params_to_fit = self.checkedListFromModel(self._model_model) 2126 2164 2127 2165 def checkedListFromModel(self, model): … … 2175 2213 name = self.nameFromData(fitted_data) 2176 2214 # Notify the GUI manager so it can create the theory model in DataExplorer 2177 new_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name)2178 self.communicate.updateTheoryFromPerspectiveSignal.emit( new_item)2215 self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 2216 self.communicate.updateTheoryFromPerspectiveSignal.emit(self.theory_item) 2179 2217 2180 2218 def nameFromData(self, fitted_data): … … 2210 2248 completefn = self.methodCompleteForData() 2211 2249 smearer = self.smearing_widget.smearer() 2250 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 2251 2212 2252 # Awful API to a backend method. 2213 2253 calc_thread = self.methodCalculateForData()(data=data, … … 2218 2258 smearer=smearer, 2219 2259 state=None, 2220 weight= None,2260 weight=weight, 2221 2261 fid=None, 2222 2262 toggle_mode_on=False, … … 2266 2306 residuals = self.calculateResiduals(fitted_data) 2267 2307 self.model_data = fitted_data 2268 2269 new_plots = [fitted_data, residuals] 2308 new_plots = [fitted_data] 2309 if residuals is not None: 2310 new_plots.append(residuals) 2311 2312 if self.data_is_loaded: 2313 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 2314 else: 2315 # delete theory items for the model, in order to get rid of any redundant items, e.g. beta(Q), S_eff(Q) 2316 self.communicate.deleteIntermediateTheoryPlotsSignal.emit(self.kernel_module.id) 2270 2317 2271 2318 # Create plots for intermediate product data … … 2282 2329 new_plots.append(sq_data) 2283 2330 2284 if self.data_is_loaded: 2285 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 2286 2331 # Update/generate plots 2287 2332 for plot in new_plots: 2288 if hasattr(plot, "id") and "esidual" in plot.id: 2289 # TODO: fix updates to residuals plot 2290 pass 2291 elif plot is not None: 2292 self.communicate.plotUpdateSignal.emit([plot]) 2333 self.communicate.plotUpdateSignal.emit([plot]) 2293 2334 2294 2335 def complete2D(self, return_data): … … 2308 2349 2309 2350 # Modify fitted_data with weighting 2310 self.addWeightingToData(fitted_data)2311 2312 self.createNewIndex( fitted_data)2351 weighted_data = self.addWeightingToData(fitted_data) 2352 2353 self.createNewIndex(weighted_data) 2313 2354 # Calculate difference between return_data and logic.data 2314 self.chi2 = FittingUtilities.calculateChi2( fitted_data, self.logic.data)2355 self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.logic.data) 2315 2356 # Update the control 2316 2357 chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 2317 2358 self.lblChi2Value.setText(chi2_repr) 2318 2359 2319 # self.communicate.plotUpdateSignal.emit([fitted_data])2320 2321 2360 # Plot residuals if actual data 2322 2361 if not self.data_is_loaded: 2323 2362 return 2324 2363 2325 residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data)2364 residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 2326 2365 residuals_plot.id = "Residual " + residuals_plot.id 2327 2366 self.createNewIndex(residuals_plot) … … 2392 2431 self._poly_model.clear() 2393 2432 2433 parameters = self.model_parameters.form_volume_parameters 2434 if self.is2D: 2435 parameters += self.model_parameters.orientation_parameters 2436 2394 2437 [self.setPolyModelParameters(i, param) for i, param in \ 2395 enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 2438 enumerate(parameters) if param.polydisperse] 2439 2396 2440 FittingUtilities.addPolyHeadersToModel(self._poly_model) 2397 2441 … … 2751 2795 2752 2796 fp.chi2 = self.chi2 2753 fp.parameters_to_fit = self.parameters_to_fit 2797 fp.main_params_to_fit = self.main_params_to_fit 2798 fp.poly_params_to_fit = self.poly_params_to_fit 2799 fp.magnet_params_to_fit = self.magnet_params_to_fit 2754 2800 fp.kernel_module = self.kernel_module 2755 2801 … … 2811 2857 if self.all_data: 2812 2858 index = self.all_data[self.data_index] 2859 else: 2860 index = self.theory_item 2813 2861 report_logic = ReportPageLogic(self, 2814 2862 kernel_module=self.kernel_module,
Note: See TracChangeset
for help on using the changeset viewer.