Ignore:
File:
1 edited

Legend:

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

    r0109f2a r40975f8  
    4949 
    5050 
    51  
    5251TAB_MAGNETISM = 4 
    5352TAB_POLY = 3 
     
    6160 
    6261logger = logging.getLogger(__name__) 
    63  
    6462 
    6563class ToolTippedItemModel(QtGui.QStandardItemModel): 
     
    221219        # Utility variable to enable unselectable option in category combobox 
    222220        self._previous_category_index = 0 
    223         # Utility variables for multishell display 
    224         self._n_shells_row = 0 
    225         self._num_shell_params = 0 
     221        # Utility variable for multishell display 
     222        self._last_model_row = 0 
    226223        # Dictionary of {model name: model class} for the current category 
    227224        self.models = {} 
     
    251248        self.kernel_module_copy = None 
    252249 
     250        # dictionaries of current params 
     251        self.poly_params = {} 
     252        self.magnet_params = {} 
     253 
    253254        # Page id for fitting 
    254255        # To keep with previous SasView values, use 200 as the start offset 
     
    267268        self.has_poly_error_column = False 
    268269        self.has_magnet_error_column = False 
     270 
     271        # If the widget generated theory item, save it 
     272        self.theory_item = None 
    269273 
    270274        # signal communicator 
     
    390394        # Tag along functionality 
    391395        self.label.setText("Data loaded from: ") 
    392         self.lblFilename.setText(self.logic.data.filename) 
     396        if self.logic.data.filename: 
     397            self.lblFilename.setText(self.logic.data.filename) 
     398        else: 
     399            self.lblFilename.setText(self.logic.data.name) 
    393400        self.updateQRange() 
    394401        # Switch off Data2D control 
     
    523530        # Signals from separate tabs asking for replot 
    524531        self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
    525         self.options_widget.plot_signal.connect(self.onOptionsUpdate) 
    526532 
    527533        # Signals from other widgets 
     
    670676        Return list of all parameters for the current model 
    671677        """ 
    672         return [self._model_model.item(row).text() 
    673                 for row in range(self._model_model.rowCount()) 
    674                 if self.isCheckable(row)] 
     678        return [self._model_model.item(row).text() for row in range(self._model_model.rowCount())] 
    675679 
    676680    def modifyViewOnRow(self, row, font=None, brush=None): 
     
    700704        assert isinstance(constraint, Constraint) 
    701705        assert 0 <= row <= self._model_model.rowCount() 
    702         assert self.isCheckable(row) 
    703706 
    704707        item = QtGui.QStandardItem() 
     
    721724        max_col = self.lstParams.itemDelegate().param_max 
    722725        for row in self.selectedParameters(): 
    723             assert(self.isCheckable(row)) 
    724726            param = self._model_model.item(row, 0).text() 
    725727            value = self._model_model.item(row, 1).text() 
     
    764766        max_col = self.lstParams.itemDelegate().param_max 
    765767        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         if self.isCheckable(row): 
     796        try: 
    797797            item = self._model_model.item(row, 1) 
    798             try: 
    799                 return item.child(0).data() 
    800             except AttributeError: 
    801                 # return none when no constraints 
    802                 pass 
    803         return None 
     798            return item.child(0).data() 
     799        except AttributeError: 
     800            # return none when no constraints 
     801            return None 
    804802 
    805803    def rowHasConstraint(self, row): 
     
    807805        Finds out if row of the main model has a constraint child 
    808806        """ 
    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 
     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 
    815812        return False 
    816813 
     
    819816        Finds out if row of the main model has an active constraint child 
    820817        """ 
    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 
     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 
    827823        return False 
    828824 
     
    831827        Finds out if row of the main model has an active, nontrivial constraint child 
    832828        """ 
    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 
     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 
    839834        return False 
    840835 
     
    964959        model = self.cbModel.currentText() 
    965960 
    966         # empty combobox forced to be read 
     961        # Assure the control is active 
     962        if not self.cbModel.isEnabled(): 
     963            return 
     964        # Empty combobox forced to be read 
    967965        if not model: 
    968966            return 
    969         # Reset structure factor 
    970         self.cbStructureFactor.setCurrentIndex(0) 
    971967 
    972968        # Reset parameters to fit 
     
    975971        self.has_poly_error_column = False 
    976972 
    977         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) 
    978977 
    979978    def onSelectBatchFilename(self, data_index): 
     
    11181117            self.disableModelCombo() 
    11191118            self.enableStructureCombo() 
     1119            # set the index to 0 
     1120            self.cbStructureFactor.setCurrentIndex(0) 
     1121            self.model_parameters = None 
    11201122            self._model_model.clear() 
    11211123            return 
     
    11421144        model_row = item.row() 
    11431145        name_index = self._poly_model.index(model_row, 0) 
    1144         parameter_name = str(name_index.data()).lower() # "distribution of sld" etc. 
    1145         if "distribution of" in parameter_name: 
     1146        parameter_name = str(name_index.data()) # "distribution of sld" etc. 
     1147        if "istribution of" in parameter_name: 
    11461148            # just the last word 
    11471149            parameter_name = parameter_name.rsplit()[-1] 
     
    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) 
     
    15681569            # internal so can use closure for param_dict 
    15691570            param_name = str(self._model_model.item(row, 0).text()) 
    1570             if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
     1571            if param_name not in list(param_dict.keys()): 
    15711572                return 
    15721573            # modify the param value 
     
    15801581            # Utility function for updateof polydispersity part of the main model 
    15811582            param_name = str(self._model_model.item(row, 0).text())+'.width' 
    1582             if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
     1583            if param_name not in list(param_dict.keys()): 
    15831584                return 
    15841585            # modify the param value 
     
    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): 
     
    19551958        # Crete/overwrite model items 
    19561959        self._model_model.clear() 
    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 
     1960 
     1961        # First, add parameters from the main model 
     1962        if model_name is not None: 
     1963            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: 
     1972            # Allow the SF combobox visibility for the given sasmodel 
     1973            self.enableStructureFactorControl(structure_factor) 
     1974            if self.cbStructureFactor.isEnabled(): 
     1975                structure_factor = self.cbStructureFactor.currentText() 
    19641976                self.fromStructureFactorToQModel(structure_factor) 
    1965             else: 
    1966                 # No models selected 
    1967                 return 
    1968         else: 
    1969             self.fromModelToQModel(model_name) 
     1977 
     1978        # Then, add multishells 
     1979        if model_name is not None: 
     1980            # Multishell models need additional treatment 
    19701981            self.addExtraShells() 
    19711982 
    1972             if structure_factor not in (None, "None"): 
    1973                 # add S(Q) 
    1974                 self.fromStructureFactorToQModel(structure_factor) 
    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() 
     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() 
    19831989 
    19841990        # Adjust the table cells width 
     
    20052011        """ 
    20062012        name = model_name 
     2013        kernel_module = None 
    20072014        if self.cbCategory.currentText() == CATEGORY_CUSTOM: 
    20082015            # custom kernel load requires full path 
     
    20102017        try: 
    20112018            kernel_module = generate.load_kernel_module(name) 
    2012         except ModuleNotFoundError: 
    2013             # maybe it's a recategorised custom model? 
    2014             name = os.path.join(ModelUtilities.find_plugins_dir(), model_name+".py") 
    2015             # If this rises, it's a valid problem. 
    2016             kernel_module = generate.load_kernel_module(name) 
     2019        except ModuleNotFoundError as ex: 
     2020            pass 
     2021 
     2022        if kernel_module is None: 
     2023            # mismatch between "name" attribute and actual filename. 
     2024            curr_model = self.models[model_name] 
     2025            name, _ = os.path.splitext(os.path.basename(curr_model.filename)) 
     2026            try: 
     2027                kernel_module = generate.load_kernel_module(name) 
     2028            except ModuleNotFoundError as ex: 
     2029                logging.error("Can't find the model "+ str(ex)) 
     2030                return 
    20172031 
    20182032        if hasattr(kernel_module, 'parameters'): 
     
    20452059        self.shell_names = self.shellNamesList() 
    20462060 
    2047         # Get new rows for QModel 
     2061        # Update the QModel 
    20482062        new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 
    20492063 
    2050         # Add heading row 
    2051         FittingUtilities.addHeadingRowToModel(self._model_model, model_name) 
    2052  
    2053         # Update QModel 
    20542064        for row in new_rows: 
    20552065            self._model_model.appendRow(row) 
     2066        # Update the counter used for multishell display 
     2067        self._last_model_row = self._model_model.rowCount() 
    20562068 
    20572069    def fromStructureFactorToQModel(self, structure_factor): 
     
    20592071        Setting model parameters into QStandardItemModel based on selected _structure factor_ 
    20602072        """ 
    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 
     2073        if structure_factor is None or structure_factor=="None": 
     2074            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) 
    21162084        for row in new_rows: 
    21172085            self._model_model.appendRow(row) 
    21182086            # disable fitting of parameters not listed in self.kernel_module (probably radius_effective) 
    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) 
     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() 
    21222093 
    21232094    def haveParamsToFit(self): 
     
    21452116        model_row = item.row() 
    21462117        name_index = self._model_model.index(model_row, 0) 
    2147         name_item = self._model_model.itemFromIndex(name_index) 
    21482118 
    21492119        # Extract changed value. 
     
    21542124            return 
    21552125 
    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)) 
     2126        parameter_name = str(self._model_model.data(name_index)) # sld, background etc. 
    21612127 
    21622128        # Update the parameter value - note: this supports +/-inf as well 
     
    22572223        name = self.nameFromData(fitted_data) 
    22582224        # Notify the GUI manager so it can create the theory model in DataExplorer 
    2259         new_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 
    2260         self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item) 
     2225        self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 
     2226        self.communicate.updateTheoryFromPerspectiveSignal.emit(self.theory_item) 
    22612227 
    22622228    def nameFromData(self, fitted_data): 
     
    22812247        return self.completed1D if isinstance(self.data, Data1D) else self.completed2D 
    22822248 
     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 
    22832266    def calculateQGridForModelExt(self, data=None, model=None, completefn=None, use_threads=True): 
    22842267        """ 
     
    22882271            data = self.data 
    22892272        if model is None: 
    2290             model = self.kernel_module 
     2273            model = copy.deepcopy(self.kernel_module) 
     2274            self.updateKernelModelWithExtraParams(model) 
     2275 
    22912276        if completefn is None: 
    22922277            completefn = self.methodCompleteForData() 
    22932278        smearer = self.smearing_widget.smearer() 
     2279        weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
     2280 
    22942281        # Awful API to a backend method. 
    22952282        calc_thread = self.methodCalculateForData()(data=data, 
     
    23002287                                               smearer=smearer, 
    23012288                                               state=None, 
    2302                                                weight=None, 
     2289                                               weight=weight, 
    23032290                                               fid=None, 
    23042291                                               toggle_mode_on=False, 
     
    23482335        residuals = self.calculateResiduals(fitted_data) 
    23492336        self.model_data = fitted_data 
    2350  
    2351         new_plots = [fitted_data, residuals] 
    2352  
    2353         # Create plots for intermediate product data 
    2354         pq_data, sq_data = self.logic.new1DProductPlots(return_data, self.tab_id) 
    2355         if pq_data is not None: 
    2356             pq_data.symbol = "Line" 
    2357             self.createNewIndex(pq_data) 
    2358             # self.communicate.plotUpdateSignal.emit([pq_data]) 
    2359             new_plots.append(pq_data) 
    2360         if sq_data is not None: 
    2361             sq_data.symbol = "Line" 
    2362             self.createNewIndex(sq_data) 
    2363             # self.communicate.plotUpdateSignal.emit([sq_data]) 
    2364             new_plots.append(sq_data) 
     2337        new_plots = [fitted_data] 
     2338        if residuals is not None: 
     2339            new_plots.append(residuals) 
    23652340 
    23662341        if self.data_is_loaded: 
    23672342            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  
     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 
     2347        # Create plots for intermediate product data 
     2348        plots = self.logic.new1DProductPlots(return_data, self.tab_id) 
     2349        for plot in plots: 
     2350            plot.symbol = "Line" 
     2351            self.createNewIndex(plot) 
     2352            new_plots.append(plot) 
     2353 
     2354        # Update/generate plots 
    23832355        for plot in new_plots: 
    2384             if hasattr(plot, "id") and "esidual" in plot.id: 
    2385                 # TODO: fix updates to residuals plot 
    2386                 pass 
    2387             elif plot is not None: 
    2388                 self.communicate.plotUpdateSignal.emit([plot]) 
     2356            self.communicate.plotUpdateSignal.emit([plot]) 
    23892357 
    23902358    def complete2D(self, return_data): 
     
    23932361        """ 
    23942362        fitted_data = self.logic.new2DPlot(return_data) 
    2395         self.calculateResiduals(fitted_data) 
     2363        residuals = self.calculateResiduals(fitted_data) 
    23962364        self.model_data = fitted_data 
     2365        new_plots = [fitted_data] 
     2366        if residuals is not None: 
     2367            new_plots.append(residuals) 
     2368 
     2369        # Update/generate plots 
     2370        for plot in new_plots: 
     2371            self.communicate.plotUpdateSignal.emit([plot]) 
    23972372 
    23982373    def calculateResiduals(self, fitted_data): 
     
    24042379 
    24052380        # Modify fitted_data with weighting 
    2406         self.addWeightingToData(fitted_data) 
    2407  
    2408         self.createNewIndex(fitted_data) 
     2381        weighted_data = self.addWeightingToData(fitted_data) 
     2382 
     2383        self.createNewIndex(weighted_data) 
    24092384        # Calculate difference between return_data and logic.data 
    2410         self.chi2 = FittingUtilities.calculateChi2(fitted_data, self.logic.data) 
     2385        self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.logic.data) 
    24112386        # Update the control 
    24122387        chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 
    24132388        self.lblChi2Value.setText(chi2_repr) 
    24142389 
    2415         # self.communicate.plotUpdateSignal.emit([fitted_data]) 
    2416  
    24172390        # Plot residuals if actual data 
    24182391        if not self.data_is_loaded: 
    24192392            return 
    24202393 
    2421         residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data) 
     2394        residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 
    24222395        residuals_plot.id = "Residual " + residuals_plot.id 
    24232396        self.createNewIndex(residuals_plot) 
     
    24882461        self._poly_model.clear() 
    24892462 
     2463        parameters = self.model_parameters.form_volume_parameters 
     2464        if self.is2D: 
     2465            parameters += self.model_parameters.orientation_parameters 
     2466 
    24902467        [self.setPolyModelParameters(i, param) for i, param in \ 
    2491             enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 
     2468            enumerate(parameters) if param.polydisperse] 
     2469 
    24922470        FittingUtilities.addPolyHeadersToModel(self._poly_model) 
    24932471 
     
    25222500        _, min, max = self.kernel_module.details[param_name] 
    25232501 
     2502        # Update local param dict 
     2503        self.poly_params[param_name + '.width'] = width 
     2504        self.poly_params[param_name + '.npts'] = npts 
     2505        self.poly_params[param_name + '.nsigmas'] = nsigs 
     2506 
    25242507        # Construct a row with polydisp. related variable. 
    25252508        # This will get added to the polydisp. model 
     
    25692552        def updateFunctionCaption(row): 
    25702553            # Utility function for update of polydispersity function name in the main model 
    2571             if not self.isCheckable(row): 
    2572                 return 
    25732554            param_name = str(self._model_model.item(row, 0).text()) 
    25742555            if param_name !=  param.name: 
     
    26982679                        param.units] 
    26992680 
     2681        self.magnet_params[param.name] = param.default 
     2682 
    27002683        FittingUtilities.addCheckedListToModel(model, checked_list) 
    27012684 
     
    27372720 
    27382721        self.lstParams.setIndexWidget(shell_index, func) 
    2739         self._n_shells_row = shell_row - 1 
     2722        self._last_model_row = self._model_model.rowCount() 
    27402723 
    27412724        # Set the index to the state-kept value 
     
    27482731        """ 
    27492732        # Find row location of the combobox 
    2750         first_row = self._n_shells_row + 1 
    2751         remove_rows = self._num_shell_params 
     2733        last_row = self._last_model_row 
     2734        remove_rows = self._model_model.rowCount() - last_row 
    27522735 
    27532736        if remove_rows > 1: 
    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  
     2737            self._model_model.removeRows(last_row, remove_rows) 
     2738 
     2739        FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index) 
    27592740        self.current_shell_displayed = index 
    27602741 
     
    28762857        # TODO: add polidyspersity and magnetism 
    28772858 
    2878  
    28792859    def updateUndo(self): 
    28802860        """ 
     
    29132893        if self.all_data: 
    29142894            index = self.all_data[self.data_index] 
     2895        else: 
     2896            index = self.theory_item 
    29152897        report_logic = ReportPageLogic(self, 
    29162898                                       kernel_module=self.kernel_module, 
     
    30363018        # first - regular params 
    30373019        param_list = [] 
     3020 
     3021        param_list.append(['model_name', str(self.cbModel.currentText())]) 
    30383022        def gatherParams(row): 
    30393023            """ 
     
    31223106        if lines[0] != 'sasview_parameter_values': 
    31233107            return False 
    3124         for line in lines[1:-1]: 
     3108 
     3109        model = lines[1].split(',') 
     3110 
     3111        if model[0] != 'model_name': 
     3112            return False 
     3113 
     3114        context['model_name'] = [model[1]] 
     3115        for line in lines[2:-1]: 
    31253116            if len(line) != 0: 
    31263117                item = line.split(',') 
     
    31483139                    except IndexError: 
    31493140                        pass 
     3141 
     3142        if str(self.cbModel.currentText()) != str(context['model_name'][0]): 
     3143            msg = QtWidgets.QMessageBox() 
     3144            msg.setIcon(QtWidgets.QMessageBox.Information) 
     3145            msg.setText("The model in the clipboard is not the same as the currently loaded model. \ 
     3146                         Not all parameters saved may paste correctly.") 
     3147            msg.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) 
     3148            result = msg.exec_() 
     3149            if result == QtWidgets.QMessageBox.Ok: 
     3150                pass 
     3151            else: 
     3152                return 
    31503153 
    31513154        self.updateFullModel(context) 
     
    31863189            param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 
    31873190            self._model_model.item(row, 3+ioffset).setText(param_repr) 
     3191            self.setFocus() 
     3192 
    31883193 
    31893194        # block signals temporarily, so we don't end up 
     
    31923197        self.iterateOverModel(updateFittedValues) 
    31933198        self._model_model.blockSignals(False) 
     3199 
    31943200 
    31953201    def updateFullPolyModel(self, param_dict): 
     
    32363242            param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 
    32373243            self._poly_model.item(row, 5+ioffset).setText(param_repr) 
     3244            self.setFocus() 
    32383245 
    32393246        # block signals temporarily, so we don't end up 
     
    32433250        self._poly_model.blockSignals(False) 
    32443251 
    3245  
Note: See TracChangeset for help on using the changeset viewer.