Changeset d9410c5 in sasview for src


Ignore:
Timestamp:
Sep 6, 2018 1:32:24 PM (6 years ago)
Author:
wojciech
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.
Message:

Merge branch 'ESS_GUI' of https://github.com/SasView/sasview into ESS_GUI_Pr_fixes

Location:
src/sas
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/MainWindow/DataExplorer.py

    r6b50296 rfd7ef36  
    44import time 
    55import logging 
    6 import re 
    76 
    87from PyQt5 import QtCore 
     
    3736    # The controller which is responsible for managing signal slots connections 
    3837    # 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     # or 
    43     # "4 modelname". 
    44     # Useful for determining whether the plot in question is for an intermediate result, such as P(Q) or S(Q) in the 
    45     # 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+)?(.*)$") 
    4738 
    4839    def __init__(self, parent=None, guimanager=None, manager=None): 
     
    581572            else: 
    582573                # 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) 
    584575                # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 
    585576                if match and match.groups()[1] != None: 
     
    12901281        self.theory_model.appendRow(model_item) 
    12911282 
     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  
    123123        #self._workspace.workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget) 
    124124        self._workspace.addDockWidget(Qt.LeftDockWidgetArea, self.dockedFilesWidget) 
     125        self._workspace.resizeDocks([self.dockedFilesWidget], [305], Qt.Horizontal) 
    125126 
    126127        # Add the console window as another docked widget 
     
    395396        self.communicate.perspectiveChangedSignal.connect(self.perspectiveChanged) 
    396397        self.communicate.updateTheoryFromPerspectiveSignal.connect(self.updateTheoryFromPerspective) 
     398        self.communicate.deleteIntermediateTheoryPlotsSignal.connect(self.deleteIntermediateTheoryPlotsByModelID) 
    397399        self.communicate.plotRequestedSignal.connect(self.showPlot) 
    398400        self.communicate.plotFromFilenameSignal.connect(self.showPlotFromFilename) 
     
    532534        """ 
    533535        self.communicate.copyFitParamsSignal.emit("") 
     536        self._workspace.actionPaste.setEnabled(True) 
    534537        pass 
    535538 
     
    885888        """ 
    886889        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) 
    887897 
    888898    def updateModelFromDataOperationPanel(self, new_item, new_datalist_item): 
     
    952962            self._workspace.menubar.addAction(self._workspace.menuWindow.menuAction()) 
    953963            self._workspace.menubar.addAction(self._workspace.menuHelp.menuAction()) 
     964 
    954965        elif isinstance(perspective, Perspectives.PERSPECTIVES["Invariant"]): 
    955966            self.checkAnalysisOption(self._workspace.actionInvariant) 
  • src/sas/qtgui/MainWindow/UI/MainWindowUI.ui

    r6b50296 rdda8f16  
    254254  </action> 
    255255  <action name="actionPaste"> 
     256   <property name="enabled"> 
     257    <bool>false</bool> 
     258   </property> 
    256259   <property name="icon"> 
    257260    <iconset> 
  • src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py

    rf6c19cf rb764ae5  
    457457    """ 
    458458    weight = None 
     459    if data is None: 
     460        return [] 
    459461    if is2d: 
     462        if not hasattr(data, 'err_data'): 
     463            return [] 
    460464        dy_data = data.err_data 
    461465        data = data.data 
    462466    else: 
     467        if not hasattr(data, 'dy'): 
     468            return [] 
    463469        dy_data = data.dy 
    464470        data = data.y 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r5aad7a5 r66d4370  
    4949 
    5050 
    51  
    5251TAB_MAGNETISM = 4 
    5352TAB_POLY = 3 
     
    6160 
    6261logger = logging.getLogger(__name__) 
    63  
    6462 
    6563class ToolTippedItemModel(QtGui.QStandardItemModel): 
     
    249247        # copy of current kernel model 
    250248        self.kernel_module_copy = None 
     249 
     250        # dictionaries of current params 
     251        self.poly_params = {} 
     252        self.magnet_params = {} 
    251253 
    252254        # Page id for fitting 
     
    528530        # Signals from separate tabs asking for replot 
    529531        self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
    530         self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
    531532 
    532533        # Signals from other widgets 
     
    964965        if not model: 
    965966            return 
    966         # Reset structure factor 
    967         self.cbStructureFactor.setCurrentIndex(0) 
    968967 
    969968        # Reset parameters to fit 
     
    972971        self.has_poly_error_column = False 
    973972 
    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) 
    975977 
    976978    def onSelectBatchFilename(self, data_index): 
     
    11881190            # Update the sasmodel 
    11891191            # 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 
    11911195 
    11921196            # Update plot 
    11931197            self.updateData() 
    1194  
    1195         # update in param model 
    1196         if model_column in [delegate.poly_pd, delegate.poly_error, delegate.poly_min, delegate.poly_max]: 
    1197             row = self.getRowFromName(parameter_name) 
    1198             param_item = self._model_model.item(row) 
    1199             param_item.child(0).child(0, model_column).setText(item.text()) 
    12001198 
    12011199    def onMagnetModelChange(self, item): 
     
    12261224            # Unparsable field 
    12271225            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 
    12391243            self.recalculatePlotData() 
    12401244 
     
    14971501        # Data going in 
    14981502        data = self.logic.data 
    1499         model = self.kernel_module 
     1503        model = copy.deepcopy(self.kernel_module) 
    15001504        qmin = self.q_range_min 
    15011505        qmax = self.q_range_max 
     1506        # add polydisperse/magnet parameters if asked 
     1507        self.updateKernelModelWithExtraParams(model) 
    15021508 
    15031509        params_to_fit = self.main_params_to_fit 
     
    15091515            raise ValueError('Fitting requires at least one parameter to optimize.') 
    15101516 
    1511         # Potential smearing added 
    1512         # Remember that smearing_min/max can be None -> 
    1513         # deal with it until Python gets discriminated unions 
    1514         self.addWeightingToData(data) 
    1515  
    15161517        # Get the constraints. 
    15171518        constraints = self.getComplexConstraintsForModel() 
     
    15301531            data = GuiUtils.dataFromItem(fit_index) 
    15311532            # Potential weights added directly to data 
    1532             self.addWeightingToData(data) 
     1533            weighted_data = self.addWeightingToData(data) 
    15331534            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, 
    15351536                             constraints=constraints) 
    15361537            except ValueError as ex: 
    15371538                raise ValueError("Setting model parameters failed with: %s" % ex) 
    15381539 
    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, 
    15411542                            qmax=qmax) 
    15421543            fitter_single.select_problem_for_fit(id=fit_id, value=1) 
     
    19291930        Adds weighting contribution to fitting data 
    19301931        """ 
     1932        new_data = copy.deepcopy(data) 
    19311933        # Send original data for weighting 
    19321934        weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
    19331935        if self.is2D: 
    1934             data.err_data = weight 
     1936            new_data.err_data = weight 
    19351937        else: 
    1936             data.dy = weight 
    1937         pass 
     1938            new_data.dy = weight 
     1939 
     1940        return new_data 
    19381941 
    19391942    def updateQRange(self): 
     
    19691972            # Allow the SF combobox visibility for the given sasmodel 
    19701973            self.enableStructureFactorControl(structure_factor) 
     1974            if self.cbStructureFactor.isEnabled(): 
     1975                structure_factor = self.cbStructureFactor.currentText() 
     1976                self.fromStructureFactorToQModel(structure_factor) 
    19711977 
    19721978        # Then, add multishells 
     
    19761982 
    19771983        # Add polydispersity to the model 
     1984        self.poly_params = {} 
    19781985        self.setPolyModel() 
    19791986        # Add magnetic parameters to the model 
     1987        self.magnet_params = {} 
    19801988        self.setMagneticModel() 
    19811989 
     
    20632071        Setting model parameters into QStandardItemModel based on selected _structure factor_ 
    20642072        """ 
     2073        if structure_factor is None or structure_factor=="None": 
     2074            return 
    20652075        structure_module = generate.load_kernel_module(structure_factor) 
    20662076        structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) 
     
    22372247        return self.completed1D if isinstance(self.data, Data1D) else self.completed2D 
    22382248 
     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 
    22392266    def calculateQGridForModelExt(self, data=None, model=None, completefn=None, use_threads=True): 
    22402267        """ 
     
    22442271            data = self.data 
    22452272        if model is None: 
    2246             model = self.kernel_module 
     2273            model = copy.deepcopy(self.kernel_module) 
     2274            self.updateKernelModelWithExtraParams(model) 
     2275 
    22472276        if completefn is None: 
    22482277            completefn = self.methodCompleteForData() 
    22492278        smearer = self.smearing_widget.smearer() 
     2279        weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
     2280 
    22502281        # Awful API to a backend method. 
    22512282        calc_thread = self.methodCalculateForData()(data=data, 
     
    22562287                                               smearer=smearer, 
    22572288                                               state=None, 
    2258                                                weight=None, 
     2289                                               weight=weight, 
    22592290                                               fid=None, 
    22602291                                               toggle_mode_on=False, 
     
    23082339            new_plots.append(residuals) 
    23092340 
     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 
    23102347        # Create plots for intermediate product data 
    23112348        pq_data, sq_data = self.logic.new1DProductPlots(return_data, self.tab_id) 
     
    23212358            new_plots.append(sq_data) 
    23222359 
    2323         if self.data_is_loaded: 
    2324             GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 
    2325  
    23262360        # Update/generate plots 
    23272361        for plot in new_plots: 
     
    23332367        """ 
    23342368        fitted_data = self.logic.new2DPlot(return_data) 
    2335         self.calculateResiduals(fitted_data) 
     2369        residuals = self.calculateResiduals(fitted_data) 
    23362370        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]) 
    23372378 
    23382379    def calculateResiduals(self, fitted_data): 
     
    23442385 
    23452386        # 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) 
    23492390        # 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) 
    23512392        # Update the control 
    23522393        chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 
    23532394        self.lblChi2Value.setText(chi2_repr) 
    23542395 
    2355         # self.communicate.plotUpdateSignal.emit([fitted_data]) 
    2356  
    23572396        # Plot residuals if actual data 
    23582397        if not self.data_is_loaded: 
    23592398            return 
    23602399 
    2361         residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data) 
     2400        residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 
    23622401        residuals_plot.id = "Residual " + residuals_plot.id 
    23632402        self.createNewIndex(residuals_plot) 
     
    24672506        _, min, max = self.kernel_module.details[param_name] 
    24682507 
     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 
    24692513        # Construct a row with polydisp. related variable. 
    24702514        # This will get added to the polydisp. model 
     
    26412685                        param.units] 
    26422686 
     2687        self.magnet_params[param.name] = param.default 
     2688 
    26432689        FittingUtilities.addCheckedListToModel(model, checked_list) 
    26442690 
     
    28162862 
    28172863        # TODO: add polidyspersity and magnetism 
    2818  
    28192864 
    28202865    def updateUndo(self): 
     
    29793024        # first - regular params 
    29803025        param_list = [] 
     3026 
     3027        param_list.append(['model_name', str(self.cbModel.currentText())]) 
    29813028        def gatherParams(row): 
    29823029            """ 
     
    30653112        if lines[0] != 'sasview_parameter_values': 
    30663113            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]: 
    30683122            if len(line) != 0: 
    30693123                item = line.split(',') 
     
    30913145                    except IndexError: 
    30923146                        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 
    30933159 
    30943160        self.updateFullModel(context) 
     
    31293195            param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 
    31303196            self._model_model.item(row, 3+ioffset).setText(param_repr) 
     3197            self.setFocus() 
     3198 
    31313199 
    31323200        # block signals temporarily, so we don't end up 
     
    31353203        self.iterateOverModel(updateFittedValues) 
    31363204        self._model_model.blockSignals(False) 
     3205 
    31373206 
    31383207    def updateFullPolyModel(self, param_dict): 
     
    31793248            param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 
    31803249            self._poly_model.item(row, 5+ioffset).setText(param_repr) 
     3250            self.setFocus() 
    31813251 
    31823252        # block signals temporarily, so we don't end up 
     
    31863256        self._poly_model.blockSignals(False) 
    31873257 
    3188  
  • src/sas/qtgui/Perspectives/Fitting/ModelThread.py

    r3ae9179 r2df558e  
    117117                    self.source) 
    118118        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, 
     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, 
    131131                           #qstep=self.qstep, 
    132                            update_chisqr=self.update_chisqr, 
    133                            source=self.source) 
     132                           self.update_chisqr, 
     133                           self.source)) 
    134134 
    135135 
     
    250250                    pq_values, sq_values) 
    251251        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)) 
    267264 
    268265    def results(self): 
  • src/sas/qtgui/Perspectives/Fitting/OptionsWidget.py

    rc0a3b22e rb764ae5  
    7979        self.weightingGroup.buttonClicked.connect(self.onWeightingChoice) 
    8080 
     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() 
    8186        self.initModel() 
    8287        self.initMapper() 
    8388        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)) 
    8994        self.model.blockSignals(False) 
    9095 
     
    134139        Callback for resetting qmin/qmax 
    135140        """ 
    136         self.updateQRange(QMIN_DEFAULT, QMAX_DEFAULT, NPTS_DEFAULT) 
     141        self.updateQRange(self.qmin, self.qmax, self.npts) 
    137142 
    138143    def onWeightingChoice(self, button): 
     
    179184        self.model.item(MODEL.index('MAX_RANGE')).setText(str(q_range_max)) 
    180185        self.model.item(MODEL.index('NPTS')).setText(str(npts)) 
     186        self.qmin, self.qmax, self.npts = q_range_min, q_range_max, npts 
    181187 
    182188    def state(self): 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py

    r6dbff18 r66d4370  
    1818from sas.qtgui.Perspectives.Fitting.FittingWidget import * 
    1919from sas.qtgui.Perspectives.Fitting.Constraint import Constraint 
    20  
     20import sas.qtgui.Utilities.LocalConfig 
    2121from sas.qtgui.UnitTesting.TestUtils import QtSignalSpy 
     22from sas.qtgui.Perspectives.Fitting.ModelThread import Calc1D 
     23from sas.qtgui.Perspectives.Fitting.ModelThread import Calc2D 
    2224 
    2325from sas.qtgui.Plotting.PlotterData import Data1D 
     
    260262        self.widget.cbModel.setCurrentIndex(0) 
    261263 
    262         # Observe factor reset to None 
    263         self.assertEqual(self.widget.cbStructureFactor.currentText(), STRUCTURE_DEFAULT) 
     264        # Observe factor doesn't reset to None 
     265        self.assertEqual(self.widget.cbStructureFactor.currentText(), 'squarewell') 
    264266 
    265267        # Switch category to structure factor 
     
    319321        Check that the fitting 1D data object is ready 
    320322        """ 
    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) 
    331344 
    332345    def testCalculateResiduals(self): 
     
    417430        index = self.widget._poly_model.index(0,0) 
    418431 
    419         #self.widget.show() 
    420         #QtWidgets.QApplication(sys.argv).exec_() 
    421  
    422432        # Set the checbox 
    423433        self.widget._poly_model.item(0,0).setCheckState(2) 
     
    435445        self.assertEqual(self.widget.kernel_module.details['radius_bell'][1], 1.0) 
    436446 
     447        #self.widget.show() 
     448        #QtWidgets.QApplication.exec_() 
     449 
    437450        # 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) 
    439452        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) 
    441454        # try something stupid 
    442455        self.widget._poly_model.item(0,4).setText("butt") 
    443456        # 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) 
    445458 
    446459        # 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) 
    448461        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) 
    450463        # try something stupid again 
    451464        self.widget._poly_model.item(0,4).setText("beer") 
    452465        # 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) 
    454467 
    455468    def testOnPolyComboIndexChange(self): 
     
    472485        self.widget.onPolyComboIndexChange('rectangle', 0) 
    473486        # 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) 
    476489        # Change the index 
    477490        self.widget.onPolyComboIndexChange('lognormal', 0) 
    478491        # 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) 
    481494        # Change the index 
    482495        self.widget.onPolyComboIndexChange('schulz', 0) 
    483496        # 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) 
    486499 
    487500        # mock up file load 
     
    637650        self.assertEqual(self.widget.cmdPlot.text(), 'Show Plot') 
    638651 
    639         self.widget.show() 
    640  
    641652        # Set data 
    642653        test_data = Data1D(x=[1,2], y=[1,2]) 
    643  
     654        item = QtGui.QStandardItem() 
     655        updateModelItem(item, test_data, "test") 
    644656        # Force same data into logic 
    645         self.widget.logic.data = test_data 
    646         self.widget.data_is_loaded = True 
     657        self.widget.data = item 
    647658 
    648659        # Change the category index so we have a model available 
     
    690701        self.widget.close() 
    691702 
     703    def testOnEmptyFit2(self): 
    692704        test_data = Data2D(image=[1.0, 2.0, 3.0], 
    693705                           err_image=[0.01, 0.02, 0.03], 
     
    700712        item = QtGui.QStandardItem() 
    701713        updateModelItem(item, test_data, "test") 
     714 
    702715        # Force same data into logic 
    703716        self.widget.data = item 
     
    717730        self.widget.close() 
    718731 
    719  
    720     def testOnFit1D(self): 
     732    def notestOnFit1D(self): 
    721733        """ 
    722734        Test the threaded fitting call 
     
    756768        self.widget.close() 
    757769 
    758     def testOnFit2D(self): 
     770    def notestOnFit2D(self): 
    759771        """ 
    760772        Test the threaded fitting call 
     
    851863        # Set data 
    852864        test_data = Data1D(x=[1,2], y=[1,2]) 
    853  
     865        item = QtGui.QStandardItem() 
     866        updateModelItem(item, test_data, "test") 
    854867        # 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 
    857871        category_index = self.widget.cbCategory.findText('Sphere') 
     872 
    858873        self.widget.cbCategory.setCurrentIndex(category_index) 
    859874        self.widget.main_params_to_fit = ['scale'] 
     
    937952        # Set data 
    938953        test_data = Data1D(x=[1,2], y=[1,2]) 
    939  
     954        item = QtGui.QStandardItem() 
     955        updateModelItem(item, test_data, "test") 
    940956        # Force same data into logic 
    941         self.widget.logic.data = test_data 
    942         self.widget.data_is_loaded = True 
     957        self.widget.data = item 
    943958        category_index = self.widget.cbCategory.findText("Sphere") 
    944959        self.widget.cbCategory.setCurrentIndex(category_index) 
     
    962977        # Set data 
    963978        test_data = Data1D(x=[1,2], y=[1,2]) 
    964  
     979        item = QtGui.QStandardItem() 
     980        updateModelItem(item, test_data, "test") 
    965981        # Force same data into logic 
    966         self.widget.logic.data = test_data 
    967         self.widget.data_is_loaded = True 
     982        self.widget.data = item 
    968983        category_index = self.widget.cbCategory.findText("Sphere") 
    969984 
  • src/sas/qtgui/Plotting/Plotter.py

    rae43f3b rb764ae5  
    195195            ax.set_xlabel(self.x_label) 
    196196 
    197         # define the ranges 
    198         #self.setRange = SetGraphRange(parent=self, 
    199         #    x_range=self.ax.get_xlim(), y_range=self.ax.get_ylim()) 
    200  
    201197        # refresh canvas 
    202198        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() 
    203203 
    204204    def createContextMenu(self): 
  • src/sas/qtgui/Utilities/GuiUtils.py

    r9463ca2 r6da3e3d  
    3535        HELP_DIRECTORY_LOCATION = "docs/sphinx-docs/build/html" 
    3636IMAGES_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. 
     44theory_plot_ID_pattern = re.compile(r"^([0-9]+)\s+(\[(.*)\]\s+)?(.*)$") 
    3745 
    3846def get_app_dir(): 
     
    212220    updateTheoryFromPerspectiveSignal = QtCore.pyqtSignal(QtGui.QStandardItem) 
    213221 
     222    # Request to delete plots (in the theory view) related to a given model ID 
     223    deleteIntermediateTheoryPlotsSignal = QtCore.pyqtSignal(str) 
     224 
    214225    # New plot requested from the GUI manager 
    215226    # Old "NewPlotEvent" 
     
    260271    # Fitting parameter paste from clipboard 
    261272    pasteFitParamsSignal = QtCore.pyqtSignal() 
     273 
    262274    # Notify about new categories/models from category manager 
    263275    updateModelCategoriesSignal = QtCore.pyqtSignal() 
  • src/sas/qtgui/Utilities/LocalConfig.py

    re4335ae rb764ae5  
    134134 
    135135# Default threading model 
    136 USING_TWISTED = True 
     136USING_TWISTED = False 
    137137 
    138138# Time out for updating sasview 
  • src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py

    r3c6ecd9 rb1f6063  
    309309                                            and not self.isCalculating) 
    310310        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) 
    313312        self.stopButton.setVisible(self.isCalculating) 
    314313        self.regConstantSuggestionButton.setEnabled( 
     
    641640        self.calcThread.ready(2.5) 
    642641 
     642        #Perform estimate should be done on value enter this should solve delay problem 
     643        self.performEstimate() 
     644 
    643645    def stopCalcThread(self): 
    644646        """ Stops a thread if it exists and is running """ 
  • src/sas/sascalc/pr/invertor.py

    rb8080e1 r6701a0b  
    7171        A[j][i] = (Fourier transformed base function for point j) 
    7272 
    73     We them choose a number of r-points, n_r, to evaluate the second 
     73    We then choose a number of r-points, n_r, to evaluate the second 
    7474    derivative of P(r) at. This is used as our regularization term. 
    7575    For a vector r of length n_r, the following n_r rows are set to :: 
     
    144144        x, y, err, d_max, q_min, q_max and alpha 
    145145        """ 
    146         if   name == 'x': 
     146        if name == 'x': 
    147147            if 0.0 in value: 
    148148                msg = "Invertor: one of your q-values is zero. " 
     
    227227        return None 
    228228 
     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 
    229243    def clone(self): 
    230244        """ 
     
    244258        invertor.x = self.x 
    245259        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 
    247264        invertor.est_bck = self.est_bck 
    248265        invertor.background = self.background 
     
    268285            A[i][j] = (Fourier transformed base function for point j) 
    269286 
    270         We them choose a number of r-points, n_r, to evaluate the second 
     287        We then choose a number of r-points, n_r, to evaluate the second 
    271288        derivative of P(r) at. This is used as our regularization term. 
    272289        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.