Changeset 4ea8020 in sasview for src/sas/qtgui/Perspectives/Fitting
- Timestamp:
- Sep 7, 2018 9:40:56 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:
- c0de493
- Parents:
- 0109f2a (diff), dcabba7 (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. - git-author:
- Torin Cooper-Bennun <40573959+tcbennun@…> (09/07/18 09:40:56)
- git-committer:
- GitHub <noreply@…> (09/07/18 09:40:56)
- Location:
- src/sas/qtgui/Perspectives/Fitting
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Fitting/FittingLogic.py
rb4d05bd rdcabba7 161 161 Create a new 1D data instance based on fitting results 162 162 """ 163 # Unpack return data from Calc1D 164 x, y, page_id, state, weight,\ 165 fid, toggle_mode_on, \ 166 elapsed, index, model, \ 167 data, update_chisqr, source, \ 168 unsmeared_output, unsmeared_data, unsmeared_error, \ 169 pq_values, sq_values = return_data 170 171 return self._create1DPlot(tab_id, x, y, model, data) 163 164 return self._create1DPlot(tab_id, return_data['x'], return_data['y'], 165 return_data['model'], return_data['data']) 172 166 173 167 def new2DPlot(self, return_data): … … 175 169 Create a new 2D data instance based on fitting results 176 170 """ 177 image , data, page_id, model, state, toggle_mode_on,\178 elapsed, index, fid, qmin, qmax, weight, \179 update_chisqr, source = return_data171 image = return_data['image'] 172 data = return_data['data'] 173 model = return_data['model'] 180 174 181 175 np.nan_to_num(image) … … 183 177 new_plot.name = model.name + '2d' 184 178 new_plot.title = "Analytical model 2D " 185 new_plot.id = str( page_id) + " " + data.name186 new_plot.group_id = str( page_id) + " Model2D"179 new_plot.id = str(return_data['page_id']) + " " + data.name 180 new_plot.group_id = str(return_data['page_id']) + " Model2D" 187 181 new_plot.detector = data.detector 188 182 new_plot.source = data.source … … 218 212 (pq_plot, sq_plot). If either are unavailable, the corresponding plot is None. 219 213 """ 220 # Unpack return data from Calc1D221 x, y, page_id, state, weight, \222 fid, toggle_mode_on, \223 elapsed, index, model, \224 data, update_chisqr, source, \225 unsmeared_output, unsmeared_data, unsmeared_error, \226 pq_values, sq_values = return_data227 214 228 215 pq_plot = None 229 216 sq_plot = None 230 217 231 if pq_values is not None: 232 pq_plot = self._create1DPlot(tab_id, x, pq_values, model, data, component="P(Q)") 233 if sq_values is not None: 234 sq_plot = self._create1DPlot(tab_id, x, sq_values, model, data, component="S(Q)") 218 if return_data.get('pq_values', None) is not None: 219 pq_plot = self._create1DPlot(tab_id, return_data['x'], 220 return_data['pq_values'], return_data['model'], 221 return_data['data'], component="P(Q)") 222 if return_data.get('sq_values', None) is not None: 223 sq_plot = self._create1DPlot(tab_id, return_data['x'], 224 return_data['sq_values'], return_data['model'], 225 return_data['data'], component="S(Q)") 235 226 236 227 return pq_plot, sq_plot -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
r70f4458 r4ea8020 474 474 475 475 theory_name = str(current_data.name.split()[0]) 476 res iduals.name = "Residuals for " + str(theory_name) + "[" + \477 str(reference_data.filename)+ "]"476 res_name = reference_data.filename if reference_data.filename else reference_data.name 477 residuals.name = "Residuals for " + str(theory_name) + "[" + res_name + "]" 478 478 residuals.title = residuals.name 479 479 residuals.ytransform = 'y' … … 501 501 """ 502 502 weight = None 503 if data is None: 504 return [] 503 505 if is2d: 506 if not hasattr(data, 'err_data'): 507 return [] 504 508 dy_data = data.err_data 505 509 data = data.data 506 510 else: 511 if not hasattr(data, 'dy'): 512 return [] 507 513 dy_data = data.dy 508 514 data = data.y -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r0109f2a r4ea8020 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): … … 93 91 fittingFinishedSignal = QtCore.pyqtSignal(tuple) 94 92 batchFittingFinishedSignal = QtCore.pyqtSignal(tuple) 95 Calc1DFinishedSignal = QtCore.pyqtSignal( tuple)96 Calc2DFinishedSignal = QtCore.pyqtSignal( tuple)93 Calc1DFinishedSignal = QtCore.pyqtSignal(dict) 94 Calc2DFinishedSignal = QtCore.pyqtSignal(dict) 97 95 98 96 def __init__(self, parent=None, data=None, tab_id=1): … … 251 249 self.kernel_module_copy = None 252 250 251 # dictionaries of current params 252 self.poly_params = {} 253 self.magnet_params = {} 254 253 255 # Page id for fitting 254 256 # To keep with previous SasView values, use 200 as the start offset … … 267 269 self.has_poly_error_column = False 268 270 self.has_magnet_error_column = False 271 272 # If the widget generated theory item, save it 273 self.theory_item = None 269 274 270 275 # signal communicator … … 390 395 # Tag along functionality 391 396 self.label.setText("Data loaded from: ") 392 self.lblFilename.setText(self.logic.data.filename) 397 if self.logic.data.filename: 398 self.lblFilename.setText(self.logic.data.filename) 399 else: 400 self.lblFilename.setText(self.logic.data.name) 393 401 self.updateQRange() 394 402 # Switch off Data2D control … … 522 530 523 531 # Signals from separate tabs asking for replot 524 self.options_widget.plot_signal.connect(self.onOptionsUpdate)525 532 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 526 533 … … 964 971 model = self.cbModel.currentText() 965 972 966 # empty combobox forced to be read 973 # Assure the control is active 974 if not self.cbModel.isEnabled(): 975 return 976 # Empty combobox forced to be read 967 977 if not model: 968 978 return 969 # Reset structure factor970 self.cbStructureFactor.setCurrentIndex(0)971 979 972 980 # Reset parameters to fit … … 975 983 self.has_poly_error_column = False 976 984 977 self.respondToModelStructure(model=model, structure_factor=None) 985 structure = None 986 if self.cbStructureFactor.isEnabled(): 987 structure = str(self.cbStructureFactor.currentText()) 988 self.respondToModelStructure(model=model, structure_factor=structure) 978 989 979 990 def onSelectBatchFilename(self, data_index): … … 1118 1129 self.disableModelCombo() 1119 1130 self.enableStructureCombo() 1131 # set the index to 0 1132 self.cbStructureFactor.setCurrentIndex(0) 1133 self.model_parameters = None 1120 1134 self._model_model.clear() 1121 1135 return … … 1142 1156 model_row = item.row() 1143 1157 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:1158 parameter_name = str(name_index.data()) # "distribution of sld" etc. 1159 if "istribution of" in parameter_name: 1146 1160 # just the last word 1147 1161 parameter_name = parameter_name.rsplit()[-1] … … 1188 1202 # Update the sasmodel 1189 1203 # PD[ratio] -> width, npts -> npts, nsigs -> nsigmas 1190 self.kernel_module.setParam(parameter_name + '.' + delegate.columnDict()[model_column], value) 1204 #self.kernel_module.setParam(parameter_name + '.' + delegate.columnDict()[model_column], value) 1205 key = parameter_name + '.' + delegate.columnDict()[model_column] 1206 self.poly_params[key] = value 1191 1207 1192 1208 # Update plot … … 1197 1213 row = self.getRowFromName(parameter_name) 1198 1214 param_item = self._model_model.item(row) 1215 self._model_model.blockSignals(True) 1199 1216 param_item.child(0).child(0, model_column).setText(item.text()) 1217 self._model_model.blockSignals(False) 1200 1218 1201 1219 def onMagnetModelChange(self, item): … … 1226 1244 # Unparsable field 1227 1245 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: 1246 delegate = self.lstMagnetic.itemDelegate() 1247 1248 if model_column > 1: 1249 if model_column == delegate.mag_min: 1250 pos = 1 1251 elif model_column == delegate.mag_max: 1252 pos = 2 1253 elif model_column == delegate.mag_unit: 1254 pos = 0 1255 else: 1256 raise AttributeError("Wrong column in magnetism table.") 1257 # min/max to be changed in self.kernel_module.details[parameter_name] = ['Ang', 0.0, inf] 1258 self.kernel_module.details[parameter_name][pos] = value 1259 else: 1260 self.magnet_params[parameter_name] = value 1261 #self.kernel_module.setParam(parameter_name) = value 1262 # Force the chart update when actual parameters changed 1239 1263 self.recalculatePlotData() 1240 1264 … … 1497 1521 # Data going in 1498 1522 data = self.logic.data 1499 model = self.kernel_module1523 model = copy.deepcopy(self.kernel_module) 1500 1524 qmin = self.q_range_min 1501 1525 qmax = self.q_range_max 1526 # add polydisperse/magnet parameters if asked 1527 self.updateKernelModelWithExtraParams(model) 1502 1528 1503 1529 params_to_fit = self.main_params_to_fit … … 1509 1535 raise ValueError('Fitting requires at least one parameter to optimize.') 1510 1536 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 1537 # Get the constraints. 1517 1538 constraints = self.getComplexConstraintsForModel() … … 1530 1551 data = GuiUtils.dataFromItem(fit_index) 1531 1552 # Potential weights added directly to data 1532 self.addWeightingToData(data)1553 weighted_data = self.addWeightingToData(data) 1533 1554 try: 1534 fitter_single.set_model(model, fit_id, params_to_fit, data= data,1555 fitter_single.set_model(model, fit_id, params_to_fit, data=weighted_data, 1535 1556 constraints=constraints) 1536 1557 except ValueError as ex: 1537 1558 raise ValueError("Setting model parameters failed with: %s" % ex) 1538 1559 1539 qmin, qmax, _ = self.logic.computeRangeFromData( data)1540 fitter_single.set_data(data= data, id=fit_id, smearer=smearer, qmin=qmin,1560 qmin, qmax, _ = self.logic.computeRangeFromData(weighted_data) 1561 fitter_single.set_data(data=weighted_data, id=fit_id, smearer=smearer, qmin=qmin, 1541 1562 qmax=qmax) 1542 1563 fitter_single.select_problem_for_fit(id=fit_id, value=1) … … 1929 1950 Adds weighting contribution to fitting data 1930 1951 """ 1952 new_data = copy.deepcopy(data) 1931 1953 # Send original data for weighting 1932 1954 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 1933 1955 if self.is2D: 1934 data.err_data = weight1956 new_data.err_data = weight 1935 1957 else: 1936 data.dy = weight 1937 pass 1958 new_data.dy = weight 1959 1960 return new_data 1938 1961 1939 1962 def updateQRange(self): … … 1970 1993 self.addExtraShells() 1971 1994 1972 if structure_factor not in (None, "None"): 1973 # add S(Q) 1995 # Allow the SF combobox visibility for the given sasmodel 1996 self.enableStructureFactorControl(structure_factor) 1997 1998 # Add S(Q) 1999 if self.cbStructureFactor.isEnabled(): 2000 structure_factor = self.cbStructureFactor.currentText() 1974 2001 self.fromStructureFactorToQModel(structure_factor) 1975 else:1976 # enable selection of S(Q)1977 self.enableStructureFactorControl(structure_factor)1978 2002 1979 2003 # Add polydispersity to the model 2004 self.poly_params = {} 1980 2005 self.setPolyModel() 1981 2006 # Add magnetic parameters to the model 2007 self.magnet_params = {} 1982 2008 self.setMagneticModel() 1983 2009 … … 2005 2031 """ 2006 2032 name = model_name 2033 kernel_module = None 2007 2034 if self.cbCategory.currentText() == CATEGORY_CUSTOM: 2008 2035 # custom kernel load requires full path … … 2010 2037 try: 2011 2038 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) 2039 except ModuleNotFoundError as ex: 2040 pass 2041 2042 if kernel_module is None: 2043 # mismatch between "name" attribute and actual filename. 2044 curr_model = self.models[model_name] 2045 name, _ = os.path.splitext(os.path.basename(curr_model.filename)) 2046 try: 2047 kernel_module = generate.load_kernel_module(name) 2048 except ModuleNotFoundError as ex: 2049 logging.error("Can't find the model "+ str(ex)) 2050 return 2017 2051 2018 2052 if hasattr(kernel_module, 'parameters'): … … 2059 2093 Setting model parameters into QStandardItemModel based on selected _structure factor_ 2060 2094 """ 2095 if structure_factor is None or structure_factor=="None": 2096 return 2097 2061 2098 s_kernel = self.models[structure_factor]() 2062 2099 p_kernel = self.kernel_module … … 2257 2294 name = self.nameFromData(fitted_data) 2258 2295 # 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)2296 self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 2297 self.communicate.updateTheoryFromPerspectiveSignal.emit(self.theory_item) 2261 2298 2262 2299 def nameFromData(self, fitted_data): … … 2281 2318 return self.completed1D if isinstance(self.data, Data1D) else self.completed2D 2282 2319 2320 def updateKernelModelWithExtraParams(self, model=None): 2321 """ 2322 Updates kernel model 'model' with extra parameters from 2323 the polydisp and magnetism tab, if the tabs are enabled 2324 """ 2325 if model is None: return 2326 if not hasattr(model, 'setParam'): return 2327 2328 # add polydisperse parameters if asked 2329 if self.chkPolydispersity.isChecked(): 2330 for key, value in self.poly_params.items(): 2331 model.setParam(key, value) 2332 # add magnetic params if asked 2333 if self.chkMagnetism.isChecked(): 2334 for key, value in self.magnet_params.items(): 2335 model.setParam(key, value) 2336 2283 2337 def calculateQGridForModelExt(self, data=None, model=None, completefn=None, use_threads=True): 2284 2338 """ … … 2288 2342 data = self.data 2289 2343 if model is None: 2290 model = self.kernel_module 2344 model = copy.deepcopy(self.kernel_module) 2345 self.updateKernelModelWithExtraParams(model) 2346 2291 2347 if completefn is None: 2292 2348 completefn = self.methodCompleteForData() 2293 2349 smearer = self.smearing_widget.smearer() 2350 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 2351 2294 2352 # Awful API to a backend method. 2295 2353 calc_thread = self.methodCalculateForData()(data=data, … … 2300 2358 smearer=smearer, 2301 2359 state=None, 2302 weight= None,2360 weight=weight, 2303 2361 fid=None, 2304 2362 toggle_mode_on=False, … … 2348 2406 residuals = self.calculateResiduals(fitted_data) 2349 2407 self.model_data = fitted_data 2350 2351 new_plots = [fitted_data, residuals] 2408 new_plots = [fitted_data] 2409 if residuals is not None: 2410 new_plots.append(residuals) 2411 2412 if self.data_is_loaded: 2413 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 2414 else: 2415 # delete theory items for the model, in order to get rid of any redundant items, e.g. beta(Q), S_eff(Q) 2416 self.communicate.deleteIntermediateTheoryPlotsSignal.emit(self.kernel_module.id) 2352 2417 2353 2418 # Create plots for intermediate product data … … 2364 2429 new_plots.append(sq_data) 2365 2430 2366 if self.data_is_loaded:2367 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots)2368 2369 # TODO: merge rest of beta approx implementation in2370 # TODO: refactor2371 # deal with constrained radius_effective2372 # 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 # return2376 # 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 # break2382 2383 2431 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]) 2432 self.communicate.plotUpdateSignal.emit([plot]) 2389 2433 2390 2434 def complete2D(self, return_data): … … 2393 2437 """ 2394 2438 fitted_data = self.logic.new2DPlot(return_data) 2395 self.calculateResiduals(fitted_data)2439 residuals = self.calculateResiduals(fitted_data) 2396 2440 self.model_data = fitted_data 2441 new_plots = [fitted_data] 2442 if residuals is not None: 2443 new_plots.append(residuals) 2444 2445 # Update/generate plots 2446 for plot in new_plots: 2447 self.communicate.plotUpdateSignal.emit([plot]) 2397 2448 2398 2449 def calculateResiduals(self, fitted_data): … … 2404 2455 2405 2456 # Modify fitted_data with weighting 2406 self.addWeightingToData(fitted_data)2407 2408 self.createNewIndex( fitted_data)2457 weighted_data = self.addWeightingToData(fitted_data) 2458 2459 self.createNewIndex(weighted_data) 2409 2460 # Calculate difference between return_data and logic.data 2410 self.chi2 = FittingUtilities.calculateChi2( fitted_data, self.logic.data)2461 self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.logic.data) 2411 2462 # Update the control 2412 2463 chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 2413 2464 self.lblChi2Value.setText(chi2_repr) 2414 2465 2415 # self.communicate.plotUpdateSignal.emit([fitted_data])2416 2417 2466 # Plot residuals if actual data 2418 2467 if not self.data_is_loaded: 2419 2468 return 2420 2469 2421 residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data)2470 residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 2422 2471 residuals_plot.id = "Residual " + residuals_plot.id 2423 2472 self.createNewIndex(residuals_plot) … … 2488 2537 self._poly_model.clear() 2489 2538 2539 parameters = self.model_parameters.form_volume_parameters 2540 if self.is2D: 2541 parameters += self.model_parameters.orientation_parameters 2542 2490 2543 [self.setPolyModelParameters(i, param) for i, param in \ 2491 enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 2544 enumerate(parameters) if param.polydisperse] 2545 2492 2546 FittingUtilities.addPolyHeadersToModel(self._poly_model) 2493 2547 … … 2522 2576 _, min, max = self.kernel_module.details[param_name] 2523 2577 2578 # Update local param dict 2579 self.poly_params[param_name + '.width'] = width 2580 self.poly_params[param_name + '.npts'] = npts 2581 self.poly_params[param_name + '.nsigmas'] = nsigs 2582 2524 2583 # Construct a row with polydisp. related variable. 2525 2584 # This will get added to the polydisp. model … … 2571 2630 if not self.isCheckable(row): 2572 2631 return 2632 self._model_model.blockSignals(True) 2573 2633 param_name = str(self._model_model.item(row, 0).text()) 2634 self._model_model.blockSignals(False) 2574 2635 if param_name != param.name: 2575 2636 return 2576 2637 # Modify the param value 2638 self._model_model.blockSignals(True) 2577 2639 if self.has_error_column: 2578 2640 # err column changes the indexing … … 2580 2642 else: 2581 2643 self._model_model.item(row, 0).child(0).child(0,4).setText(combo_string) 2644 self._model_model.blockSignals(False) 2582 2645 2583 2646 if combo_string == 'array': … … 2698 2761 param.units] 2699 2762 2763 self.magnet_params[param.name] = param.default 2764 2700 2765 FittingUtilities.addCheckedListToModel(model, checked_list) 2701 2766 … … 2876 2941 # TODO: add polidyspersity and magnetism 2877 2942 2878 2879 2943 def updateUndo(self): 2880 2944 """ … … 2913 2977 if self.all_data: 2914 2978 index = self.all_data[self.data_index] 2979 else: 2980 index = self.theory_item 2915 2981 report_logic = ReportPageLogic(self, 2916 2982 kernel_module=self.kernel_module, … … 3036 3102 # first - regular params 3037 3103 param_list = [] 3104 3105 param_list.append(['model_name', str(self.cbModel.currentText())]) 3038 3106 def gatherParams(row): 3039 3107 """ … … 3122 3190 if lines[0] != 'sasview_parameter_values': 3123 3191 return False 3124 for line in lines[1:-1]: 3192 3193 model = lines[1].split(',') 3194 3195 if model[0] != 'model_name': 3196 return False 3197 3198 context['model_name'] = [model[1]] 3199 for line in lines[2:-1]: 3125 3200 if len(line) != 0: 3126 3201 item = line.split(',') … … 3148 3223 except IndexError: 3149 3224 pass 3225 3226 if str(self.cbModel.currentText()) != str(context['model_name'][0]): 3227 msg = QtWidgets.QMessageBox() 3228 msg.setIcon(QtWidgets.QMessageBox.Information) 3229 msg.setText("The model in the clipboard is not the same as the currently loaded model. \ 3230 Not all parameters saved may paste correctly.") 3231 msg.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) 3232 result = msg.exec_() 3233 if result == QtWidgets.QMessageBox.Ok: 3234 pass 3235 else: 3236 return 3150 3237 3151 3238 self.updateFullModel(context) … … 3186 3273 param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 3187 3274 self._model_model.item(row, 3+ioffset).setText(param_repr) 3275 self.setFocus() 3276 3188 3277 3189 3278 # block signals temporarily, so we don't end up … … 3192 3281 self.iterateOverModel(updateFittedValues) 3193 3282 self._model_model.blockSignals(False) 3283 3194 3284 3195 3285 def updateFullPolyModel(self, param_dict): … … 3236 3326 param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 3237 3327 self._poly_model.item(row, 5+ioffset).setText(param_repr) 3328 self.setFocus() 3238 3329 3239 3330 # block signals temporarily, so we don't end up … … 3243 3334 self._poly_model.blockSignals(False) 3244 3335 3245 -
src/sas/qtgui/Perspectives/Fitting/ModelThread.py
r3ae9179 rdcabba7 101 101 elapsed = time.time() - self.starttime 102 102 103 res = dict(image = output, data = self.data, page_id = self.page_id, 104 model = self.model, state = self.state, 105 toggle_mode_on = self.toggle_mode_on, elapsed = elapsed, 106 index = index_model, fid = self.fid, 107 qmin = self.qmin, qmax = self.qmax, 108 weight = self.weight, update_chisqr = self.update_chisqr, 109 source = self.source) 110 103 111 if LocalConfig.USING_TWISTED: 104 return (output, 105 self.data, 106 self.page_id, 107 self.model, 108 self.state, 109 self.toggle_mode_on, 110 elapsed, 111 index_model, 112 self.fid, 113 self.qmin, 114 self.qmax, 115 self.weight, 116 self.update_chisqr, 117 self.source) 118 else: 119 self.complete(image=output, 120 data=self.data, 121 page_id=self.page_id, 122 model=self.model, 123 state=self.state, 124 toggle_mode_on=self.toggle_mode_on, 125 elapsed=elapsed, 126 index=index_model, 127 fid=self.fid, 128 qmin=self.qmin, 129 qmax=self.qmax, 130 weight=self.weight, 131 #qstep=self.qstep, 132 update_chisqr=self.update_chisqr, 133 source=self.source) 134 112 return res 113 else: 114 self.completefn(res) 135 115 136 116 class Calc1D(CalcThread): … … 236 216 elapsed = time.time() - self.starttime 237 217 218 res = dict(x = self.data.x[index], y = output[index], 219 page_id = self.page_id, state = self.state, weight = self.weight, 220 fid = self.fid, toggle_mode_on = self.toggle_mode_on, 221 elapsed = elapsed, index = index, model = self.model, 222 data = self.data, update_chisqr = self.update_chisqr, 223 source = self.source, unsmeared_output = unsmeared_output, 224 unsmeared_data = unsmeared_data, unsmeared_error = unsmeared_error, 225 pq_values = pq_values, sq_values = sq_values) 226 238 227 if LocalConfig.USING_TWISTED: 239 return (self.data.x[index], output[index], 240 self.page_id, 241 self.state, 242 self.weight, 243 self.fid, 244 self.toggle_mode_on, 245 elapsed, index, self.model, 246 self.data, 247 self.update_chisqr, 248 self.source, 249 unsmeared_output, unsmeared_data, unsmeared_error, 250 pq_values, sq_values) 251 else: 252 self.complete(x=self.data.x[index], y=output[index], 253 page_id=self.page_id, 254 state=self.state, 255 weight=self.weight, 256 fid=self.fid, 257 toggle_mode_on=self.toggle_mode_on, 258 elapsed=elapsed, index=index, model=self.model, 259 data=self.data, 260 update_chisqr=self.update_chisqr, 261 source=self.source, 262 unsmeared_model=unsmeared_output, 263 unsmeared_data=unsmeared_data, 264 unsmeared_error=unsmeared_error, 265 pq_model=pq_values, 266 sq_model=sq_values) 228 return res 229 else: 230 self.completefn(res) 267 231 268 232 def results(self): -
src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py
rc0a3b22e rb764ae5 79 79 self.weightingGroup.buttonClicked.connect(self.onWeightingChoice) 80 80 81 self.qmin = QMIN_DEFAULT 82 self.qmax = QMAX_DEFAULT 83 self.npts = NPTS_DEFAULT 84 if self.logic.data_is_loaded: 85 self.qmin, self.qmax, self.npts = self.logic.computeDataRange() 81 86 self.initModel() 82 87 self.initMapper() 83 88 self.model.blockSignals(True) 84 self.updateQRange( QMIN_DEFAULT, QMAX_DEFAULT, NPTS_DEFAULT)85 self.txtMaxRange.setText(str( QMAX_DEFAULT))86 self.txtMinRange.setText(str( QMIN_DEFAULT))87 self.txtNpts.setText(str( NPTS_DEFAULT))88 self.txtNptsFit.setText(str( NPTS_DEFAULT))89 self.updateQRange(self.qmin, self.qmax, self.npts) 90 self.txtMaxRange.setText(str(self.qmax)) 91 self.txtMinRange.setText(str(self.qmin)) 92 self.txtNpts.setText(str(self.npts)) 93 self.txtNptsFit.setText(str(self.npts)) 89 94 self.model.blockSignals(False) 90 95 … … 134 139 Callback for resetting qmin/qmax 135 140 """ 136 self.updateQRange( QMIN_DEFAULT, QMAX_DEFAULT, NPTS_DEFAULT)141 self.updateQRange(self.qmin, self.qmax, self.npts) 137 142 138 143 def onWeightingChoice(self, button): … … 179 184 self.model.item(MODEL.index('MAX_RANGE')).setText(str(q_range_max)) 180 185 self.model.item(MODEL.index('NPTS')).setText(str(npts)) 186 self.qmin, self.qmax, self.npts = q_range_min, q_range_max, npts 181 187 182 188 def state(self): -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
r3fbd77b r4ea8020 18 18 from sas.qtgui.Perspectives.Fitting.FittingWidget import * 19 19 from sas.qtgui.Perspectives.Fitting.Constraint import Constraint 20 20 import sas.qtgui.Utilities.LocalConfig 21 21 from sas.qtgui.UnitTesting.TestUtils import QtSignalSpy 22 from sas.qtgui.Perspectives.Fitting.ModelThread import Calc1D 23 from sas.qtgui.Perspectives.Fitting.ModelThread import Calc2D 22 24 23 25 from sas.qtgui.Plotting.PlotterData import Data1D … … 260 262 self.widget.cbModel.setCurrentIndex(0) 261 263 262 # Observe factor reset to None263 self.assertEqual(self.widget.cbStructureFactor.currentText(), STRUCTURE_DEFAULT)264 # Observe factor doesn't reset to None 265 self.assertEqual(self.widget.cbStructureFactor.currentText(), 'squarewell') 264 266 265 267 # Switch category to structure factor … … 319 321 Check that the fitting 1D data object is ready 320 322 """ 321 # Mock the thread creation 322 threads.deferToThread = MagicMock() 323 # Model for theory 324 self.widget.SASModelToQModel("cylinder") 325 # Call the tested method 326 self.widget.calculateQGridForModel() 327 time.sleep(1) 328 # Test the mock 329 self.assertTrue(threads.deferToThread.called) 330 self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, "compute") 323 324 if LocalConfig.USING_TWISTED: 325 # Mock the thread creation 326 threads.deferToThread = MagicMock() 327 # Model for theory 328 self.widget.SASModelToQModel("cylinder") 329 # Call the tested method 330 self.widget.calculateQGridForModel() 331 time.sleep(1) 332 # Test the mock 333 self.assertTrue(threads.deferToThread.called) 334 self.assertEqual(threads.deferToThread.call_args_list[0][0][0].__name__, "compute") 335 else: 336 Calc2D.queue = MagicMock() 337 # Model for theory 338 self.widget.SASModelToQModel("cylinder") 339 # Call the tested method 340 self.widget.calculateQGridForModel() 341 time.sleep(1) 342 # Test the mock 343 self.assertTrue(Calc2D.queue.called) 331 344 332 345 def testCalculateResiduals(self): … … 417 430 index = self.widget._poly_model.index(0,0) 418 431 419 #self.widget.show()420 #QtWidgets.QApplication(sys.argv).exec_()421 422 432 # Set the checbox 423 433 self.widget._poly_model.item(0,0).setCheckState(2) … … 435 445 self.assertEqual(self.widget.kernel_module.details['radius_bell'][1], 1.0) 436 446 447 #self.widget.show() 448 #QtWidgets.QApplication.exec_() 449 437 450 # Change the number of points 438 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.npts'), 35)451 self.assertEqual(self.widget.poly_params['radius_bell.npts'], 35) 439 452 self.widget._poly_model.item(0,4).setText("22") 440 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.npts'), 22)453 self.assertEqual(self.widget.poly_params['radius_bell.npts'], 22) 441 454 # try something stupid 442 455 self.widget._poly_model.item(0,4).setText("butt") 443 456 # see that this didn't annoy the control at all 444 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.npts'), 22)457 self.assertEqual(self.widget.poly_params['radius_bell.npts'], 22) 445 458 446 459 # Change the number of sigmas 447 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.nsigmas'), 3)460 self.assertEqual(self.widget.poly_params['radius_bell.nsigmas'], 3) 448 461 self.widget._poly_model.item(0,5).setText("222") 449 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.nsigmas'), 222)462 self.assertEqual(self.widget.poly_params['radius_bell.nsigmas'], 222) 450 463 # try something stupid again 451 464 self.widget._poly_model.item(0,4).setText("beer") 452 465 # no efect 453 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.nsigmas'), 222)466 self.assertEqual(self.widget.poly_params['radius_bell.nsigmas'], 222) 454 467 455 468 def testOnPolyComboIndexChange(self): … … 472 485 self.widget.onPolyComboIndexChange('rectangle', 0) 473 486 # check values 474 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.npts'), 35)475 self.assertAlmostEqual(self.widget. kernel_module.getParam('radius_bell.nsigmas'), 1.73205, 5)487 self.assertEqual(self.widget.poly_params['radius_bell.npts'], 35) 488 self.assertAlmostEqual(self.widget.poly_params['radius_bell.nsigmas'], 1.73205, 5) 476 489 # Change the index 477 490 self.widget.onPolyComboIndexChange('lognormal', 0) 478 491 # check values 479 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.npts'), 80)480 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.nsigmas'), 8)492 self.assertEqual(self.widget.poly_params['radius_bell.npts'], 80) 493 self.assertEqual(self.widget.poly_params['radius_bell.nsigmas'], 8) 481 494 # Change the index 482 495 self.widget.onPolyComboIndexChange('schulz', 0) 483 496 # check values 484 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.npts'), 80)485 self.assertEqual(self.widget. kernel_module.getParam('radius_bell.nsigmas'), 8)497 self.assertEqual(self.widget.poly_params['radius_bell.npts'], 80) 498 self.assertEqual(self.widget.poly_params['radius_bell.nsigmas'], 8) 486 499 487 500 # mock up file load … … 651 664 self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 652 665 653 self.widget.show()654 655 666 # Set data 656 667 test_data = Data1D(x=[1,2], y=[1,2]) 657 668 item = QtGui.QStandardItem() 669 updateModelItem(item, test_data, "test") 658 670 # Force same data into logic 659 self.widget.logic.data = test_data 660 self.widget.data_is_loaded = True 671 self.widget.data = item 661 672 662 673 # Change the category index so we have a model available … … 704 715 self.widget.close() 705 716 717 def testOnEmptyFit2(self): 706 718 test_data = Data2D(image=[1.0, 2.0, 3.0], 707 719 err_image=[0.01, 0.02, 0.03], … … 714 726 item = QtGui.QStandardItem() 715 727 updateModelItem(item, test_data, "test") 728 716 729 # Force same data into logic 717 730 self.widget.data = item … … 731 744 self.widget.close() 732 745 733 734 def testOnFit1D(self): 746 def notestOnFit1D(self): 735 747 """ 736 748 Test the threaded fitting call … … 770 782 self.widget.close() 771 783 772 def testOnFit2D(self):784 def notestOnFit2D(self): 773 785 """ 774 786 Test the threaded fitting call … … 865 877 # Set data 866 878 test_data = Data1D(x=[1,2], y=[1,2]) 867 879 item = QtGui.QStandardItem() 880 updateModelItem(item, test_data, "test") 868 881 # Force same data into logic 869 self.widget.logic.data = test_data 870 self.widget.data_is_loaded = True 882 self.widget.data = item 883 884 # Force same data into logic 871 885 category_index = self.widget.cbCategory.findText('Sphere') 886 872 887 self.widget.cbCategory.setCurrentIndex(category_index) 873 888 self.widget.main_params_to_fit = ['scale'] … … 951 966 # Set data 952 967 test_data = Data1D(x=[1,2], y=[1,2]) 953 968 item = QtGui.QStandardItem() 969 updateModelItem(item, test_data, "test") 954 970 # Force same data into logic 955 self.widget.logic.data = test_data 956 self.widget.data_is_loaded = True 971 self.widget.data = item 957 972 category_index = self.widget.cbCategory.findText("Sphere") 958 973 self.widget.cbCategory.setCurrentIndex(category_index) … … 976 991 # Set data 977 992 test_data = Data1D(x=[1,2], y=[1,2]) 978 993 item = QtGui.QStandardItem() 994 updateModelItem(item, test_data, "test") 979 995 # Force same data into logic 980 self.widget.logic.data = test_data 981 self.widget.data_is_loaded = True 996 self.widget.data = item 982 997 category_index = self.widget.cbCategory.findText("Sphere") 983 998
Note: See TracChangeset
for help on using the changeset viewer.