Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    rdcabba7 r0109f2a  
    4949 
    5050 
     51 
    5152TAB_MAGNETISM = 4 
    5253TAB_POLY = 3 
     
    6061 
    6162logger = logging.getLogger(__name__) 
     63 
    6264 
    6365class ToolTippedItemModel(QtGui.QStandardItemModel): 
     
    9193    fittingFinishedSignal = QtCore.pyqtSignal(tuple) 
    9294    batchFittingFinishedSignal = QtCore.pyqtSignal(tuple) 
    93     Calc1DFinishedSignal = QtCore.pyqtSignal(dict) 
    94     Calc2DFinishedSignal = QtCore.pyqtSignal(dict) 
     95    Calc1DFinishedSignal = QtCore.pyqtSignal(tuple) 
     96    Calc2DFinishedSignal = QtCore.pyqtSignal(tuple) 
    9597 
    9698    def __init__(self, parent=None, data=None, tab_id=1): 
     
    219221        # Utility variable to enable unselectable option in category combobox 
    220222        self._previous_category_index = 0 
    221         # Utility variable for multishell display 
    222         self._last_model_row = 0 
     223        # Utility variables for multishell display 
     224        self._n_shells_row = 0 
     225        self._num_shell_params = 0 
    223226        # Dictionary of {model name: model class} for the current category 
    224227        self.models = {} 
     
    248251        self.kernel_module_copy = None 
    249252 
    250         # dictionaries of current params 
    251         self.poly_params = {} 
    252         self.magnet_params = {} 
    253  
    254253        # Page id for fitting 
    255254        # To keep with previous SasView values, use 200 as the start offset 
     
    268267        self.has_poly_error_column = False 
    269268        self.has_magnet_error_column = False 
    270  
    271         # If the widget generated theory item, save it 
    272         self.theory_item = None 
    273269 
    274270        # signal communicator 
     
    394390        # Tag along functionality 
    395391        self.label.setText("Data loaded from: ") 
    396         if self.logic.data.filename: 
    397             self.lblFilename.setText(self.logic.data.filename) 
    398         else: 
    399             self.lblFilename.setText(self.logic.data.name) 
     392        self.lblFilename.setText(self.logic.data.filename) 
    400393        self.updateQRange() 
    401394        # Switch off Data2D control 
     
    530523        # Signals from separate tabs asking for replot 
    531524        self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
     525        self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
    532526 
    533527        # Signals from other widgets 
     
    676670        Return list of all parameters for the current model 
    677671        """ 
    678         return [self._model_model.item(row).text() for row in range(self._model_model.rowCount())] 
     672        return [self._model_model.item(row).text() 
     673                for row in range(self._model_model.rowCount()) 
     674                if self.isCheckable(row)] 
    679675 
    680676    def modifyViewOnRow(self, row, font=None, brush=None): 
     
    704700        assert isinstance(constraint, Constraint) 
    705701        assert 0 <= row <= self._model_model.rowCount() 
     702        assert self.isCheckable(row) 
    706703 
    707704        item = QtGui.QStandardItem() 
     
    724721        max_col = self.lstParams.itemDelegate().param_max 
    725722        for row in self.selectedParameters(): 
     723            assert(self.isCheckable(row)) 
    726724            param = self._model_model.item(row, 0).text() 
    727725            value = self._model_model.item(row, 1).text() 
     
    766764        max_col = self.lstParams.itemDelegate().param_max 
    767765        for row in range(self._model_model.rowCount()): 
     766            if not self.isCheckable(row): 
     767                continue 
    768768            if not self.rowHasConstraint(row): 
    769769                continue 
     
    794794        For the given row, return its constraint, if any 
    795795        """ 
    796         try: 
     796        if self.isCheckable(row): 
    797797            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 
     798            try: 
     799                return item.child(0).data() 
     800            except AttributeError: 
     801                # return none when no constraints 
     802                pass 
     803        return None 
    802804 
    803805    def rowHasConstraint(self, row): 
     
    805807        Finds out if row of the main model has a constraint child 
    806808        """ 
    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 
     809        if self.isCheckable(row): 
     810            item = self._model_model.item(row, 1) 
     811            if item.hasChildren(): 
     812                c = item.child(0).data() 
     813                if isinstance(c, Constraint): 
     814                    return True 
    812815        return False 
    813816 
     
    816819        Finds out if row of the main model has an active constraint child 
    817820        """ 
    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 
     821        if self.isCheckable(row): 
     822            item = self._model_model.item(row, 1) 
     823            if item.hasChildren(): 
     824                c = item.child(0).data() 
     825                if isinstance(c, Constraint) and c.active: 
     826                    return True 
    823827        return False 
    824828 
     
    827831        Finds out if row of the main model has an active, nontrivial constraint child 
    828832        """ 
    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 
     833        if self.isCheckable(row): 
     834            item = self._model_model.item(row, 1) 
     835            if item.hasChildren(): 
     836                c = item.child(0).data() 
     837                if isinstance(c, Constraint) and c.func and c.active: 
     838                    return True 
    834839        return False 
    835840 
     
    959964        model = self.cbModel.currentText() 
    960965 
    961         # Assure the control is active 
    962         if not self.cbModel.isEnabled(): 
    963             return 
    964         # Empty combobox forced to be read 
     966        # empty combobox forced to be read 
    965967        if not model: 
    966968            return 
     969        # Reset structure factor 
     970        self.cbStructureFactor.setCurrentIndex(0) 
    967971 
    968972        # Reset parameters to fit 
     
    971975        self.has_poly_error_column = False 
    972976 
    973         structure = None 
    974         if self.cbStructureFactor.isEnabled(): 
    975             structure = str(self.cbStructureFactor.currentText()) 
    976         self.respondToModelStructure(model=model, structure_factor=structure) 
     977        self.respondToModelStructure(model=model, structure_factor=None) 
    977978 
    978979    def onSelectBatchFilename(self, data_index): 
     
    11171118            self.disableModelCombo() 
    11181119            self.enableStructureCombo() 
    1119             # set the index to 0 
    1120             self.cbStructureFactor.setCurrentIndex(0) 
    1121             self.model_parameters = None 
    11221120            self._model_model.clear() 
    11231121            return 
     
    11441142        model_row = item.row() 
    11451143        name_index = self._poly_model.index(model_row, 0) 
    1146         parameter_name = str(name_index.data()) # "distribution of sld" etc. 
    1147         if "istribution of" in parameter_name: 
     1144        parameter_name = str(name_index.data()).lower() # "distribution of sld" etc. 
     1145        if "distribution of" in parameter_name: 
    11481146            # just the last word 
    11491147            parameter_name = parameter_name.rsplit()[-1] 
     
    11901188            # Update the sasmodel 
    11911189            # PD[ratio] -> width, npts -> npts, nsigs -> nsigmas 
    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 
     1190            self.kernel_module.setParam(parameter_name + '.' + delegate.columnDict()[model_column], value) 
    11951191 
    11961192            # Update plot 
     
    12011197            row = self.getRowFromName(parameter_name) 
    12021198            param_item = self._model_model.item(row) 
    1203             self._model_model.blockSignals(True) 
    12041199            param_item.child(0).child(0, model_column).setText(item.text()) 
    1205             self._model_model.blockSignals(False) 
    12061200 
    12071201    def onMagnetModelChange(self, item): 
     
    12321226            # Unparsable field 
    12331227            return 
    1234         delegate = self.lstMagnetic.itemDelegate() 
    1235  
    1236         if model_column > 1: 
    1237             if model_column == delegate.mag_min: 
    1238                 pos = 1 
    1239             elif model_column == delegate.mag_max: 
    1240                 pos = 2 
    1241             elif model_column == delegate.mag_unit: 
    1242                 pos = 0 
    1243             else: 
    1244                 raise AttributeError("Wrong column in magnetism table.") 
    1245             # min/max to be changed in self.kernel_module.details[parameter_name] = ['Ang', 0.0, inf] 
    1246             self.kernel_module.details[parameter_name][pos] = value 
    1247         else: 
    1248             self.magnet_params[parameter_name] = value 
    1249             #self.kernel_module.setParam(parameter_name) = value 
    1250             # Force the chart update when actual parameters changed 
     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: 
    12511239            self.recalculatePlotData() 
    12521240 
     
    15091497        # Data going in 
    15101498        data = self.logic.data 
    1511         model = copy.deepcopy(self.kernel_module) 
     1499        model = self.kernel_module 
    15121500        qmin = self.q_range_min 
    15131501        qmax = self.q_range_max 
    1514         # add polydisperse/magnet parameters if asked 
    1515         self.updateKernelModelWithExtraParams(model) 
    15161502 
    15171503        params_to_fit = self.main_params_to_fit 
     
    15231509            raise ValueError('Fitting requires at least one parameter to optimize.') 
    15241510 
     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 
    15251516        # Get the constraints. 
    15261517        constraints = self.getComplexConstraintsForModel() 
     
    15391530            data = GuiUtils.dataFromItem(fit_index) 
    15401531            # Potential weights added directly to data 
    1541             weighted_data = self.addWeightingToData(data) 
     1532            self.addWeightingToData(data) 
    15421533            try: 
    1543                 fitter_single.set_model(model, fit_id, params_to_fit, data=weighted_data, 
     1534                fitter_single.set_model(model, fit_id, params_to_fit, data=data, 
    15441535                             constraints=constraints) 
    15451536            except ValueError as ex: 
    15461537                raise ValueError("Setting model parameters failed with: %s" % ex) 
    15471538 
    1548             qmin, qmax, _ = self.logic.computeRangeFromData(weighted_data) 
    1549             fitter_single.set_data(data=weighted_data, id=fit_id, smearer=smearer, qmin=qmin, 
     1539            qmin, qmax, _ = self.logic.computeRangeFromData(data) 
     1540            fitter_single.set_data(data=data, id=fit_id, smearer=smearer, qmin=qmin, 
    15501541                            qmax=qmax) 
    15511542            fitter_single.select_problem_for_fit(id=fit_id, value=1) 
     
    15771568            # internal so can use closure for param_dict 
    15781569            param_name = str(self._model_model.item(row, 0).text()) 
    1579             if param_name not in list(param_dict.keys()): 
     1570            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15801571                return 
    15811572            # modify the param value 
     
    15891580            # Utility function for updateof polydispersity part of the main model 
    15901581            param_name = str(self._model_model.item(row, 0).text())+'.width' 
    1591             if param_name not in list(param_dict.keys()): 
     1582            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15921583                return 
    15931584            # modify the param value 
     
    19381929        Adds weighting contribution to fitting data 
    19391930        """ 
    1940         new_data = copy.deepcopy(data) 
    19411931        # Send original data for weighting 
    19421932        weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
    19431933        if self.is2D: 
    1944             new_data.err_data = weight 
     1934            data.err_data = weight 
    19451935        else: 
    1946             new_data.dy = weight 
    1947  
    1948         return new_data 
     1936            data.dy = weight 
     1937        pass 
    19491938 
    19501939    def updateQRange(self): 
     
    19661955        # Crete/overwrite model items 
    19671956        self._model_model.clear() 
    1968  
    1969         # First, add parameters from the main model 
    1970         if model_name is not None: 
     1957        self._poly_model.clear() 
     1958        self._magnet_model.clear() 
     1959 
     1960        if model_name is None: 
     1961            if structure_factor not in (None, "None"): 
     1962                # S(Q) on its own, treat the same as a form factor 
     1963                self.kernel_module = None 
     1964                self.fromStructureFactorToQModel(structure_factor) 
     1965            else: 
     1966                # No models selected 
     1967                return 
     1968        else: 
    19711969            self.fromModelToQModel(model_name) 
    1972  
    1973         # Then, add structure factor derived parameters 
    1974         if structure_factor is not None and structure_factor != "None": 
    1975             if model_name is None: 
    1976                 # Instantiate the current sasmodel for SF-only models 
    1977                 self.kernel_module = self.models[structure_factor]() 
    1978             self.fromStructureFactorToQModel(structure_factor) 
    1979         else: 
    1980             # Allow the SF combobox visibility for the given sasmodel 
    1981             self.enableStructureFactorControl(structure_factor) 
    1982             if self.cbStructureFactor.isEnabled(): 
    1983                 structure_factor = self.cbStructureFactor.currentText() 
     1970            self.addExtraShells() 
     1971 
     1972            if structure_factor not in (None, "None"): 
     1973                # add S(Q) 
    19841974                self.fromStructureFactorToQModel(structure_factor) 
    1985  
    1986         # Then, add multishells 
    1987         if model_name is not None: 
    1988             # Multishell models need additional treatment 
    1989             self.addExtraShells() 
    1990  
    1991         # Add polydispersity to the model 
    1992         self.poly_params = {} 
    1993         self.setPolyModel() 
    1994         # Add magnetic parameters to the model 
    1995         self.magnet_params = {} 
    1996         self.setMagneticModel() 
     1975            else: 
     1976                # enable selection of S(Q) 
     1977                self.enableStructureFactorControl(structure_factor) 
     1978 
     1979            # Add polydispersity to the model 
     1980            self.setPolyModel() 
     1981            # Add magnetic parameters to the model 
     1982            self.setMagneticModel() 
    19971983 
    19981984        # Adjust the table cells width 
     
    20192005        """ 
    20202006        name = model_name 
    2021         kernel_module = None 
    20222007        if self.cbCategory.currentText() == CATEGORY_CUSTOM: 
    20232008            # custom kernel load requires full path 
     
    20252010        try: 
    20262011            kernel_module = generate.load_kernel_module(name) 
    2027         except ModuleNotFoundError as ex: 
    2028             pass 
    2029  
    2030         if kernel_module is None: 
    2031             # mismatch between "name" attribute and actual filename. 
    2032             curr_model = self.models[model_name] 
    2033             name, _ = os.path.splitext(os.path.basename(curr_model.filename)) 
    2034             try: 
    2035                 kernel_module = generate.load_kernel_module(name) 
    2036             except ModuleNotFoundError as ex: 
    2037                 logging.error("Can't find the model "+ str(ex)) 
    2038                 return 
     2012        except ModuleNotFoundError: 
     2013            # maybe it's a recategorised custom model? 
     2014            name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py") 
     2015            # If this rises, it's a valid problem. 
     2016            kernel_module = generate.load_kernel_module(name) 
    20392017 
    20402018        if hasattr(kernel_module, 'parameters'): 
     
    20672045        self.shell_names = self.shellNamesList() 
    20682046 
    2069         # Update the QModel 
     2047        # Get new rows for QModel 
    20702048        new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 
    20712049 
     2050        # Add heading row 
     2051        FittingUtilities.addHeadingRowToModel(self._model_model, model_name) 
     2052 
     2053        # Update QModel 
    20722054        for row in new_rows: 
    20732055            self._model_model.appendRow(row) 
    2074         # Update the counter used for multishell display 
    2075         self._last_model_row = self._model_model.rowCount() 
    20762056 
    20772057    def fromStructureFactorToQModel(self, structure_factor): 
     
    20792059        Setting model parameters into QStandardItemModel based on selected _structure factor_ 
    20802060        """ 
    2081         if structure_factor is None or structure_factor=="None": 
    2082             return 
    2083         structure_module = generate.load_kernel_module(structure_factor) 
    2084         structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) 
    2085  
    2086         structure_kernel = self.models[structure_factor]() 
    2087         form_kernel = self.kernel_module 
    2088  
    2089         self.kernel_module = MultiplicationModel(form_kernel, structure_kernel) 
    2090  
    2091         new_rows = FittingUtilities.addSimpleParametersToModel(structure_parameters, self.is2D) 
     2061        s_kernel = self.models[structure_factor]() 
     2062        p_kernel = self.kernel_module 
     2063 
     2064        if p_kernel is None: 
     2065            # Not a product model, just S(Q) 
     2066            self.kernel_module = s_kernel 
     2067            params = modelinfo.ParameterTable(self.kernel_module._model_info.parameters.kernel_parameters) 
     2068            new_rows = FittingUtilities.addSimpleParametersToModel(params, self.is2D) 
     2069        else: 
     2070            p_pars_len = len(p_kernel._model_info.parameters.kernel_parameters) 
     2071            s_pars_len = len(s_kernel._model_info.parameters.kernel_parameters) 
     2072 
     2073            self.kernel_module = MultiplicationModel(p_kernel, s_kernel) 
     2074            all_params = self.kernel_module._model_info.parameters.kernel_parameters 
     2075            all_param_names = [param.name for param in all_params] 
     2076 
     2077            # S(Q) params from the product model are not necessarily the same as those from the S(Q) model; any 
     2078            # conflicting names with P(Q) params will cause a rename; we also lose radius_effective (for now...) 
     2079 
     2080            # TODO: merge rest of beta approx implementation in 
     2081            # This is to ensure compatibility when we merge beta approx support in...! 
     2082 
     2083            # radius_effective is always s_params[0] 
     2084 
     2085            # if radius_effective_mode is in all_params, then all_params contains radius_effective and we want to 
     2086            # keep it in the model 
     2087 
     2088            # if radius_effective_mode is NOT in all_params, then radius_effective should NOT be kept, because the user 
     2089            # cannot specify it themselves; but, make sure we only remove it if it's actually there in the first place 
     2090            # (sasmodels master removes it already) 
     2091            if "radius_effective_mode" in all_param_names: 
     2092                # Show all parameters 
     2093                s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len]) 
     2094                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters) 
     2095            else: 
     2096                # Ensure radius_effective is not displayed 
     2097                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters[1:]) 
     2098                if "radius_effective" in all_param_names: 
     2099                    s_params = modelinfo.ParameterTable(all_params[p_pars_len+1:p_pars_len+s_pars_len]) 
     2100                else: 
     2101                    s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len-1]) 
     2102 
     2103            # Get new rows for QModel 
     2104            # Any renamed parameters are stored as data in the relevant item, for later handling 
     2105            new_rows = FittingUtilities.addSimpleParametersToModel(s_params, self.is2D, s_params_orig) 
     2106 
     2107            # TODO: merge rest of beta approx implementation in 
     2108            # These parameters are not part of P(Q) nor S(Q), but are added only to the product model (e.g. specifying 
     2109            # structure factor calculation mode) 
     2110            # product_params = all_params[p_pars_len+s_pars_len:] 
     2111 
     2112        # Add heading row 
     2113        FittingUtilities.addHeadingRowToModel(self._model_model, structure_factor) 
     2114 
     2115        # Update QModel 
    20922116        for row in new_rows: 
    20932117            self._model_model.appendRow(row) 
    20942118            # disable fitting of parameters not listed in self.kernel_module (probably radius_effective) 
    2095             if row[0].text() not in self.kernel_module.params.keys(): 
    2096                 row_num = self._model_model.rowCount() - 1 
    2097                 FittingUtilities.markParameterDisabled(self._model_model, row_num) 
    2098  
    2099         # Update the counter used for multishell display 
    2100         self._last_model_row = self._model_model.rowCount() 
     2119            # if row[0].text() not in self.kernel_module.params.keys(): 
     2120            #     row_num = self._model_model.rowCount() - 1 
     2121            #     FittingUtilities.markParameterDisabled(self._model_model, row_num) 
    21012122 
    21022123    def haveParamsToFit(self): 
     
    21242145        model_row = item.row() 
    21252146        name_index = self._model_model.index(model_row, 0) 
     2147        name_item = self._model_model.itemFromIndex(name_index) 
    21262148 
    21272149        # Extract changed value. 
     
    21322154            return 
    21332155 
    2134         parameter_name = str(self._model_model.data(name_index)) # sld, background etc. 
     2156        # if the item has user data, this is the actual parameter name (e.g. to handle duplicate names) 
     2157        if name_item.data(QtCore.Qt.UserRole): 
     2158            parameter_name = str(name_item.data(QtCore.Qt.UserRole)) 
     2159        else: 
     2160            parameter_name = str(self._model_model.data(name_index)) 
    21352161 
    21362162        # Update the parameter value - note: this supports +/-inf as well 
     
    22312257        name = self.nameFromData(fitted_data) 
    22322258        # Notify the GUI manager so it can create the theory model in DataExplorer 
    2233         self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 
    2234         self.communicate.updateTheoryFromPerspectiveSignal.emit(self.theory_item) 
     2259        new_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 
     2260        self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item) 
    22352261 
    22362262    def nameFromData(self, fitted_data): 
     
    22552281        return self.completed1D if isinstance(self.data, Data1D) else self.completed2D 
    22562282 
    2257     def updateKernelModelWithExtraParams(self, model=None): 
    2258         """ 
    2259         Updates kernel model 'model' with extra parameters from 
    2260         the polydisp and magnetism tab, if the tabs are enabled 
    2261         """ 
    2262         if model is None: return 
    2263         if not hasattr(model, 'setParam'): return 
    2264  
    2265         # add polydisperse parameters if asked 
    2266         if self.chkPolydispersity.isChecked(): 
    2267             for key, value in self.poly_params.items(): 
    2268                 model.setParam(key, value) 
    2269         # add magnetic params if asked 
    2270         if self.chkMagnetism.isChecked(): 
    2271             for key, value in self.magnet_params.items(): 
    2272                 model.setParam(key, value) 
    2273  
    22742283    def calculateQGridForModelExt(self, data=None, model=None, completefn=None, use_threads=True): 
    22752284        """ 
     
    22792288            data = self.data 
    22802289        if model is None: 
    2281             model = copy.deepcopy(self.kernel_module) 
    2282             self.updateKernelModelWithExtraParams(model) 
    2283  
     2290            model = self.kernel_module 
    22842291        if completefn is None: 
    22852292            completefn = self.methodCompleteForData() 
    22862293        smearer = self.smearing_widget.smearer() 
    2287         weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
    2288  
    22892294        # Awful API to a backend method. 
    22902295        calc_thread = self.methodCalculateForData()(data=data, 
     
    22952300                                               smearer=smearer, 
    22962301                                               state=None, 
    2297                                                weight=weight, 
     2302                                               weight=None, 
    22982303                                               fid=None, 
    22992304                                               toggle_mode_on=False, 
     
    23432348        residuals = self.calculateResiduals(fitted_data) 
    23442349        self.model_data = fitted_data 
    2345         new_plots = [fitted_data] 
    2346         if residuals is not None: 
    2347             new_plots.append(residuals) 
    2348  
    2349         if self.data_is_loaded: 
    2350             GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 
    2351         else: 
    2352             # delete theory items for the model, in order to get rid of any redundant items, e.g. beta(Q), S_eff(Q) 
    2353             self.communicate.deleteIntermediateTheoryPlotsSignal.emit(self.kernel_module.id) 
     2350 
     2351        new_plots = [fitted_data, residuals] 
    23542352 
    23552353        # Create plots for intermediate product data 
     
    23662364            new_plots.append(sq_data) 
    23672365 
    2368         # Update/generate plots 
     2366        if self.data_is_loaded: 
     2367            GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 
     2368 
     2369        # TODO: merge rest of beta approx implementation in 
     2370        # TODO: refactor 
     2371        # deal with constrained radius_effective 
     2372        # for row in range(self._model_model.rowCount()): 
     2373        #     if self._model_model.item(row, 0).text() == "radius_effective_mode": 
     2374        #         if GuiUtils.toDouble(self._model_model.item(row, 1).text()) == 0: 
     2375        #             return 
     2376        # radius_effective = intermediate_ER() 
     2377        # if radius_effective: 
     2378        #     for row in range(self._model_model.rowCount()): 
     2379        #         if self._model_model.item(row, 0).text() == "radius_effective": 
     2380        #             self._model_model.item(row, 1).setText(str(radius_effective)) 
     2381        #             break 
     2382 
    23692383        for plot in new_plots: 
    2370             self.communicate.plotUpdateSignal.emit([plot]) 
     2384            if hasattr(plot, "id") and "esidual" in plot.id: 
     2385                # TODO: fix updates to residuals plot 
     2386                pass 
     2387            elif plot is not None: 
     2388                self.communicate.plotUpdateSignal.emit([plot]) 
    23712389 
    23722390    def complete2D(self, return_data): 
     
    23752393        """ 
    23762394        fitted_data = self.logic.new2DPlot(return_data) 
    2377         residuals = self.calculateResiduals(fitted_data) 
     2395        self.calculateResiduals(fitted_data) 
    23782396        self.model_data = fitted_data 
    2379         new_plots = [fitted_data] 
    2380         if residuals is not None: 
    2381             new_plots.append(residuals) 
    2382  
    2383         # Update/generate plots 
    2384         for plot in new_plots: 
    2385             self.communicate.plotUpdateSignal.emit([plot]) 
    23862397 
    23872398    def calculateResiduals(self, fitted_data): 
     
    23932404 
    23942405        # Modify fitted_data with weighting 
    2395         weighted_data = self.addWeightingToData(fitted_data) 
    2396  
    2397         self.createNewIndex(weighted_data) 
     2406        self.addWeightingToData(fitted_data) 
     2407 
     2408        self.createNewIndex(fitted_data) 
    23982409        # Calculate difference between return_data and logic.data 
    2399         self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.logic.data) 
     2410        self.chi2 = FittingUtilities.calculateChi2(fitted_data, self.logic.data) 
    24002411        # Update the control 
    24012412        chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 
    24022413        self.lblChi2Value.setText(chi2_repr) 
    24032414 
     2415        # self.communicate.plotUpdateSignal.emit([fitted_data]) 
     2416 
    24042417        # Plot residuals if actual data 
    24052418        if not self.data_is_loaded: 
    24062419            return 
    24072420 
    2408         residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 
     2421        residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data) 
    24092422        residuals_plot.id = "Residual " + residuals_plot.id 
    24102423        self.createNewIndex(residuals_plot) 
     
    24752488        self._poly_model.clear() 
    24762489 
    2477         parameters = self.model_parameters.form_volume_parameters 
    2478         if self.is2D: 
    2479             parameters += self.model_parameters.orientation_parameters 
    2480  
    24812490        [self.setPolyModelParameters(i, param) for i, param in \ 
    2482             enumerate(parameters) if param.polydisperse] 
    2483  
     2491            enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 
    24842492        FittingUtilities.addPolyHeadersToModel(self._poly_model) 
    24852493 
     
    25142522        _, min, max = self.kernel_module.details[param_name] 
    25152523 
    2516         # Update local param dict 
    2517         self.poly_params[param_name + '.width'] = width 
    2518         self.poly_params[param_name + '.npts'] = npts 
    2519         self.poly_params[param_name + '.nsigmas'] = nsigs 
    2520  
    25212524        # Construct a row with polydisp. related variable. 
    25222525        # This will get added to the polydisp. model 
     
    25662569        def updateFunctionCaption(row): 
    25672570            # Utility function for update of polydispersity function name in the main model 
    2568             self._model_model.blockSignals(True) 
     2571            if not self.isCheckable(row): 
     2572                return 
    25692573            param_name = str(self._model_model.item(row, 0).text()) 
    2570             self._model_model.blockSignals(False) 
    25712574            if param_name !=  param.name: 
    25722575                return 
    25732576            # Modify the param value 
    2574             self._model_model.blockSignals(True) 
    25752577            if self.has_error_column: 
    25762578                # err column changes the indexing 
     
    25782580            else: 
    25792581                self._model_model.item(row, 0).child(0).child(0,4).setText(combo_string) 
    2580             self._model_model.blockSignals(False) 
    25812582 
    25822583        if combo_string == 'array': 
     
    26972698                        param.units] 
    26982699 
    2699         self.magnet_params[param.name] = param.default 
    2700  
    27012700        FittingUtilities.addCheckedListToModel(model, checked_list) 
    27022701 
     
    27382737 
    27392738        self.lstParams.setIndexWidget(shell_index, func) 
    2740         self._last_model_row = self._model_model.rowCount() 
     2739        self._n_shells_row = shell_row - 1 
    27412740 
    27422741        # Set the index to the state-kept value 
     
    27492748        """ 
    27502749        # Find row location of the combobox 
    2751         last_row = self._last_model_row 
    2752         remove_rows = self._model_model.rowCount() - last_row 
     2750        first_row = self._n_shells_row + 1 
     2751        remove_rows = self._num_shell_params 
    27532752 
    27542753        if remove_rows > 1: 
    2755             self._model_model.removeRows(last_row, remove_rows) 
    2756  
    2757         FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index) 
     2754            self._model_model.removeRows(first_row, remove_rows) 
     2755 
     2756        new_rows = FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index, first_row) 
     2757        self._num_shell_params = len(new_rows) 
     2758 
    27582759        self.current_shell_displayed = index 
    27592760 
     
    28752876        # TODO: add polidyspersity and magnetism 
    28762877 
     2878 
    28772879    def updateUndo(self): 
    28782880        """ 
     
    29112913        if self.all_data: 
    29122914            index = self.all_data[self.data_index] 
    2913         else: 
    2914             index = self.theory_item 
    29152915        report_logic = ReportPageLogic(self, 
    29162916                                       kernel_module=self.kernel_module, 
     
    30363036        # first - regular params 
    30373037        param_list = [] 
    3038  
    3039         param_list.append(['model_name', str(self.cbModel.currentText())]) 
    30403038        def gatherParams(row): 
    30413039            """ 
     
    31243122        if lines[0] != 'sasview_parameter_values': 
    31253123            return False 
    3126  
    3127         model = lines[1].split(',') 
    3128  
    3129         if model[0] != 'model_name': 
    3130             return False 
    3131  
    3132         context['model_name'] = [model[1]] 
    3133         for line in lines[2:-1]: 
     3124        for line in lines[1:-1]: 
    31343125            if len(line) != 0: 
    31353126                item = line.split(',') 
     
    31573148                    except IndexError: 
    31583149                        pass 
    3159  
    3160         if str(self.cbModel.currentText()) != str(context['model_name'][0]): 
    3161             msg = QtWidgets.QMessageBox() 
    3162             msg.setIcon(QtWidgets.QMessageBox.Information) 
    3163             msg.setText("The model in the clipboard is not the same as the currently loaded model. \ 
    3164                          Not all parameters saved may paste correctly.") 
    3165             msg.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) 
    3166             result = msg.exec_() 
    3167             if result == QtWidgets.QMessageBox.Ok: 
    3168                 pass 
    3169             else: 
    3170                 return 
    31713150 
    31723151        self.updateFullModel(context) 
     
    32073186            param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 
    32083187            self._model_model.item(row, 3+ioffset).setText(param_repr) 
    3209             self.setFocus() 
    3210  
    32113188 
    32123189        # block signals temporarily, so we don't end up 
     
    32153192        self.iterateOverModel(updateFittedValues) 
    32163193        self._model_model.blockSignals(False) 
    3217  
    32183194 
    32193195    def updateFullPolyModel(self, param_dict): 
     
    32603236            param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 
    32613237            self._poly_model.item(row, 5+ioffset).setText(param_repr) 
    3262             self.setFocus() 
    32633238 
    32643239        # block signals temporarily, so we don't end up 
     
    32683243        self._poly_model.blockSignals(False) 
    32693244 
     3245 
Note: See TracChangeset for help on using the changeset viewer.