Ignore:
File:
1 edited

Legend:

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

    r40975f8 r0109f2a  
    4949 
    5050 
     51 
    5152TAB_MAGNETISM = 4 
    5253TAB_POLY = 3 
     
    6061 
    6162logger = logging.getLogger(__name__) 
     63 
    6264 
    6365class ToolTippedItemModel(QtGui.QStandardItemModel): 
     
    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 
    11971193            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()) 
    11981200 
    11991201    def onMagnetModelChange(self, item): 
     
    12241226            # Unparsable field 
    12251227            return 
    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 
     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: 
    12431239            self.recalculatePlotData() 
    12441240 
     
    15011497        # Data going in 
    15021498        data = self.logic.data 
    1503         model = copy.deepcopy(self.kernel_module) 
     1499        model = self.kernel_module 
    15041500        qmin = self.q_range_min 
    15051501        qmax = self.q_range_max 
    1506         # add polydisperse/magnet parameters if asked 
    1507         self.updateKernelModelWithExtraParams(model) 
    15081502 
    15091503        params_to_fit = self.main_params_to_fit 
     
    15151509            raise ValueError('Fitting requires at least one parameter to optimize.') 
    15161510 
     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 
    15171516        # Get the constraints. 
    15181517        constraints = self.getComplexConstraintsForModel() 
     
    15311530            data = GuiUtils.dataFromItem(fit_index) 
    15321531            # Potential weights added directly to data 
    1533             weighted_data = self.addWeightingToData(data) 
     1532            self.addWeightingToData(data) 
    15341533            try: 
    1535                 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, 
    15361535                             constraints=constraints) 
    15371536            except ValueError as ex: 
    15381537                raise ValueError("Setting model parameters failed with: %s" % ex) 
    15391538 
    1540             qmin, qmax, _ = self.logic.computeRangeFromData(weighted_data) 
    1541             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, 
    15421541                            qmax=qmax) 
    15431542            fitter_single.select_problem_for_fit(id=fit_id, value=1) 
     
    15691568            # internal so can use closure for param_dict 
    15701569            param_name = str(self._model_model.item(row, 0).text()) 
    1571             if param_name not in list(param_dict.keys()): 
     1570            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15721571                return 
    15731572            # modify the param value 
     
    15811580            # Utility function for updateof polydispersity part of the main model 
    15821581            param_name = str(self._model_model.item(row, 0).text())+'.width' 
    1583             if param_name not in list(param_dict.keys()): 
     1582            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15841583                return 
    15851584            # modify the param value 
     
    19301929        Adds weighting contribution to fitting data 
    19311930        """ 
    1932         new_data = copy.deepcopy(data) 
    19331931        # Send original data for weighting 
    19341932        weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
    19351933        if self.is2D: 
    1936             new_data.err_data = weight 
     1934            data.err_data = weight 
    19371935        else: 
    1938             new_data.dy = weight 
    1939  
    1940         return new_data 
     1936            data.dy = weight 
     1937        pass 
    19411938 
    19421939    def updateQRange(self): 
     
    19581955        # Crete/overwrite model items 
    19591956        self._model_model.clear() 
    1960  
    1961         # First, add parameters from the main model 
    1962         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: 
    19631969            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() 
     1970            self.addExtraShells() 
     1971 
     1972            if structure_factor not in (None, "None"): 
     1973                # add S(Q) 
    19761974                self.fromStructureFactorToQModel(structure_factor) 
    1977  
    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() 
     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() 
    19891983 
    19901984        # Adjust the table cells width 
     
    20112005        """ 
    20122006        name = model_name 
    2013         kernel_module = None 
    20142007        if self.cbCategory.currentText() == CATEGORY_CUSTOM: 
    20152008            # custom kernel load requires full path 
     
    20172010        try: 
    20182011            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 
     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) 
    20312017 
    20322018        if hasattr(kernel_module, 'parameters'): 
     
    20592045        self.shell_names = self.shellNamesList() 
    20602046 
    2061         # Update the QModel 
     2047        # Get new rows for QModel 
    20622048        new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 
    20632049 
     2050        # Add heading row 
     2051        FittingUtilities.addHeadingRowToModel(self._model_model, model_name) 
     2052 
     2053        # Update QModel 
    20642054        for row in new_rows: 
    20652055            self._model_model.appendRow(row) 
    2066         # Update the counter used for multishell display 
    2067         self._last_model_row = self._model_model.rowCount() 
    20682056 
    20692057    def fromStructureFactorToQModel(self, structure_factor): 
     
    20712059        Setting model parameters into QStandardItemModel based on selected _structure factor_ 
    20722060        """ 
    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) 
     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 
    20842116        for row in new_rows: 
    20852117            self._model_model.appendRow(row) 
    20862118            # 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() 
     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) 
    20932122 
    20942123    def haveParamsToFit(self): 
     
    21162145        model_row = item.row() 
    21172146        name_index = self._model_model.index(model_row, 0) 
     2147        name_item = self._model_model.itemFromIndex(name_index) 
    21182148 
    21192149        # Extract changed value. 
     
    21242154            return 
    21252155 
    2126         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)) 
    21272161 
    21282162        # Update the parameter value - note: this supports +/-inf as well 
     
    22232257        name = self.nameFromData(fitted_data) 
    22242258        # Notify the GUI manager so it can create the theory model in DataExplorer 
    2225         self.theory_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 
    2226         self.communicate.updateTheoryFromPerspectiveSignal.emit(self.theory_item) 
     2259        new_item = GuiUtils.createModelItemWithPlot(fitted_data, name=name) 
     2260        self.communicate.updateTheoryFromPerspectiveSignal.emit(new_item) 
    22272261 
    22282262    def nameFromData(self, fitted_data): 
     
    22472281        return self.completed1D if isinstance(self.data, Data1D) else self.completed2D 
    22482282 
    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  
    22662283    def calculateQGridForModelExt(self, data=None, model=None, completefn=None, use_threads=True): 
    22672284        """ 
     
    22712288            data = self.data 
    22722289        if model is None: 
    2273             model = copy.deepcopy(self.kernel_module) 
    2274             self.updateKernelModelWithExtraParams(model) 
    2275  
     2290            model = self.kernel_module 
    22762291        if completefn is None: 
    22772292            completefn = self.methodCompleteForData() 
    22782293        smearer = self.smearing_widget.smearer() 
    2279         weight = FittingUtilities.getWeight(data=data, is2d=self.is2D, flag=self.weighting) 
    2280  
    22812294        # Awful API to a backend method. 
    22822295        calc_thread = self.methodCalculateForData()(data=data, 
     
    22872300                                               smearer=smearer, 
    22882301                                               state=None, 
    2289                                                weight=weight, 
     2302                                               weight=None, 
    22902303                                               fid=None, 
    22912304                                               toggle_mode_on=False, 
     
    23352348        residuals = self.calculateResiduals(fitted_data) 
    23362349        self.model_data = fitted_data 
    2337         new_plots = [fitted_data] 
    2338         if residuals is not None: 
    2339             new_plots.append(residuals) 
     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) 
    23402365 
    23412366        if self.data_is_loaded: 
    23422367            GuiUtils.deleteRedundantPlots(self.all_data[self.data_index], new_plots) 
    2343         else: 
    2344             # delete theory items for the model, in order to get rid of any redundant items, e.g. beta(Q), S_eff(Q) 
    2345             self.communicate.deleteIntermediateTheoryPlotsSignal.emit(self.kernel_module.id) 
    2346  
    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 
     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 
    23552383        for plot in new_plots: 
    2356             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]) 
    23572389 
    23582390    def complete2D(self, return_data): 
     
    23612393        """ 
    23622394        fitted_data = self.logic.new2DPlot(return_data) 
    2363         residuals = self.calculateResiduals(fitted_data) 
     2395        self.calculateResiduals(fitted_data) 
    23642396        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]) 
    23722397 
    23732398    def calculateResiduals(self, fitted_data): 
     
    23792404 
    23802405        # Modify fitted_data with weighting 
    2381         weighted_data = self.addWeightingToData(fitted_data) 
    2382  
    2383         self.createNewIndex(weighted_data) 
     2406        self.addWeightingToData(fitted_data) 
     2407 
     2408        self.createNewIndex(fitted_data) 
    23842409        # Calculate difference between return_data and logic.data 
    2385         self.chi2 = FittingUtilities.calculateChi2(weighted_data, self.logic.data) 
     2410        self.chi2 = FittingUtilities.calculateChi2(fitted_data, self.logic.data) 
    23862411        # Update the control 
    23872412        chi2_repr = "---" if self.chi2 is None else GuiUtils.formatNumber(self.chi2, high=True) 
    23882413        self.lblChi2Value.setText(chi2_repr) 
    23892414 
     2415        # self.communicate.plotUpdateSignal.emit([fitted_data]) 
     2416 
    23902417        # Plot residuals if actual data 
    23912418        if not self.data_is_loaded: 
    23922419            return 
    23932420 
    2394         residuals_plot = FittingUtilities.plotResiduals(self.data, weighted_data) 
     2421        residuals_plot = FittingUtilities.plotResiduals(self.data, fitted_data) 
    23952422        residuals_plot.id = "Residual " + residuals_plot.id 
    23962423        self.createNewIndex(residuals_plot) 
     
    24612488        self._poly_model.clear() 
    24622489 
    2463         parameters = self.model_parameters.form_volume_parameters 
    2464         if self.is2D: 
    2465             parameters += self.model_parameters.orientation_parameters 
    2466  
    24672490        [self.setPolyModelParameters(i, param) for i, param in \ 
    2468             enumerate(parameters) if param.polydisperse] 
    2469  
     2491            enumerate(self.model_parameters.form_volume_parameters) if param.polydisperse] 
    24702492        FittingUtilities.addPolyHeadersToModel(self._poly_model) 
    24712493 
     
    25002522        _, min, max = self.kernel_module.details[param_name] 
    25012523 
    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  
    25072524        # Construct a row with polydisp. related variable. 
    25082525        # This will get added to the polydisp. model 
     
    25522569        def updateFunctionCaption(row): 
    25532570            # Utility function for update of polydispersity function name in the main model 
     2571            if not self.isCheckable(row): 
     2572                return 
    25542573            param_name = str(self._model_model.item(row, 0).text()) 
    25552574            if param_name !=  param.name: 
     
    26792698                        param.units] 
    26802699 
    2681         self.magnet_params[param.name] = param.default 
    2682  
    26832700        FittingUtilities.addCheckedListToModel(model, checked_list) 
    26842701 
     
    27202737 
    27212738        self.lstParams.setIndexWidget(shell_index, func) 
    2722         self._last_model_row = self._model_model.rowCount() 
     2739        self._n_shells_row = shell_row - 1 
    27232740 
    27242741        # Set the index to the state-kept value 
     
    27312748        """ 
    27322749        # Find row location of the combobox 
    2733         last_row = self._last_model_row 
    2734         remove_rows = self._model_model.rowCount() - last_row 
     2750        first_row = self._n_shells_row + 1 
     2751        remove_rows = self._num_shell_params 
    27352752 
    27362753        if remove_rows > 1: 
    2737             self._model_model.removeRows(last_row, remove_rows) 
    2738  
    2739         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 
    27402759        self.current_shell_displayed = index 
    27412760 
     
    28572876        # TODO: add polidyspersity and magnetism 
    28582877 
     2878 
    28592879    def updateUndo(self): 
    28602880        """ 
     
    28932913        if self.all_data: 
    28942914            index = self.all_data[self.data_index] 
    2895         else: 
    2896             index = self.theory_item 
    28972915        report_logic = ReportPageLogic(self, 
    28982916                                       kernel_module=self.kernel_module, 
     
    30183036        # first - regular params 
    30193037        param_list = [] 
    3020  
    3021         param_list.append(['model_name', str(self.cbModel.currentText())]) 
    30223038        def gatherParams(row): 
    30233039            """ 
     
    31063122        if lines[0] != 'sasview_parameter_values': 
    31073123            return False 
    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]: 
     3124        for line in lines[1:-1]: 
    31163125            if len(line) != 0: 
    31173126                item = line.split(',') 
     
    31393148                    except IndexError: 
    31403149                        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 
    31533150 
    31543151        self.updateFullModel(context) 
     
    31893186            param_repr = GuiUtils.formatNumber(param_dict[param_name][3+ioffset], high=True) 
    31903187            self._model_model.item(row, 3+ioffset).setText(param_repr) 
    3191             self.setFocus() 
    3192  
    31933188 
    31943189        # block signals temporarily, so we don't end up 
     
    31973192        self.iterateOverModel(updateFittedValues) 
    31983193        self._model_model.blockSignals(False) 
    3199  
    32003194 
    32013195    def updateFullPolyModel(self, param_dict): 
     
    32423236            param_repr = GuiUtils.formatNumber(param_dict[param_name][5+ioffset], high=True) 
    32433237            self._poly_model.item(row, 5+ioffset).setText(param_repr) 
    3244             self.setFocus() 
    32453238 
    32463239        # block signals temporarily, so we don't end up 
     
    32503243        self._poly_model.blockSignals(False) 
    32513244 
     3245 
Note: See TracChangeset for help on using the changeset viewer.