Changeset d9410c5 in sasview
- Timestamp:
- Sep 6, 2018 3:32:24 PM (6 years ago)
- Branches:
- ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- 0c0491d
- Parents:
- b1f6063 (diff), 66d4370 (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. - Location:
- src/sas
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/MainWindow/DataExplorer.py
r6b50296 rfd7ef36 4 4 import time 5 5 import logging 6 import re7 6 8 7 from PyQt5 import QtCore … … 37 36 # The controller which is responsible for managing signal slots connections 38 37 # for the gui and providing an interface to the data model. 39 40 # This matches the ID of a plot created using FittingLogic._create1DPlot, e.g.41 # "5 [P(Q)] modelname"42 # or43 # "4 modelname".44 # Useful for determining whether the plot in question is for an intermediate result, such as P(Q) or S(Q) in the45 # case of a product model; the identifier for this is held in square brackets, as in the example above.46 theory_plot_ID_pattern = re.compile(r"^([0-9]+)\s+(\[(.*)\]\s+)?(.*)$")47 38 48 39 def __init__(self, parent=None, guimanager=None, manager=None): … … 581 572 else: 582 573 # Don't plot intermediate results, e.g. P(Q), S(Q) 583 match = self.theory_plot_ID_pattern.match(plot_id)574 match = GuiUtils.theory_plot_ID_pattern.match(plot_id) 584 575 # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 585 576 if match and match.groups()[1] != None: … … 1290 1281 self.theory_model.appendRow(model_item) 1291 1282 1283 def deleteIntermediateTheoryPlotsByModelID(self, model_id): 1284 """Given a model's ID, deletes all items in the theory item model which reference the same ID. Useful in the 1285 case of intermediate results disappearing when changing calculations (in which case you don't want them to be 1286 retained in the list).""" 1287 items_to_delete = [] 1288 for r in range(self.theory_model.rowCount()): 1289 item = self.theory_model.item(r, 0) 1290 data = item.child(0).data() 1291 if not hasattr(data, "id"): 1292 return 1293 match = GuiUtils.theory_plot_ID_pattern.match(data.id) 1294 if match: 1295 item_model_id = match.groups()[-1] 1296 if item_model_id == model_id: 1297 # Only delete those identified as an intermediate plot 1298 if match.groups()[2] not in (None, ""): 1299 items_to_delete.append(item) 1300 1301 for item in items_to_delete: 1302 self.theory_model.removeRow(item.row()) -
src/sas/qtgui/MainWindow/GuiManager.py
r6b50296 rf84d793 123 123 #self._workspace.workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget) 124 124 self._workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget) 125 self._workspace.resizeDocks([self.dockedFilesWidget], [305], Qt.Horizontal) 125 126 126 127 # Add the console window as another docked widget … … 395 396 self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged) 396 397 self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 398 self.communicate.deleteIntermediateTheoryPlotsSignal.connect(self.deleteIntermediateTheoryPlotsByModelID) 397 399 self.communicate.plotRequestedSignal.connect(self.showPlot) 398 400 self.communicate.plotFromFilenameSignal.connect(self.showPlotFromFilename) … … 532 534 """ 533 535 self.communicate.copyFitParamsSignal.emit("") 536 self._workspace.actionPaste.setEnabled(True) 534 537 pass 535 538 … … 885 888 """ 886 889 self.filesWidget.updateTheoryFromPerspective(index) 890 891 def deleteIntermediateTheoryPlotsByModelID(self, model_id): 892 """ 893 Catch the signal to delete items in the Theory item model which correspond to a model ID. 894 Send the request to the DataExplorer for updating the theory model. 895 """ 896 self.filesWidget.deleteIntermediateTheoryPlotsByModelID(model_id) 887 897 888 898 def updateModelFromDataOperationPanel(self, new_item, new_datalist_item): … … 952 962 self._workspace.menubar.addAction(self._workspace.menuWindow.menuAction()) 953 963 self._workspace.menubar.addAction(self._workspace.menuHelp.menuAction()) 964 954 965 elif isinstance(perspective, Perspectives.PERSPECTIVES["Invariant"]): 955 966 self.checkAnalysisOption(self._workspace.actionInvariant) -
src/sas/qtgui/MainWindow/UI/MainWindowUI.ui
r6b50296 rdda8f16 254 254 </action> 255 255 <action name="actionPaste"> 256 <property name="enabled"> 257 <bool>false</bool> 258 </property> 256 259 <property name="icon"> 257 260 <iconset> -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
rf6c19cf rb764ae5 457 457 """ 458 458 weight = None 459 if data is None: 460 return [] 459 461 if is2d: 462 if not hasattr(data, 'err_data'): 463 return [] 460 464 dy_data = data.err_data 461 465 data = data.data 462 466 else: 467 if not hasattr(data, 'dy'): 468 return [] 463 469 dy_data = data.dy 464 470 data = data.y -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r5aad7a5 r66d4370 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): … … 249 247 # copy of current kernel model 250 248 self.kernel_module_copy = None 249 250 # dictionaries of current params 251 self.poly_params = {} 252 self.magnet_params = {} 251 253 252 254 # Page id for fitting … … 528 530 # Signals from separate tabs asking for replot 529 531 self.options_widget.plot_signal.connect(self.onOptionsUpdate) 530 self.options_widget.plot_signal.connect(self.onOptionsUpdate)531 532 532 533 # Signals from other widgets … … 964 965 if not model: 965 966 return 966 # Reset structure factor967 self.cbStructureFactor.setCurrentIndex(0)968 967 969 968 # Reset parameters to fit … … 972 971 self.has_poly_error_column = False 973 972 974 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) 975 977 976 978 def onSelectBatchFilename(self, data_index): … … 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) … … 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): … … 1969 1972 # Allow the SF combobox visibility for the given sasmodel 1970 1973 self.enableStructureFactorControl(structure_factor) 1974 if self.cbStructureFactor.isEnabled(): 1975 structure_factor = self.cbStructureFactor.currentText() 1976 self.fromStructureFactorToQModel(structure_factor) 1971 1977 1972 1978 # Then, add multishells … … 1976 1982 1977 1983 # Add polydispersity to the model 1984 self.poly_params = {} 1978 1985 self.setPolyModel() 1979 1986 # Add magnetic parameters to the model 1987 self.magnet_params = {} 1980 1988 self.setMagneticModel() 1981 1989 … … 2063 2071 Setting model parameters into QStandardItemModel based on selected _structure factor_ 2064 2072 """ 2073 if structure_factor is None or structure_factor=="None": 2074 return 2065 2075 structure_module = generate.load_kernel_module(structure_factor) 2066 2076 structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) … … 2237 2247 return self.completed1D if isinstance(self.data, Data1D) else self.completed2D 2238 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 2239 2266 def calculateQGridForModelExt(self, data=None, model=None, completefn=None, use_threads=True): 2240 2267 """ … … 2244 2271 data = self.data 2245 2272 if model is None: 2246 model = self.kernel_module 2273 model = copy.deepcopy(self.kernel_module) 2274 self.updateKernelModelWithExtraParams(model) 2275 2247 2276 if completefn is None: 2248 2277 completefn = self.methodCompleteForData() 2249 2278 smearer = self.smearing_widget.smearer() 2279 weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 2280 2250 2281 # Awful API to a backend method. 2251 2282 calc_thread = self.methodCalculateForData()(data=data, … … 2256 2287 smearer=smearer, 2257 2288 state=None, 2258 weight= None,2289 weight=weight, 2259 2290 fid=None, 2260 2291 toggle_mode_on=False, … … 2308 2339 new_plots.append(residuals) 2309 2340 2341 if self.data_is_loaded: 2342 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 2310 2347 # Create plots for intermediate product data 2311 2348 pq_data, sq_data = self.logic.new1DProductPlots(return_data, self.tab_id) … … 2321 2358 new_plots.append(sq_data) 2322 2359 2323 if self.data_is_loaded:2324 GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots)2325 2326 2360 # Update/generate plots 2327 2361 for plot in new_plots: … … 2333 2367 """ 2334 2368 fitted_data = self.logic.new2DPlot(return_data) 2335 self.calculateResiduals(fitted_data)2369 residuals = self.calculateResiduals(fitted_data) 2336 2370 self.model_data = fitted_data 2371 new_plots = [fitted_data] 2372 if residuals is not None: 2373 new_plots.append(residuals) 2374 2375 # Update/generate plots 2376 for plot in new_plots: 2377 self.communicate.plotUpdateSignal.emit([plot]) 2337 2378 2338 2379 def calculateResiduals(self, fitted_data): … … 2344 2385 2345 2386 # Modify fitted_data with weighting 2346 self.addWeightingToData(fitted_data)2347 2348 self.createNewIndex( fitted_data)2387 weighted_data = self.addWeightingToData(fitted_data) 2388 2389 self.createNewIndex(weighted_data) 2349 2390 # Calculate difference between return_data and logic.data 2350 self.chi2 = FittingUtilities.calculateChi2( fitted_data, self.logic.data)2391 self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.logic.data) 2351 2392 # Update the control 2352 2393 chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 2353 2394 self.lblChi2Value.setText(chi2_repr) 2354 2395 2355 # self.communicate.plotUpdateSignal.emit([fitted_data])2356 2357 2396 # Plot residuals if actual data 2358 2397 if not self.data_is_loaded: 2359 2398 return 2360 2399 2361 residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data)2400 residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 2362 2401 residuals_plot.id = "Residual " + residuals_plot.id 2363 2402 self.createNewIndex(residuals_plot) … … 2467 2506 _, min, max = self.kernel_module.details[param_name] 2468 2507 2508 # Update local param dict 2509 self.poly_params[param_name + '.width'] = width 2510 self.poly_params[param_name + '.npts'] = npts 2511 self.poly_params[param_name + '.nsigmas'] = nsigs 2512 2469 2513 # Construct a row with polydisp. related variable. 2470 2514 # This will get added to the polydisp. model … … 2641 2685 param.units] 2642 2686 2687 self.magnet_params[param.name] = param.default 2688 2643 2689 FittingUtilities.addCheckedListToModel(model, checked_list) 2644 2690 … … 2816 2862 2817 2863 # TODO: add polidyspersity and magnetism 2818 2819 2864 2820 2865 def updateUndo(self): … … 2979 3024 # first - regular params 2980 3025 param_list = [] 3026 3027 param_list.append(['model_name', str(self.cbModel.currentText())]) 2981 3028 def gatherParams(row): 2982 3029 """ … … 3065 3112 if lines[0] != 'sasview_parameter_values': 3066 3113 return False 3067 for line in lines[1:-1]: 3114 3115 model = lines[1].split(',') 3116 3117 if model[0] != 'model_name': 3118 return False 3119 3120 context['model_name'] = [model[1]] 3121 for line in lines[2:-1]: 3068 3122 if len(line) != 0: 3069 3123 item = line.split(',') … … 3091 3145 except IndexError: 3092 3146 pass 3147 3148 if str(self.cbModel.currentText()) != str(context['model_name'][0]): 3149 msg = QtWidgets.QMessageBox() 3150 msg.setIcon(QtWidgets.QMessageBox.Information) 3151 msg.setText("The model in the clipboard is not the same as the currently loaded model. \ 3152 Not all parameters saved may paste correctly.") 3153 msg.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) 3154 result = msg.exec_() 3155 if result == QtWidgets.QMessageBox.Ok: 3156 pass 3157 else: 3158 return 3093 3159 3094 3160 self.updateFullModel(context) … … 3129 3195 param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 3130 3196 self._model_model.item(row, 3+ioffset).setText(param_repr) 3197 self.setFocus() 3198 3131 3199 3132 3200 # block signals temporarily, so we don't end up … … 3135 3203 self.iterateOverModel(updateFittedValues) 3136 3204 self._model_model.blockSignals(False) 3205 3137 3206 3138 3207 def updateFullPolyModel(self, param_dict): … … 3179 3248 param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 3180 3249 self._poly_model.item(row, 5+ioffset).setText(param_repr) 3250 self.setFocus() 3181 3251 3182 3252 # block signals temporarily, so we don't end up … … 3186 3256 self._poly_model.blockSignals(False) 3187 3257 3188 -
src/sas/qtgui/Perspectives/Fitting/ModelThread.py
r3ae9179 r2df558e 117 117 self.source) 118 118 else: 119 self.complete (image=output,120 data=self.data,121 page_id=self.page_id,122 model=self.model,123 s tate=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,119 self.completefn((output, 120 self.data, 121 self.page_id, 122 self.model, 123 self.state, 124 self.toggle_mode_on, 125 elapsed, 126 index_model, 127 self.fid, 128 self.qmin, 129 self.qmax, 130 self.weight, 131 131 #qstep=self.qstep, 132 update_chisqr=self.update_chisqr,133 s ource=self.source)132 self.update_chisqr, 133 self.source)) 134 134 135 135 … … 250 250 pq_values, sq_values) 251 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) 252 self.completefn((self.data.x[index], output[index], 253 self.page_id, 254 self.state, 255 self.weight, 256 self.fid, 257 self.toggle_mode_on, 258 elapsed, index, self.model, 259 self.data, 260 self.update_chisqr, 261 self.source, 262 unsmeared_output, unsmeared_data, unsmeared_error, 263 pq_values, sq_values)) 267 264 268 265 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
r6dbff18 r66d4370 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 … … 637 650 self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 638 651 639 self.widget.show()640 641 652 # Set data 642 653 test_data = Data1D(x=[1,2], y=[1,2]) 643 654 item = QtGui.QStandardItem() 655 updateModelItem(item, test_data, "test") 644 656 # Force same data into logic 645 self.widget.logic.data = test_data 646 self.widget.data_is_loaded = True 657 self.widget.data = item 647 658 648 659 # Change the category index so we have a model available … … 690 701 self.widget.close() 691 702 703 def testOnEmptyFit2(self): 692 704 test_data = Data2D(image=[1.0, 2.0, 3.0], 693 705 err_image=[0.01, 0.02, 0.03], … … 700 712 item = QtGui.QStandardItem() 701 713 updateModelItem(item, test_data, "test") 714 702 715 # Force same data into logic 703 716 self.widget.data = item … … 717 730 self.widget.close() 718 731 719 720 def testOnFit1D(self): 732 def notestOnFit1D(self): 721 733 """ 722 734 Test the threaded fitting call … … 756 768 self.widget.close() 757 769 758 def testOnFit2D(self):770 def notestOnFit2D(self): 759 771 """ 760 772 Test the threaded fitting call … … 851 863 # Set data 852 864 test_data = Data1D(x=[1,2], y=[1,2]) 853 865 item = QtGui.QStandardItem() 866 updateModelItem(item, test_data, "test") 854 867 # Force same data into logic 855 self.widget.logic.data = test_data 856 self.widget.data_is_loaded = True 868 self.widget.data = item 869 870 # Force same data into logic 857 871 category_index = self.widget.cbCategory.findText('Sphere') 872 858 873 self.widget.cbCategory.setCurrentIndex(category_index) 859 874 self.widget.main_params_to_fit = ['scale'] … … 937 952 # Set data 938 953 test_data = Data1D(x=[1,2], y=[1,2]) 939 954 item = QtGui.QStandardItem() 955 updateModelItem(item, test_data, "test") 940 956 # Force same data into logic 941 self.widget.logic.data = test_data 942 self.widget.data_is_loaded = True 957 self.widget.data = item 943 958 category_index = self.widget.cbCategory.findText("Sphere") 944 959 self.widget.cbCategory.setCurrentIndex(category_index) … … 962 977 # Set data 963 978 test_data = Data1D(x=[1,2], y=[1,2]) 964 979 item = QtGui.QStandardItem() 980 updateModelItem(item, test_data, "test") 965 981 # Force same data into logic 966 self.widget.logic.data = test_data 967 self.widget.data_is_loaded = True 982 self.widget.data = item 968 983 category_index = self.widget.cbCategory.findText("Sphere") 969 984 -
src/sas/qtgui/Plotting/Plotter.py
rae43f3b rb764ae5 195 195 ax.set_xlabel(self.x_label) 196 196 197 # define the ranges198 #self.setRange = SetGraphRange(parent=self,199 # x_range=self.ax.get_xlim(), y_range=self.ax.get_ylim())200 201 197 # refresh canvas 202 198 self.canvas.draw_idle() 199 # This is an important processEvent. 200 # This allows charts to be properly updated in order 201 # of plots being applied. 202 QtWidgets.QApplication.processEvents() 203 203 204 204 def createContextMenu(self): -
src/sas/qtgui/Utilities/GuiUtils.py
r9463ca2 r6da3e3d 35 35 HELP_DIRECTORY_LOCATION = "docs/sphinx-docs/build/html" 36 36 IMAGES_DIRECTORY_LOCATION = HELP_DIRECTORY_LOCATION + "/_images" 37 38 # This matches the ID of a plot created using FittingLogic._create1DPlot, e.g. 39 # "5 [P(Q)] modelname" 40 # or 41 # "4 modelname". 42 # Useful for determining whether the plot in question is for an intermediate result, such as P(Q) or S(Q) in the 43 # case of a product model; the identifier for this is held in square brackets, as in the example above. 44 theory_plot_ID_pattern = re.compile(r"^([0-9]+)\s+(\[(.*)\]\s+)?(.*)$") 37 45 38 46 def get_app_dir(): … … 212 220 updateTheoryFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem) 213 221 222 # Request to delete plots (in the theory view) related to a given model ID 223 deleteIntermediateTheoryPlotsSignal = QtCore.pyqtSignal(str) 224 214 225 # New plot requested from the GUI manager 215 226 # Old "NewPlotEvent" … … 260 271 # Fitting parameter paste from clipboard 261 272 pasteFitParamsSignal = QtCore.pyqtSignal() 273 262 274 # Notify about new categories/models from category manager 263 275 updateModelCategoriesSignal = QtCore.pyqtSignal() -
src/sas/qtgui/Utilities/LocalConfig.py
re4335ae rb764ae5 134 134 135 135 # Default threading model 136 USING_TWISTED = True136 USING_TWISTED = False 137 137 138 138 # Time out for updating sasview -
src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py
r3c6ecd9 rb1f6063 309 309 and not self.isCalculating) 310 310 self.removeButton.setEnabled(self.logic.data_is_loaded) 311 self.explorerButton.setEnabled(self.logic.data_is_loaded 312 and np.all(self.logic.data.dy != 0)) 311 self.explorerButton.setEnabled(self.logic.data_is_loaded) 313 312 self.stopButton.setVisible(self.isCalculating) 314 313 self.regConstantSuggestionButton.setEnabled( … … 641 640 self.calcThread.ready(2.5) 642 641 642 #Perform estimate should be done on value enter this should solve delay problem 643 self.performEstimate() 644 643 645 def stopCalcThread(self): 644 646 """ Stops a thread if it exists and is running """ -
src/sas/sascalc/pr/invertor.py
rb8080e1 r6701a0b 71 71 A[j][i] = (Fourier transformed base function for point j) 72 72 73 We the mchoose a number of r-points, n_r, to evaluate the second73 We then choose a number of r-points, n_r, to evaluate the second 74 74 derivative of P(r) at. This is used as our regularization term. 75 75 For a vector r of length n_r, the following n_r rows are set to :: … … 144 144 x, y, err, d_max, q_min, q_max and alpha 145 145 """ 146 if 146 if name == 'x': 147 147 if 0.0 in value: 148 148 msg = "Invertor: one of your q-values is zero. " … … 227 227 return None 228 228 229 def add_errors(self, yvalues): 230 """ 231 Adds errors to data set is they are not avaialble 232 :return: 233 """ 234 stats_errors = np.zeros(len(yvalues)) 235 for i in range(len(yvalues)): 236 # Scale the error so that we can fit over several decades of Q 237 scale = 0.05 * np.sqrt(yvalues[i]) 238 min_err = 0.01 * yvalues[i] 239 stats_errors[i] = scale * np.sqrt(np.fabs(yvalues[i])) + min_err 240 logger.warning("Simulated errors have been added to the data set\n") 241 return stats_errors 242 229 243 def clone(self): 230 244 """ … … 244 258 invertor.x = self.x 245 259 invertor.y = self.y 246 invertor.err = self.err 260 if np.size(self.err) == 0 or np.all(self.err) == 0: 261 invertor.err = self.add_errors(self.y) 262 else: 263 invertor.err = self.err 247 264 invertor.est_bck = self.est_bck 248 265 invertor.background = self.background … … 268 285 A[i][j] = (Fourier transformed base function for point j) 269 286 270 We the mchoose a number of r-points, n_r, to evaluate the second287 We then choose a number of r-points, n_r, to evaluate the second 271 288 derivative of P(r) at. This is used as our regularization term. 272 289 For a vector r of length n_r, the following n_r rows are set to ::
Note: See TracChangeset
for help on using the changeset viewer.