Ignore:
Timestamp:
Sep 7, 2018 10:53:02 AM (6 years ago)
Author:
Torin Cooper-Bennun <torin.cooper-bennun@…>
Branches:
ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
Children:
c0de493
Parents:
8136e09 (diff), f0365a2e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'ESS_GUI' into ESS_GUI_iss1034

File:
1 edited

Legend:

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

    r8136e09 r01b4877  
    9191    fittingFinishedSignal = QtCore.pyqtSignal(tuple) 
    9292    batchFittingFinishedSignal = QtCore.pyqtSignal(tuple) 
    93     Calc1DFinishedSignal = QtCore.pyqtSignal(tuple) 
    94     Calc2DFinishedSignal = QtCore.pyqtSignal(tuple) 
     93    Calc1DFinishedSignal = QtCore.pyqtSignal(dict) 
     94    Calc2DFinishedSignal = QtCore.pyqtSignal(dict) 
    9595 
    9696    def __init__(self, parent=None, data=None, tab_id=1): 
     
    219219        # Utility variable to enable unselectable option in category combobox 
    220220        self._previous_category_index = 0 
    221         # Utility variable for multishell display 
    222         self._last_model_row = 0 
     221        # Utility variables for multishell display 
     222        self._n_shells_row = 0 
     223        self._num_shell_params = 0 
    223224        # Dictionary of {model name: model class} for the current category 
    224225        self.models = {} 
     
    676677        Return list of all parameters for the current model 
    677678        """ 
    678         return [self._model_model.item(row).text() for row in range(self._model_model.rowCount())] 
     679        return [self._model_model.item(row).text() 
     680                for row in range(self._model_model.rowCount()) 
     681                if self.isCheckable(row)] 
    679682 
    680683    def modifyViewOnRow(self, row, font=None, brush=None): 
     
    704707        assert isinstance(constraint, Constraint) 
    705708        assert 0 <= row <= self._model_model.rowCount() 
     709        assert self.isCheckable(row) 
    706710 
    707711        item = QtGui.QStandardItem() 
     
    724728        max_col = self.lstParams.itemDelegate().param_max 
    725729        for row in self.selectedParameters(): 
     730            assert(self.isCheckable(row)) 
    726731            param = self._model_model.item(row, 0).text() 
    727732            value = self._model_model.item(row, 1).text() 
     
    766771        max_col = self.lstParams.itemDelegate().param_max 
    767772        for row in range(self._model_model.rowCount()): 
     773            if not self.isCheckable(row): 
     774                continue 
    768775            if not self.rowHasConstraint(row): 
    769776                continue 
     
    794801        For the given row, return its constraint, if any 
    795802        """ 
    796         try: 
     803        if self.isCheckable(row): 
    797804            item = self._model_model.item(row, 1) 
    798             return item.child(0).data() 
    799         except AttributeError: 
    800             # return none when no constraints 
    801             return None 
     805            try: 
     806                return item.child(0).data() 
     807            except AttributeError: 
     808                # return none when no constraints 
     809                pass 
     810        return None 
    802811 
    803812    def rowHasConstraint(self, row): 
     
    805814        Finds out if row of the main model has a constraint child 
    806815        """ 
    807         item = self._model_model.item(row, 1) 
    808         if item.hasChildren(): 
    809             c = item.child(0).data() 
    810             if isinstance(c, Constraint): 
    811                 return True 
     816        if self.isCheckable(row): 
     817            item = self._model_model.item(row, 1) 
     818            if item.hasChildren(): 
     819                c = item.child(0).data() 
     820                if isinstance(c, Constraint): 
     821                    return True 
    812822        return False 
    813823 
     
    816826        Finds out if row of the main model has an active constraint child 
    817827        """ 
    818         item = self._model_model.item(row, 1) 
    819         if item.hasChildren(): 
    820             c = item.child(0).data() 
    821             if isinstance(c, Constraint) and c.active: 
    822                 return True 
     828        if self.isCheckable(row): 
     829            item = self._model_model.item(row, 1) 
     830            if item.hasChildren(): 
     831                c = item.child(0).data() 
     832                if isinstance(c, Constraint) and c.active: 
     833                    return True 
    823834        return False 
    824835 
     
    827838        Finds out if row of the main model has an active, nontrivial constraint child 
    828839        """ 
    829         item = self._model_model.item(row, 1) 
    830         if item.hasChildren(): 
    831             c = item.child(0).data() 
    832             if isinstance(c, Constraint) and c.func and c.active: 
    833                 return True 
     840        if self.isCheckable(row): 
     841            item = self._model_model.item(row, 1) 
     842            if item.hasChildren(): 
     843                c = item.child(0).data() 
     844                if isinstance(c, Constraint) and c.func and c.active: 
     845                    return True 
    834846        return False 
    835847 
     
    14951507        # update charts 
    14961508        self.onPlot() 
     1509        #self.recalculatePlotData() 
     1510 
    14971511 
    14981512        # Read only value - we can get away by just printing it here 
     
    15771591            # internal so can use closure for param_dict 
    15781592            param_name = str(self._model_model.item(row, 0).text()) 
    1579             if param_name not in list(param_dict.keys()): 
     1593            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15801594                return 
    15811595            # modify the param value 
    15821596            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    15831597            self._model_model.item(row, 1).setText(param_repr) 
     1598            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    15841599            if self.has_error_column: 
    15851600                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
     
    15891604            # Utility function for updateof polydispersity part of the main model 
    15901605            param_name = str(self._model_model.item(row, 0).text())+'.width' 
    1591             if param_name not in list(param_dict.keys()): 
     1606            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15921607                return 
    15931608            # modify the param value 
     
    16231638            poly_item.insertColumn(2, [QtGui.QStandardItem("")]) 
    16241639 
    1625         # block signals temporarily, so we don't end up 
    1626         # updating charts with every single model change on the end of fitting 
    1627         self._model_model.blockSignals(True) 
    1628  
    16291640        if not self.has_error_column: 
    16301641            # create top-level error column 
     
    16331644            self.iterateOverModel(createErrorColumn) 
    16341645 
    1635             # we need to enable signals for this, otherwise the final column mysteriously disappears (don't ask, I don't 
    1636             # know) 
    1637             self._model_model.blockSignals(False) 
    16381646            self._model_model.insertColumn(2, error_column) 
    1639             self._model_model.blockSignals(True) 
    16401647 
    16411648            FittingUtilities.addErrorHeadersToModel(self._model_model) 
     
    16461653            self.has_error_column = True 
    16471654 
     1655        # block signals temporarily, so we don't end up 
     1656        # updating charts with every single model change on the end of fitting 
     1657        self._model_model.itemChanged.disconnect() 
    16481658        self.iterateOverModel(updateFittedValues) 
    16491659        self.iterateOverModel(updatePolyValues) 
    1650  
    1651         self._model_model.blockSignals(False) 
     1660        self._model_model.itemChanged.connect(self.onMainParamsChange) 
    16521661 
    16531662        # Adjust the table cells width. 
     
    16841693            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    16851694            self._poly_model.item(row_i, 1).setText(param_repr) 
     1695            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    16861696            if self.has_poly_error_column: 
    16871697                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
    16881698                self._poly_model.item(row_i, 2).setText(error_repr) 
    1689  
    16901699 
    16911700        def createErrorColumn(row_i): 
     
    17081717        # block signals temporarily, so we don't end up 
    17091718        # updating charts with every single model change on the end of fitting 
    1710         self._poly_model.blockSignals(True) 
     1719        self._poly_model.itemChanged.disconnect() 
    17111720        self.iterateOverPolyModel(updateFittedValues) 
    1712         self._poly_model.blockSignals(False) 
     1721        self._poly_model.itemChanged.connect(self.onPolyModelChange) 
    17131722 
    17141723        if self.has_poly_error_column: 
     
    17201729 
    17211730        # switch off reponse to model change 
    1722         self._poly_model.blockSignals(True) 
    17231731        self._poly_model.insertColumn(2, error_column) 
    1724         self._poly_model.blockSignals(False) 
    17251732        FittingUtilities.addErrorPolyHeadersToModel(self._poly_model) 
    17261733 
     
    17551762            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    17561763            self._magnet_model.item(row, 1).setText(param_repr) 
     1764            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    17571765            if self.has_magnet_error_column: 
    17581766                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
     
    17741782        # block signals temporarily, so we don't end up 
    17751783        # updating charts with every single model change on the end of fitting 
    1776         self._magnet_model.blockSignals(True) 
     1784        self._magnet_model.itemChanged.disconnect() 
    17771785        self.iterateOverMagnetModel(updateFittedValues) 
    1778         self._magnet_model.blockSignals(False) 
     1786        self._magnet_model.itemChanged.connect(self.onMagnetModelChange) 
    17791787 
    17801788        if self.has_magnet_error_column: 
     
    17861794 
    17871795        # switch off reponse to model change 
    1788         self._magnet_model.blockSignals(True) 
    17891796        self._magnet_model.insertColumn(2, error_column) 
    1790         self._magnet_model.blockSignals(False) 
    17911797        FittingUtilities.addErrorHeadersToModel(self._magnet_model) 
    17921798 
     
    18001806        self.cmdPlot.setText("Show Plot") 
    18011807        # Force data recalculation so existing charts are updated 
     1808        self.showPlot() 
    18021809        self.recalculatePlotData() 
    1803         self.showPlot() 
    18041810 
    18051811    def onSmearingOptionsUpdate(self): 
     
    19661972        # Crete/overwrite model items 
    19671973        self._model_model.clear() 
    1968  
    1969         # First, add parameters from the main model 
    1970         if model_name is not None: 
     1974        self._poly_model.clear() 
     1975        self._magnet_model.clear() 
     1976 
     1977        if model_name is None: 
     1978            if structure_factor not in (None, "None"): 
     1979                # S(Q) on its own, treat the same as a form factor 
     1980                self.kernel_module = None 
     1981                self.fromStructureFactorToQModel(structure_factor) 
     1982            else: 
     1983                # No models selected 
     1984                return 
     1985        else: 
    19711986            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: 
     1987            self.addExtraShells() 
     1988 
    19801989            # Allow the SF combobox visibility for the given sasmodel 
    19811990            self.enableStructureFactorControl(structure_factor) 
     1991         
     1992            # Add S(Q) 
    19821993            if self.cbStructureFactor.isEnabled(): 
    19831994                structure_factor = self.cbStructureFactor.currentText() 
    19841995                self.fromStructureFactorToQModel(structure_factor) 
    19851996 
    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() 
     1997            # Add polydispersity to the model 
     1998            self.poly_params = {} 
     1999            self.setPolyModel() 
     2000            # Add magnetic parameters to the model 
     2001            self.magnet_params = {} 
     2002            self.setMagneticModel() 
    19972003 
    19982004        # Adjust the table cells width 
     
    20672073        self.shell_names = self.shellNamesList() 
    20682074 
     2075        # Add heading row 
     2076        FittingUtilities.addHeadingRowToModel(self._model_model, model_name) 
     2077 
    20692078        # Update the QModel 
    2070         new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 
    2071  
    2072         for row in new_rows: 
    2073             self._model_model.appendRow(row) 
    2074         # Update the counter used for multishell display 
    2075         self._last_model_row = self._model_model.rowCount() 
     2079        FittingUtilities.addParametersToModel( 
     2080                self.model_parameters, 
     2081                self.kernel_module, 
     2082                self.is2D, 
     2083                self._model_model, 
     2084                self.lstParams) 
    20762085 
    20772086    def fromStructureFactorToQModel(self, structure_factor): 
     
    20812090        if structure_factor is None or structure_factor=="None": 
    20822091            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) 
    2092         for row in new_rows: 
    2093             self._model_model.appendRow(row) 
    2094             # 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         # grab list of params injected by sasmodels.product 
    2100         # (only supporting sasmodels master until ESS_GUI merge!!!) 
    2101         num_p_params = len(form_kernel._model_info.parameters.kernel_parameters) 
    2102         num_s_params = len(structure_kernel._model_info.parameters.kernel_parameters) 
    2103         product_params = modelinfo.ParameterTable( 
    2104                 self.kernel_module._model_info.parameters.kernel_parameters[num_p_params+num_s_params-1:]) 
    2105         product_rows = FittingUtilities.addSimpleParametersToModel(product_params, self.is2D) 
    2106  
    2107         # product params should go at the top of the list, below scale & background 
    2108         row_num = 2 
    2109         for row in product_rows: 
    2110             self._model_model.insertRow(row_num, row) 
    2111             row_num += 1 
    2112  
    2113         # Update the counter used for multishell display 
    2114         self._last_model_row = self._model_model.rowCount() 
     2092 
     2093        product_params = None 
     2094 
     2095        if self.kernel_module is None: 
     2096            # Structure factor is the only selected model; build it and show all its params 
     2097            self.kernel_module = self.models[structure_factor]() 
     2098            s_params = self.kernel_module._model_info.parameters 
     2099            s_params_orig = s_params 
     2100        else: 
     2101            s_kernel = self.models[structure_factor]() 
     2102            p_kernel = self.kernel_module 
     2103 
     2104            p_pars_len = len(p_kernel._model_info.parameters.kernel_parameters) 
     2105            s_pars_len = len(s_kernel._model_info.parameters.kernel_parameters) 
     2106 
     2107            self.kernel_module = MultiplicationModel(p_kernel, s_kernel) 
     2108            all_params = self.kernel_module._model_info.parameters.kernel_parameters 
     2109            all_param_names = [param.name for param in all_params] 
     2110 
     2111            # S(Q) params from the product model are not necessarily the same as those from the S(Q) model; any 
     2112            # conflicting names with P(Q) params will cause a rename 
     2113 
     2114            if "radius_effective_mode" in all_param_names: 
     2115                # Show all parameters 
     2116                # In this case, radius_effective is NOT pruned by sasmodels.product 
     2117                s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len]) 
     2118                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters) 
     2119                product_params = modelinfo.ParameterTable( 
     2120                        self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len:]) 
     2121            else: 
     2122                # Ensure radius_effective is not displayed 
     2123                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters[1:]) 
     2124                if "radius_effective" in all_param_names: 
     2125                    # In this case, radius_effective is NOT pruned by sasmodels.product 
     2126                    s_params = modelinfo.ParameterTable(all_params[p_pars_len+1:p_pars_len+s_pars_len]) 
     2127                    product_params = modelinfo.ParameterTable( 
     2128                            self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len:]) 
     2129                else: 
     2130                    # In this case, radius_effective is pruned by sasmodels.product 
     2131                    s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len-1]) 
     2132                    product_params = modelinfo.ParameterTable( 
     2133                            self.kernel_module._model_info.parameters.kernel_parameters[p_pars_len+s_pars_len-1:]) 
     2134 
     2135        # Add heading row 
     2136        FittingUtilities.addHeadingRowToModel(self._model_model, structure_factor) 
     2137 
     2138        # Get new rows for QModel 
     2139        # Any renamed parameters are stored as data in the relevant item, for later handling 
     2140        FittingUtilities.addSimpleParametersToModel( 
     2141                parameters=s_params, 
     2142                is2D=self.is2D, 
     2143                parameters_original=s_params_orig, 
     2144                model=self._model_model, 
     2145                view=self.lstParams) 
     2146 
     2147        # Insert product-only params into QModel 
     2148        if product_params: 
     2149            prod_rows = FittingUtilities.addSimpleParametersToModel( 
     2150                    parameters=product_params, 
     2151                    is2D=self.is2D, 
     2152                    parameters_original=None, 
     2153                    model=self._model_model, 
     2154                    view=self.lstParams, 
     2155                    row_num=2) 
     2156 
     2157            # Since this all happens after shells are dealt with and we've inserted rows, fix this counter 
     2158            self._n_shells_row += len(prod_rows) 
    21152159 
    21162160    def haveParamsToFit(self): 
     
    21382182        model_row = item.row() 
    21392183        name_index = self._model_model.index(model_row, 0) 
     2184        name_item = self._model_model.itemFromIndex(name_index) 
    21402185 
    21412186        # Extract changed value. 
     
    21462191            return 
    21472192 
    2148         parameter_name = str(self._model_model.data(name_index)) # sld, background etc. 
     2193        # if the item has user data, this is the actual parameter name (e.g. to handle duplicate names) 
     2194        if name_item.data(QtCore.Qt.UserRole): 
     2195            parameter_name = str(name_item.data(QtCore.Qt.UserRole)) 
     2196        else: 
     2197            parameter_name = str(self._model_model.data(name_index)) 
    21492198 
    21502199        # Update the parameter value - note: this supports +/-inf as well 
     
    23802429            new_plots.append(sq_data) 
    23812430 
    2382         # Update/generate plots 
    23832431        for plot in new_plots: 
    23842432            self.communicate.plotUpdateSignal.emit([plot]) 
     
    25802628        def updateFunctionCaption(row): 
    25812629            # Utility function for update of polydispersity function name in the main model 
     2630            if not self.isCheckable(row): 
     2631                return 
    25822632            self._model_model.blockSignals(True) 
    25832633            param_name = str(self._model_model.item(row, 0).text()) 
     
    27522802 
    27532803        self.lstParams.setIndexWidget(shell_index, func) 
    2754         self._last_model_row = self._model_model.rowCount() 
     2804        self._n_shells_row = shell_row - 1 
    27552805 
    27562806        # Set the index to the state-kept value 
     
    27632813        """ 
    27642814        # Find row location of the combobox 
    2765         last_row = self._last_model_row 
    2766         remove_rows = self._model_model.rowCount() - last_row 
     2815        first_row = self._n_shells_row + 1 
     2816        remove_rows = self._num_shell_params 
    27672817 
    27682818        if remove_rows > 1: 
    2769             self._model_model.removeRows(last_row, remove_rows) 
    2770  
    2771         FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index) 
     2819            self._model_model.removeRows(first_row, remove_rows) 
     2820 
     2821        new_rows = FittingUtilities.addShellsToModel( 
     2822                self.model_parameters, 
     2823                self._model_model, 
     2824                index, 
     2825                first_row, 
     2826                self.lstParams) 
     2827 
     2828        self._num_shell_params = len(new_rows) 
    27722829        self.current_shell_displayed = index 
    27732830 
Note: See TracChangeset for help on using the changeset viewer.