Changeset 9ba91b7 in sasview


Ignore:
Timestamp:
Sep 7, 2018 10:11:37 AM (6 years ago)
Author:
ibressler
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:
254199c
Parents:
d6c4987 (diff), fb560d2 (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:
Ingo Breßler <dev@…> (09/07/18 10:09:21)
git-committer:
Ingo Breßler <dev@…> (09/07/18 10:11:37)
Message:

Merge branch 'ESS_GUI' into ESS_GUI_iss1033

  • fixed the conflicts introduced by dcabba7b in ESS_GUI
Location:
src/sas/qtgui
Files:
7 edited

Legend:

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

    rfd7ef36 r60d55a7  
    560560        # Now query the model item for available plots 
    561561        plots = GuiUtils.plotsFromFilename(filename, model) 
    562         ids_keys = list(self.active_plots.keys()) 
    563         ids_vals = [val.data.id for val in self.active_plots.values()] 
    564562 
    565563        new_plots = [] 
    566564        for item, plot in plots.items(): 
    567             plot_id = plot.id 
    568             if plot_id in ids_keys: 
    569                 self.active_plots[plot_id].replacePlot(plot_id, plot) 
    570             elif plot_id in ids_vals: 
    571                 list(self.active_plots.values())[ids_vals.index(plot_id)].replacePlot(plot_id, plot) 
    572             else: 
     565            if not self.updatePlot(plot): 
    573566                # Don't plot intermediate results, e.g. P(Q), S(Q) 
    574                 match = GuiUtils.theory_plot_ID_pattern.match(plot_id) 
     567                match = GuiUtils.theory_plot_ID_pattern.match(plot.id) 
    575568                # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 
    576569                if match and match.groups()[1] != None: 
     
    706699                self.active_plots[plot_set.id] = old_plot 
    707700 
    708     def updatePlot(self, new_data): 
    709         """ 
    710         Modify existing plot for immediate response 
    711         """ 
    712         data = new_data[0] 
     701    def updatePlot(self, data): 
     702        """ 
     703        Modify existing plot for immediate response and returns True. 
     704        Returns false, if the plot does not exist already. 
     705        """ 
     706        try: # there might be a list or a single value being passed 
     707            data = data[0] 
     708        except TypeError: 
     709            pass 
    713710        assert type(data).__name__ in ['Data1D', 'Data2D'] 
    714711 
     
    719716        if data_id in ids_keys: 
    720717            self.active_plots[data_id].replacePlot(data_id, data) 
     718            return True 
    721719        elif data_id in ids_vals: 
    722720            list(self.active_plots.values())[ids_vals.index(data_id)].replacePlot(data_id, data) 
     721            return True 
     722        return False 
    723723 
    724724    def chooseFiles(self): 
  • src/sas/qtgui/Perspectives/Fitting/FittingLogic.py

    r40975f8 r9ba91b7  
    161161        Create a new 1D data instance based on fitting results 
    162162        """ 
    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         intermediate_results = return_data 
    170  
    171         return self._create1DPlot(tab_id, x, y, model, data) 
     163        return self._create1DPlot(tab_id, return_data['x'], return_data['y'], 
     164                                  return_data['model'], return_data['data']) 
    172165 
    173166    def new2DPlot(self, return_data): 
     
    175168        Create a new 2D data instance based on fitting results 
    176169        """ 
    177         image, data, page_id, model, state, toggle_mode_on,\ 
    178         elapsed, index, fid, qmin, qmax, weight, \ 
    179         update_chisqr, source = return_data 
     170        image = return_data['image'] 
     171        data = return_data['data'] 
     172        model = return_data['model'] 
    180173 
    181174        np.nan_to_num(image) 
     
    183176        new_plot.name = model.name + '2d' 
    184177        new_plot.title = "Analytical model 2D " 
    185         new_plot.id = str(page_id) + " " + data.name 
    186         new_plot.group_id = str(page_id) + " Model2D" 
     178        new_plot.id = str(return_data['page_id']) + " " + data.name 
     179        new_plot.group_id = str(return_data['page_id']) + " Model2D" 
    187180        new_plot.detector = data.detector 
    188181        new_plot.source = data.source 
     
    218211        (pq_plot, sq_plot). If either are unavailable, the corresponding plot is None. 
    219212        """ 
    220         # Unpack return data from Calc1D 
    221         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         intermediate_results = return_data 
    227  
    228213        plots = [] 
    229         for name, result in intermediate_results.items(): 
    230             plots.append(self._create1DPlot(tab_id, x, result, model, data, component=name)) 
     214        for name, result in return_data['intermediate_results'].items(): 
     215            plots.append(self._create1DPlot(tab_id, return_data['x'], result, 
     216                         return_data['model'], return_data['data'], 
     217                         component=name)) 
    231218        return plots 
    232219 
  • src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py

    rb764ae5 r4ea8020  
    124124    return item 
    125125 
    126 def addSimpleParametersToModel(parameters, is2D): 
     126def addSimpleParametersToModel(parameters, is2D, parameters_original=None): 
    127127    """ 
    128128    Update local ModelModel with sasmodel parameters 
     129    parameters_original: list of parameters before any tagging on their IDs, e.g. for product model 
     130    (so that those are the display names; see below) 
    129131    """ 
    130132    if is2D: 
     
    132134    else: 
    133135        params = parameters.iq_parameters 
     136 
     137    if parameters_original: 
     138        # 'parameters_original' contains the parameters as they are to be DISPLAYED, while 'parameters' 
     139        # contains the parameters as they were renamed; this is for handling name collisions in product model. 
     140        # The 'real name' of the parameter will be stored in the item's user data. 
     141        if is2D: 
     142            params_orig = [p for p in parameters_original.kernel_parameters if p.type != 'magnetic'] 
     143        else: 
     144            params_orig = parameters_original.iq_parameters 
     145    else: 
     146        # no difference in names anyway 
     147        params_orig = params 
     148 
    134149    item = [] 
    135     for param in params: 
     150    for param, param_orig in zip(params, params_orig): 
    136151        # Create the top level, checkable item 
    137         item_name = param.name 
     152        item_name = param_orig.name 
    138153        item1 = QtGui.QStandardItem(item_name) 
     154        item1.setData(param.name, QtCore.Qt.UserRole) 
    139155        item1.setCheckable(True) 
    140156        item1.setEditable(False) 
     
    144160        item4 = QtGui.QStandardItem(str(param.limits[0])) 
    145161        item5 = QtGui.QStandardItem(str(param.limits[1])) 
    146         item6 = QtGui.QStandardItem(param.units) 
     162        item6 = QtGui.QStandardItem(str(param.units)) 
    147163        item6.setEditable(False) 
    148164        item.append([item1, item2, item4, item5, item6]) 
     
    182198    model.appendRow(item_list) 
    183199 
     200def addHeadingRowToModel(model, name): 
     201    """adds a non-interactive top-level row to the model""" 
     202    header_row = [QtGui.QStandardItem() for i in range(5)] 
     203    header_row[0].setText(name) 
     204 
     205    font = header_row[0].font() 
     206    font.setBold(True) 
     207    header_row[0].setFont(font) 
     208 
     209    for item in header_row: 
     210        item.setEditable(False) 
     211        item.setCheckable(False) 
     212        item.setSelectable(False) 
     213 
     214    model.appendRow(header_row) 
     215 
    184216def addHeadersToModel(model): 
    185217    """ 
     
    227259    model.header_tooltips = copy.copy(poly_header_error_tooltips) 
    228260 
    229 def addShellsToModel(parameters, model, index): 
    230     """ 
    231     Find out multishell parameters and update the model with the requested number of them 
     261def addShellsToModel(parameters, model, index, row_num=None): 
     262    """ 
     263    Find out multishell parameters and update the model with the requested number of them. 
     264    Inserts them after the row at row_num, if not None; otherwise, appends to end. 
     265    Returns a list of lists of QStandardItem objects. 
    232266    """ 
    233267    multishell_parameters = getIterParams(parameters) 
    234268 
     269    rows = [] 
    235270    for i in range(index): 
    236271        for par in multishell_parameters: 
     
    259294            item4 = QtGui.QStandardItem(str(par.limits[1])) 
    260295            item5 = QtGui.QStandardItem(par.units) 
    261             model.appendRow([item1, item2, item3, item4, item5]) 
     296            row = [item1, item2, item3, item4, item5] 
     297            rows.append(row) 
     298 
     299            if row_num is None: 
     300                model.appendRow(row) 
     301            else: 
     302                model.insertRow(row_num, row) 
     303                row_num += 1 
     304 
     305    return rows 
    262306 
    263307def calculateChi2(reference_data, current_data): 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r40975f8 r9ba91b7  
    9191    fittingFinishedSignal = QtCore.pyqtSignal(tuple) 
    9292    batchFittingFinishedSignal = QtCore.pyqtSignal(tuple) 
    93     Calc1DFinishedSignal = QtCore.pyqtSignal(tuple) 
    94     Calc2DFinishedSignal = QtCore.pyqtSignal(tuple) 
     93    Calc1DFinishedSignal = QtCore.pyqtSignal(dict) 
     94    Calc2DFinishedSignal = QtCore.pyqtSignal(dict) 
    9595 
    9696    def __init__(self, parent=None, data=None, tab_id=1): 
     
    219219        # Utility variable to enable unselectable option in category combobox 
    220220        self._previous_category_index = 0 
    221         # Utility variable for multishell display 
    222         self._last_model_row = 0 
     221        # Utility variables for multishell display 
     222        self._n_shells_row = 0 
     223        self._num_shell_params = 0 
    223224        # Dictionary of {model name: model class} for the current category 
    224225        self.models = {} 
     
    676677        Return list of all parameters for the current model 
    677678        """ 
    678         return [self._model_model.item(row).text() for row in range(self._model_model.rowCount())] 
     679        return [self._model_model.item(row).text() 
     680                for row in range(self._model_model.rowCount()) 
     681                if self.isCheckable(row)] 
    679682 
    680683    def modifyViewOnRow(self, row, font=None, brush=None): 
     
    704707        assert isinstance(constraint, Constraint) 
    705708        assert 0 <= row <= self._model_model.rowCount() 
     709        assert self.isCheckable(row) 
    706710 
    707711        item = QtGui.QStandardItem() 
     
    724728        max_col = self.lstParams.itemDelegate().param_max 
    725729        for row in self.selectedParameters(): 
     730            assert(self.isCheckable(row)) 
    726731            param = self._model_model.item(row, 0).text() 
    727732            value = self._model_model.item(row, 1).text() 
     
    766771        max_col = self.lstParams.itemDelegate().param_max 
    767772        for row in range(self._model_model.rowCount()): 
     773            if not self.isCheckable(row): 
     774                continue 
    768775            if not self.rowHasConstraint(row): 
    769776                continue 
     
    794801        For the given row, return its constraint, if any 
    795802        """ 
    796         try: 
     803        if self.isCheckable(row): 
    797804            item = self._model_model.item(row, 1) 
    798             return item.child(0).data() 
    799         except AttributeError: 
    800             # return none when no constraints 
    801             return None 
     805            try: 
     806                return item.child(0).data() 
     807            except AttributeError: 
     808                # return none when no constraints 
     809                pass 
     810        return None 
    802811 
    803812    def rowHasConstraint(self, row): 
     
    805814        Finds out if row of the main model has a constraint child 
    806815        """ 
    807         item = self._model_model.item(row, 1) 
    808         if item.hasChildren(): 
    809             c = item.child(0).data() 
    810             if isinstance(c, Constraint): 
    811                 return True 
     816        if self.isCheckable(row): 
     817            item = self._model_model.item(row, 1) 
     818            if item.hasChildren(): 
     819                c = item.child(0).data() 
     820                if isinstance(c, Constraint): 
     821                    return True 
    812822        return False 
    813823 
     
    816826        Finds out if row of the main model has an active constraint child 
    817827        """ 
    818         item = self._model_model.item(row, 1) 
    819         if item.hasChildren(): 
    820             c = item.child(0).data() 
    821             if isinstance(c, Constraint) and c.active: 
    822                 return True 
     828        if self.isCheckable(row): 
     829            item = self._model_model.item(row, 1) 
     830            if item.hasChildren(): 
     831                c = item.child(0).data() 
     832                if isinstance(c, Constraint) and c.active: 
     833                    return True 
    823834        return False 
    824835 
     
    827838        Finds out if row of the main model has an active, nontrivial constraint child 
    828839        """ 
    829         item = self._model_model.item(row, 1) 
    830         if item.hasChildren(): 
    831             c = item.child(0).data() 
    832             if isinstance(c, Constraint) and c.func and c.active: 
    833                 return True 
     840        if self.isCheckable(row): 
     841            item = self._model_model.item(row, 1) 
     842            if item.hasChildren(): 
     843                c = item.child(0).data() 
     844                if isinstance(c, Constraint) and c.func and c.active: 
     845                    return True 
    834846        return False 
    835847 
     
    11971209            self.updateData() 
    11981210 
     1211        # update in param model 
     1212        if model_column in [delegate.poly_pd, delegate.poly_error, delegate.poly_min, delegate.poly_max]: 
     1213            row = self.getRowFromName(parameter_name) 
     1214            param_item = self._model_model.item(row) 
     1215            self._model_model.blockSignals(True) 
     1216            param_item.child(0).child(0, model_column).setText(item.text()) 
     1217            self._model_model.blockSignals(False) 
     1218 
    11991219    def onMagnetModelChange(self, item): 
    12001220        """ 
     
    15691589            # internal so can use closure for param_dict 
    15701590            param_name = str(self._model_model.item(row, 0).text()) 
    1571             if param_name not in list(param_dict.keys()): 
     1591            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15721592                return 
    15731593            # modify the param value 
     
    15811601            # Utility function for updateof polydispersity part of the main model 
    15821602            param_name = str(self._model_model.item(row, 0).text())+'.width' 
    1583             if param_name not in list(param_dict.keys()): 
     1603            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15841604                return 
    15851605            # modify the param value 
     
    19581978        # Crete/overwrite model items 
    19591979        self._model_model.clear() 
    1960  
    1961         # First, add parameters from the main model 
    1962         if model_name is not None: 
     1980        self._poly_model.clear() 
     1981        self._magnet_model.clear() 
     1982 
     1983        if model_name is None: 
     1984            if structure_factor not in (None, "None"): 
     1985                # S(Q) on its own, treat the same as a form factor 
     1986                self.kernel_module = None 
     1987                self.fromStructureFactorToQModel(structure_factor) 
     1988            else: 
     1989                # No models selected 
     1990                return 
     1991        else: 
    19631992            self.fromModelToQModel(model_name) 
    1964  
    1965         # Then, add structure factor derived parameters 
    1966         if structure_factor is not None and structure_factor != "None": 
    1967             if model_name is None: 
    1968                 # Instantiate the current sasmodel for SF-only models 
    1969                 self.kernel_module = self.models[structure_factor]() 
    1970             self.fromStructureFactorToQModel(structure_factor) 
    1971         else: 
     1993            self.addExtraShells() 
     1994 
    19721995            # Allow the SF combobox visibility for the given sasmodel 
    19731996            self.enableStructureFactorControl(structure_factor) 
     1997         
     1998            # Add S(Q) 
    19741999            if self.cbStructureFactor.isEnabled(): 
    19752000                structure_factor = self.cbStructureFactor.currentText() 
    19762001                self.fromStructureFactorToQModel(structure_factor) 
    19772002 
    1978         # Then, add multishells 
    1979         if model_name is not None: 
    1980             # Multishell models need additional treatment 
    1981             self.addExtraShells() 
    1982  
    1983         # Add polydispersity to the model 
    1984         self.poly_params = {} 
    1985         self.setPolyModel() 
    1986         # Add magnetic parameters to the model 
    1987         self.magnet_params = {} 
    1988         self.setMagneticModel() 
     2003            # Add polydispersity to the model 
     2004            self.poly_params = {} 
     2005            self.setPolyModel() 
     2006            # Add magnetic parameters to the model 
     2007            self.magnet_params = {} 
     2008            self.setMagneticModel() 
    19892009 
    19902010        # Adjust the table cells width 
     
    20592079        self.shell_names = self.shellNamesList() 
    20602080 
    2061         # Update the QModel 
     2081        # Get new rows for QModel 
    20622082        new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 
    20632083 
     2084        # Add heading row 
     2085        FittingUtilities.addHeadingRowToModel(self._model_model, model_name) 
     2086 
     2087        # Update QModel 
    20642088        for row in new_rows: 
    20652089            self._model_model.appendRow(row) 
    2066         # Update the counter used for multishell display 
    2067         self._last_model_row = self._model_model.rowCount() 
    20682090 
    20692091    def fromStructureFactorToQModel(self, structure_factor): 
     
    20732095        if structure_factor is None or structure_factor=="None": 
    20742096            return 
    2075         structure_module = generate.load_kernel_module(structure_factor) 
    2076         structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) 
    2077  
    2078         structure_kernel = self.models[structure_factor]() 
    2079         form_kernel = self.kernel_module 
    2080  
    2081         self.kernel_module = MultiplicationModel(form_kernel, structure_kernel) 
    2082  
    2083         new_rows = FittingUtilities.addSimpleParametersToModel(structure_parameters, self.is2D) 
     2097 
     2098        s_kernel = self.models[structure_factor]() 
     2099        p_kernel = self.kernel_module 
     2100 
     2101        if p_kernel is None: 
     2102            # Not a product model, just S(Q) 
     2103            self.kernel_module = s_kernel 
     2104            params = modelinfo.ParameterTable(self.kernel_module._model_info.parameters.kernel_parameters) 
     2105            new_rows = FittingUtilities.addSimpleParametersToModel(params, self.is2D) 
     2106        else: 
     2107            p_pars_len = len(p_kernel._model_info.parameters.kernel_parameters) 
     2108            s_pars_len = len(s_kernel._model_info.parameters.kernel_parameters) 
     2109 
     2110            self.kernel_module = MultiplicationModel(p_kernel, s_kernel) 
     2111            all_params = self.kernel_module._model_info.parameters.kernel_parameters 
     2112            all_param_names = [param.name for param in all_params] 
     2113 
     2114            # S(Q) params from the product model are not necessarily the same as those from the S(Q) model; any 
     2115            # conflicting names with P(Q) params will cause a rename; we also lose radius_effective (for now...) 
     2116 
     2117            # TODO: merge rest of beta approx implementation in 
     2118            # This is to ensure compatibility when we merge beta approx support in...! 
     2119 
     2120            # radius_effective is always s_params[0] 
     2121 
     2122            # if radius_effective_mode is in all_params, then all_params contains radius_effective and we want to 
     2123            # keep it in the model 
     2124 
     2125            # if radius_effective_mode is NOT in all_params, then radius_effective should NOT be kept, because the user 
     2126            # cannot specify it themselves; but, make sure we only remove it if it's actually there in the first place 
     2127            # (sasmodels master removes it already) 
     2128            if "radius_effective_mode" in all_param_names: 
     2129                # Show all parameters 
     2130                s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len]) 
     2131                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters) 
     2132            else: 
     2133                # Ensure radius_effective is not displayed 
     2134                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters[1:]) 
     2135                if "radius_effective" in all_param_names: 
     2136                    s_params = modelinfo.ParameterTable(all_params[p_pars_len+1:p_pars_len+s_pars_len]) 
     2137                else: 
     2138                    s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len-1]) 
     2139 
     2140            # Get new rows for QModel 
     2141            # Any renamed parameters are stored as data in the relevant item, for later handling 
     2142            new_rows = FittingUtilities.addSimpleParametersToModel(s_params, self.is2D, s_params_orig) 
     2143 
     2144            # TODO: merge rest of beta approx implementation in 
     2145            # These parameters are not part of P(Q) nor S(Q), but are added only to the product model (e.g. specifying 
     2146            # structure factor calculation mode) 
     2147            # product_params = all_params[p_pars_len+s_pars_len:] 
     2148 
     2149        # Add heading row 
     2150        FittingUtilities.addHeadingRowToModel(self._model_model, structure_factor) 
     2151 
     2152        # Update QModel 
    20842153        for row in new_rows: 
    20852154            self._model_model.appendRow(row) 
    20862155            # disable fitting of parameters not listed in self.kernel_module (probably radius_effective) 
    2087             if row[0].text() not in self.kernel_module.params.keys(): 
    2088                 row_num = self._model_model.rowCount() - 1 
    2089                 FittingUtilities.markParameterDisabled(self._model_model, row_num) 
    2090  
    2091         # Update the counter used for multishell display 
    2092         self._last_model_row = self._model_model.rowCount() 
     2156            # if row[0].text() not in self.kernel_module.params.keys(): 
     2157            #     row_num = self._model_model.rowCount() - 1 
     2158            #     FittingUtilities.markParameterDisabled(self._model_model, row_num) 
    20932159 
    20942160    def haveParamsToFit(self): 
     
    21162182        model_row = item.row() 
    21172183        name_index = self._model_model.index(model_row, 0) 
     2184        name_item = self._model_model.itemFromIndex(name_index) 
    21182185 
    21192186        # Extract changed value. 
     
    21242191            return 
    21252192 
    2126         parameter_name = str(self._model_model.data(name_index)) # sld, background etc. 
     2193        # if the item has user data, this is the actual parameter name (e.g. to handle duplicate names) 
     2194        if name_item.data(QtCore.Qt.UserRole): 
     2195            parameter_name = str(name_item.data(QtCore.Qt.UserRole)) 
     2196        else: 
     2197            parameter_name = str(self._model_model.data(name_index)) 
    21272198 
    21282199        # Update the parameter value - note: this supports +/-inf as well 
     
    23522423            new_plots.append(plot) 
    23532424 
    2354         # Update/generate plots 
    23552425        for plot in new_plots: 
    23562426            self.communicate.plotUpdateSignal.emit([plot]) 
     
    25522622        def updateFunctionCaption(row): 
    25532623            # Utility function for update of polydispersity function name in the main model 
     2624            if not self.isCheckable(row): 
     2625                return 
     2626            self._model_model.blockSignals(True) 
    25542627            param_name = str(self._model_model.item(row, 0).text()) 
     2628            self._model_model.blockSignals(False) 
    25552629            if param_name !=  param.name: 
    25562630                return 
    25572631            # Modify the param value 
     2632            self._model_model.blockSignals(True) 
    25582633            if self.has_error_column: 
    25592634                # err column changes the indexing 
     
    25612636            else: 
    25622637                self._model_model.item(row, 0).child(0).child(0,4).setText(combo_string) 
     2638            self._model_model.blockSignals(False) 
    25632639 
    25642640        if combo_string == 'array': 
     
    27202796 
    27212797        self.lstParams.setIndexWidget(shell_index, func) 
    2722         self._last_model_row = self._model_model.rowCount() 
     2798        self._n_shells_row = shell_row - 1 
    27232799 
    27242800        # Set the index to the state-kept value 
     
    27312807        """ 
    27322808        # Find row location of the combobox 
    2733         last_row = self._last_model_row 
    2734         remove_rows = self._model_model.rowCount() - last_row 
     2809        first_row = self._n_shells_row + 1 
     2810        remove_rows = self._num_shell_params 
    27352811 
    27362812        if remove_rows > 1: 
    2737             self._model_model.removeRows(last_row, remove_rows) 
    2738  
    2739         FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index) 
     2813            self._model_model.removeRows(first_row, remove_rows) 
     2814 
     2815        new_rows = FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index, first_row) 
     2816        self._num_shell_params = len(new_rows) 
     2817 
    27402818        self.current_shell_displayed = index 
    27412819 
  • src/sas/qtgui/Perspectives/Fitting/ModelThread.py

    r40975f8 r9ba91b7  
    101101        elapsed = time.time() - self.starttime 
    102102 
     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 
    103111        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.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                            #qstep=self.qstep, 
    132                            self.update_chisqr, 
    133                            self.source)) 
    134  
     112            return res 
     113        else: 
     114            self.completefn(res) 
    135115 
    136116class Calc1D(CalcThread): 
     
    249229        elapsed = time.time() - self.starttime 
    250230 
     231        res = dict(x = self.data.x[index], y = output[index], 
     232            page_id = self.page_id, state = self.state, weight = self.weight, 
     233            fid = self.fid, toggle_mode_on = self.toggle_mode_on, 
     234            elapsed = elapsed, index = index, model = self.model, 
     235            data = self.data, update_chisqr = self.update_chisqr, 
     236            source = self.source, unsmeared_output = unsmeared_output, 
     237            unsmeared_data = unsmeared_data, unsmeared_error = unsmeared_error, 
     238            intermediate_results = results_eval) 
     239 
    251240        if LocalConfig.USING_TWISTED: 
    252             return (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                     results_eval) 
    264         else: 
    265             self.completefn((self.data.x[index], output[index], 
    266                         self.page_id, 
    267                         self.state, 
    268                         self.weight, 
    269                         self.fid, 
    270                         self.toggle_mode_on, 
    271                         elapsed, index, self.model, 
    272                         self.data, 
    273                         self.update_chisqr, 
    274                         self.source, 
    275                         unsmeared_output, unsmeared_data, unsmeared_error, 
    276                         results_eval)) 
     241            return res 
     242        else: 
     243            self.completefn(res) 
    277244 
    278245    def results(self): 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py

    r66d4370 r4ea8020  
    256256        self.widget.cbStructureFactor.setCurrentIndex(structure_index) 
    257257 
    258         # We have 4 more rows now 
     258        # We have 3 more param rows now (radius_effective is removed), and a new heading 
    259259        self.assertEqual(self.widget._model_model.rowCount(), rowcount+4) 
    260260 
     
    276276        last_index = self.widget.cbStructureFactor.count() 
    277277        self.widget.cbStructureFactor.setCurrentIndex(last_index-1) 
    278         # Do we have all the rows? 
    279         self.assertEqual(self.widget._model_model.rowCount(), 4) 
     278        # Do we have all the rows (incl. radius_effective & heading row)? 
     279        self.assertEqual(self.widget._model_model.rowCount(), 5) 
    280280 
    281281        # Are the command buttons properly enabled? 
     
    509509        Test opening of the load file dialog for 'array' polydisp. function 
    510510        """ 
     511 
     512        # open a non-existent file 
    511513        filename = os.path.join("UnitTesting", "testdata_noexist.txt") 
     514        with self.assertRaises(OSError, msg="testdata_noexist.txt should be a non-existent file"): 
     515            os.stat(filename) 
    512516        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=(filename,'')) 
    513517        self.widget.show() 
     
    525529 
    526530        # good file 
     531        # TODO: this depends on the working directory being src/sas/qtgui, 
     532        # TODO: which isn't convenient if you want to run this test suite 
     533        # TODO: individually 
    527534        filename = os.path.join("UnitTesting", "testdata.txt") 
     535        try: 
     536            os.stat(filename) 
     537        except OSError: 
     538            self.assertTrue(False, "testdata.txt does not exist") 
    528539        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=(filename,'')) 
    529540 
     
    591602 
    592603        # Assure we have the combobox available 
    593         last_row = self.widget._last_model_row 
    594         func_index = self.widget._model_model.index(last_row-1, 1) 
     604        cbox_row = self.widget._n_shells_row 
     605        func_index = self.widget._model_model.index(cbox_row, 1) 
    595606        self.assertIsInstance(self.widget.lstParams.indexWidget(func_index), QtWidgets.QComboBox) 
     607 
     608        # get number of rows before changing shell count 
     609        last_row = self.widget._model_model.rowCount() 
    596610 
    597611        # Change the combo box index 
     
    10271041 
    10281042         # Check the model 
    1029         self.assertEqual(self.widget._model_model.rowCount(), 6) 
     1043        self.assertEqual(self.widget._model_model.rowCount(), 7) 
    10301044        self.assertEqual(self.widget._model_model.columnCount(), 5) 
    10311045 
     
    11431157        # two rows selected 
    11441158        index1 = self.widget.lstParams.model().index(1, 0, QtCore.QModelIndex()) 
    1145         index2 = self.widget.lstParams.model().index(2, 0, QtCore.QModelIndex()) 
     1159        index2 = self.widget.lstParams.model().index(3, 0, QtCore.QModelIndex()) 
    11461160        selection_model = self.widget.lstParams.selectionModel() 
    11471161        selection_model.select(index1, selection_model.Select | selection_model.Rows) 
     
    11791193        # several random parameters 
    11801194        self.assertEqual(self.widget.getRowFromName('scale'), 0) 
    1181         self.assertEqual(self.widget.getRowFromName('length'), 5) 
     1195        self.assertEqual(self.widget.getRowFromName('length'), 6) 
    11821196 
    11831197    def testGetParamNames(self): 
     
    12161230        # Create a constraint object 
    12171231        const = Constraint(parent=None, value=7.0) 
    1218         row = 2 
     1232        row = 3 
    12191233 
    12201234        spy = QtSignalSpy(self.widget, self.widget.constraintAddedSignal) 
     
    12351249        # assign complex constraint now 
    12361250        const = Constraint(parent=None, param='radius', func='5*sld') 
    1237         row = 4 
     1251        row = 5 
    12381252        # call the method tested 
    12391253        self.widget.addConstraintToRow(constraint=const, row=row) 
     
    12941308        self.widget.cbModel.setCurrentIndex(model_index) 
    12951309 
     1310        row1 = 1 
     1311        row2 = 5 
     1312 
     1313        param1 = "background" 
     1314        param2 = "radius" 
     1315 
     1316        #default_value1 = "0.001" 
     1317        default_value2 = "20" 
     1318 
    12961319        # select two rows 
    1297         row1 = 1 
    1298         row2 = 4 
    12991320        index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 
    13001321        index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) 
     
    13131334 
    13141335        # delete one of the constraints 
    1315         self.widget.deleteConstraintOnParameter(param='background') 
     1336        self.widget.deleteConstraintOnParameter(param=param1) 
    13161337 
    13171338        # see that the other constraint is still present 
    1318         cons = self.widget.getConstraintForRow(4) # 4 = radius 
    1319         self.assertEqual(cons.param, "radius") 
    1320         self.assertEqual(cons.value, "20") 
     1339        cons = self.widget.getConstraintForRow(row2) 
     1340        self.assertEqual(cons.param, param2) 
     1341        self.assertEqual(cons.value, default_value2) 
    13211342 
    13221343        # kill the other constraint 
     
    13241345 
    13251346        # see that the other constraint is still present 
    1326         self.assertEqual(self.widget.getConstraintsForModel(), [('radius', None)]) 
     1347        self.assertEqual(self.widget.getConstraintsForModel(), [(param2, None)]) 
    13271348 
    13281349    def testGetConstraintForRow(self): 
     
    13441365        self.widget.cbModel.setCurrentIndex(model_index) 
    13451366 
     1367        row1 = 1 
     1368        row2 = 5 
     1369 
    13461370        # select two rows 
    1347         row1 = 1 
    1348         row2 = 4 
    13491371        index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 
    13501372        index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) 
     
    13561378        self.widget.addSimpleConstraint() 
    13571379 
    1358         con_list = [False, True, False, False, True, False] 
     1380        con_list = [False, True, False, False, False, True, False] 
    13591381        new_list = [] 
    13601382        for row in range(self.widget._model_model.rowCount()): 
     
    13741396        self.widget.cbModel.setCurrentIndex(model_index) 
    13751397 
     1398        row1 = 1 
     1399        row2 = 5 
     1400 
    13761401        # select two rows 
    1377         row1 = 1 
    1378         row2 = 4 
    13791402        index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 
    13801403        index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) 
     
    13901413        constraint_objects[0].active = False 
    13911414 
    1392         con_list = [False, False, False, False, True, False] 
     1415        con_list = [False, False, False, False, False, True, False] 
    13931416        new_list = [] 
    13941417        for row in range(self.widget._model_model.rowCount()): 
     
    14111434        self.assertEqual(self.widget.getConstraintsForModel(),[]) 
    14121435 
     1436        row1 = 1 
     1437        row2 = 5 
     1438 
     1439        param1 = "background" 
     1440        param2 = "radius" 
     1441 
     1442        default_value1 = "0.001" 
     1443        default_value2 = "20" 
     1444 
    14131445        # select two rows 
    1414         row1 = 1 
    1415         row2 = 4 
    14161446        index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 
    14171447        index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) 
     
    14251455        # simple constraints 
    14261456        # self.assertEqual(self.widget.getConstraintsForModel(), [('background', '0.001'), ('radius', '20')]) 
    1427         cons = self.widget.getConstraintForRow(1) # 1 - background 
    1428         self.assertEqual(cons.param, "background") 
    1429         self.assertEqual(cons.value, "0.001") 
    1430         cons = self.widget.getConstraintForRow(4) # 4 = radius 
    1431         self.assertEqual(cons.param, "radius") 
    1432         self.assertEqual(cons.value, "20") 
     1457        cons = self.widget.getConstraintForRow(row1) 
     1458        self.assertEqual(cons.param, param1) 
     1459        self.assertEqual(cons.value, default_value1) 
     1460        cons = self.widget.getConstraintForRow(row2) 
     1461        self.assertEqual(cons.param, param2) 
     1462        self.assertEqual(cons.value, default_value2) 
    14331463 
    14341464        objects = self.widget.getConstraintObjectsForModel() 
    14351465        self.assertEqual(len(objects), 2) 
    1436         self.assertEqual(objects[1].value, '20') 
    1437         self.assertEqual(objects[0].param, 'background') 
     1466        self.assertEqual(objects[1].value, default_value2) 
     1467        self.assertEqual(objects[0].param, param1) 
     1468 
     1469        row = 0 
     1470        param = "scale" 
     1471        func = "5*sld" 
    14381472 
    14391473        # add complex constraint 
    1440         const = Constraint(parent=None, param='scale', func='5*sld') 
    1441         row = 0 
     1474        const = Constraint(parent=None, param=param, func=func) 
    14421475        self.widget.addConstraintToRow(constraint=const, row=row) 
    14431476        #self.assertEqual(self.widget.getConstraintsForModel(),[('scale', '5*sld'), ('background', '0.001'), ('radius', None)]) 
    1444         cons = self.widget.getConstraintForRow(4) # 4 = radius 
    1445         self.assertEqual(cons.param, "radius") 
    1446         self.assertEqual(cons.value, "20") 
     1477        cons = self.widget.getConstraintForRow(row2) 
     1478        self.assertEqual(cons.param, param2) 
     1479        self.assertEqual(cons.value, default_value2) 
    14471480 
    14481481        objects = self.widget.getConstraintObjectsForModel() 
    14491482        self.assertEqual(len(objects), 3) 
    1450         self.assertEqual(objects[0].func, '5*sld') 
     1483        self.assertEqual(objects[0].func, func) 
    14511484 
    14521485    def testReplaceConstraintName(self): 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingLogicTest.py

    re752ab8 rd6c4987  
    103103                       data, False, None, 
    104104                       None, None, None, 
    105                        None, None) 
     105                       None) 
    106106 
    107107        new_plot = self.logic.new1DPlot(return_data=return_data, tab_id=0) 
Note: See TracChangeset for help on using the changeset viewer.