Changes in / [9ba91b7:254199c] in sasview


Ignore:
Location:
src/sas/qtgui
Files:
1 added
3 edited

Legend:

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

    r70f4458 r70f4458  
    88from sas.qtgui.Plotting.PlotterData import Data1D 
    99from sas.qtgui.Plotting.PlotterData import Data2D 
     10 
     11from sas.qtgui.Perspectives.Fitting.AssociatedComboBox import AssociatedComboBox 
    1012 
    1113model_header_captions = ['Parameter', 'Value', 'Min', 'Max', 'Units'] 
     
    6163    return (param_name, param_length) 
    6264 
    63 def addParametersToModel(parameters, kernel_module, is2D): 
    64     """ 
    65     Update local ModelModel with sasmodel parameters 
     65def createFixedChoiceComboBox(param, item_row): 
     66    """ 
     67    Determines whether param is a fixed-choice parameter, modifies items in item_row appropriately and returns a combo 
     68    box containing the fixed choices. Returns None if param is not fixed-choice. 
     69     
     70    item_row is a list of QStandardItem objects for insertion into the parameter table.  
     71    """ 
     72 
     73    # Determine whether this is a fixed-choice parameter. There are lots of conditionals, simply because the 
     74    # implementation is not yet concrete; there are several possible indicators that the parameter is fixed-choice. 
     75    # TODO: (when the sasmodels implementation is concrete, clean this up) 
     76    choices = None 
     77    if isinstance(param.choices, (list, tuple)) and len(param.choices) > 0: 
     78        # The choices property is concrete in sasmodels, probably will use this 
     79        choices = param.choices 
     80    elif isinstance(param.units, (list, tuple)): 
     81        choices = [str(x) for x in param.units] 
     82 
     83    cbox = None 
     84    if choices is not None: 
     85        # Use combo box for input, if it is fixed-choice 
     86        cbox = AssociatedComboBox(item_row[1], idx_as_value=True) 
     87        cbox.addItems(choices) 
     88        item_row[2].setEditable(False) 
     89        item_row[3].setEditable(False) 
     90 
     91    return cbox 
     92 
     93def addParametersToModel(parameters, kernel_module, is2D, model=None, view=None): 
     94    """ 
     95    Update local ModelModel with sasmodel parameters. 
     96    Actually appends to model, if model and view params are not None. 
     97    Always returns list of lists of QStandardItems. 
    6698    """ 
    6799    multishell_parameters = getIterParams(parameters) 
     
    72104    else: 
    73105        params = parameters.iq_parameters 
    74     item = [] 
     106 
     107    rows = [] 
    75108    for param in params: 
    76109        # don't include shell parameters 
    77110        if param.name == multishell_param_name: 
    78111            continue 
     112 
    79113        # Modify parameter name from <param>[n] to <param>1 
    80114        item_name = param.name 
    81115        if param in multishell_parameters: 
    82116            continue 
    83         #    item_name = replaceShellName(param.name, 1) 
    84117 
    85118        item1 = QtGui.QStandardItem(item_name) 
    86119        item1.setCheckable(True) 
    87120        item1.setEditable(False) 
    88         # item_err = QtGui.QStandardItem() 
     121 
    89122        # check for polydisp params 
    90123        if param.polydisperse: 
     
    93126            item1_1 = QtGui.QStandardItem("Distribution") 
    94127            item1_1.setEditable(False) 
     128 
    95129            # Find param in volume_params 
    96130            for p in parameters.form_volume_parameters: 
     
    99133                width = kernel_module.getParam(p.name+'.width') 
    100134                ptype = kernel_module.getParam(p.name+'.type') 
    101  
    102135                item1_2 = QtGui.QStandardItem(str(width)) 
    103136                item1_2.setEditable(False) 
     
    110143                poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
    111144                break 
     145 
    112146            # Add the polydisp item as a child 
    113147            item1.appendRow([poly_item]) 
     148 
    114149        # Param values 
    115150        item2 = QtGui.QStandardItem(str(param.default)) 
    116         # TODO: the error column. 
    117         # Either add a proxy model or a custom view delegate 
    118         #item_err = QtGui.QStandardItem() 
    119151        item3 = QtGui.QStandardItem(str(param.limits[0])) 
    120152        item4 = QtGui.QStandardItem(str(param.limits[1])) 
    121         item5 = QtGui.QStandardItem(param.units) 
     153        item5 = QtGui.QStandardItem(str(param.units)) 
    122154        item5.setEditable(False) 
    123         item.append([item1, item2, item3, item4, item5]) 
    124     return item 
    125  
    126 def addSimpleParametersToModel(parameters, is2D, parameters_original=None): 
    127     """ 
    128     Update local ModelModel with sasmodel parameters 
    129     parameters_original: list of parameters before any tagging on their IDs, e.g. for product model 
    130     (so that those are the display names; see below) 
     155 
     156        # Check if fixed-choice (returns combobox, if so, also makes some items uneditable) 
     157        row = [item1, item2, item3, item4, item5] 
     158        cbox = createFixedChoiceComboBox(param, row) 
     159 
     160        # Append to the model and use the combobox, if required 
     161        if None not in (model, view): 
     162            model.appendRow(row) 
     163            if cbox: 
     164                view.setIndexWidget(item2.index(), cbox) 
     165        rows.append(row) 
     166 
     167    return rows 
     168 
     169def addSimpleParametersToModel(parameters, is2D, parameters_original=None, model=None, view=None): 
     170    """ 
     171    Update local ModelModel with sasmodel parameters (non-dispersed, non-magnetic) 
     172    Actually appends to model, if model and view params are not None. 
     173    Always returns list of lists of QStandardItems. 
     174 
     175    parameters_original: list of parameters before any tagging on their IDs, e.g. for product model (so that those are 
     176    the display names; see below) 
    131177    """ 
    132178    if is2D: 
     
    147193        params_orig = params 
    148194 
    149     item = [] 
     195    rows = [] 
    150196    for param, param_orig in zip(params, params_orig): 
    151197        # Create the top level, checkable item 
     
    155201        item1.setCheckable(True) 
    156202        item1.setEditable(False) 
     203 
    157204        # Param values 
    158205        # TODO: add delegate for validation of cells 
    159206        item2 = QtGui.QStandardItem(str(param.default)) 
    160         item4 = QtGui.QStandardItem(str(param.limits[0])) 
    161         item5 = QtGui.QStandardItem(str(param.limits[1])) 
    162         item6 = QtGui.QStandardItem(str(param.units)) 
    163         item6.setEditable(False) 
    164         item.append([item1, item2, item4, item5, item6]) 
    165     return item 
     207        item3 = QtGui.QStandardItem(str(param.limits[0])) 
     208        item4 = QtGui.QStandardItem(str(param.limits[1])) 
     209        item5 = QtGui.QStandardItem(str(param.units)) 
     210        item5.setEditable(False) 
     211 
     212        # Check if fixed-choice (returns combobox, if so, also makes some items uneditable) 
     213        row = [item1, item2, item3, item4, item5] 
     214        cbox = createFixedChoiceComboBox(param, row) 
     215 
     216        # Append to the model and use the combobox, if required 
     217        if None not in (model, view): 
     218            model.appendRow(row) 
     219            if cbox: 
     220                view.setIndexWidget(item2.index(), cbox) 
     221        rows.append(row) 
     222 
     223    return rows 
    166224 
    167225def markParameterDisabled(model, row): 
     
    259317    model.header_tooltips = copy.copy(poly_header_error_tooltips) 
    260318 
    261 def addShellsToModel(parameters, model, index, row_num=None): 
     319def addShellsToModel(parameters, model, index, row_num=None, view=None): 
    262320    """ 
    263321    Find out multishell parameters and update the model with the requested number of them. 
    264322    Inserts them after the row at row_num, if not None; otherwise, appends to end. 
     323    If view param is not None, supports fixed-choice params. 
    265324    Returns a list of lists of QStandardItem objects. 
    266325    """ 
     
    285344                    item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
    286345                    item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
    287                     item1_5 = QtGui.QStandardItem(p.units) 
     346                    item1_5 = QtGui.QStandardItem(str(p.units)) 
    288347                    poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
    289348                    break 
     
    293352            item3 = QtGui.QStandardItem(str(par.limits[0])) 
    294353            item4 = QtGui.QStandardItem(str(par.limits[1])) 
    295             item5 = QtGui.QStandardItem(par.units) 
     354            item5 = QtGui.QStandardItem(str(par.units)) 
     355            item5.setEditable(False) 
     356 
     357            # Check if fixed-choice (returns combobox, if so, also makes some items uneditable) 
    296358            row = [item1, item2, item3, item4, item5] 
    297             rows.append(row) 
    298  
     359            cbox = createFixedChoiceComboBox(par, row) 
     360 
     361            # Always add to the model 
    299362            if row_num is None: 
    300363                model.appendRow(row) 
     
    302365                model.insertRow(row_num, row) 
    303366                row_num += 1 
     367 
     368            # Apply combobox if required 
     369            if None not in (view, cbox): 
     370                view.setIndexWidget(item2.index(), cbox) 
     371 
     372            rows.append(row) 
    304373 
    305374    return rows 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r0109f2a r5fb714b  
    15071507        # update charts 
    15081508        self.onPlot() 
     1509        #self.recalculatePlotData() 
     1510 
    15091511 
    15101512        # Read only value - we can get away by just printing it here 
     
    15941596            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    15951597            self._model_model.item(row, 1).setText(param_repr) 
     1598            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    15961599            if self.has_error_column: 
    15971600                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
     
    16351638            poly_item.insertColumn(2, [QtGui.QStandardItem("")]) 
    16361639 
    1637         # block signals temporarily, so we don't end up 
    1638         # updating charts with every single model change on the end of fitting 
    1639         self._model_model.blockSignals(True) 
    1640  
    16411640        if not self.has_error_column: 
    16421641            # create top-level error column 
     
    16451644            self.iterateOverModel(createErrorColumn) 
    16461645 
    1647             # we need to enable signals for this, otherwise the final column mysteriously disappears (don't ask, I don't 
    1648             # know) 
    1649             self._model_model.blockSignals(False) 
    16501646            self._model_model.insertColumn(2, error_column) 
    1651             self._model_model.blockSignals(True) 
    16521647 
    16531648            FittingUtilities.addErrorHeadersToModel(self._model_model) 
     
    16581653            self.has_error_column = True 
    16591654 
     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() 
    16601658        self.iterateOverModel(updateFittedValues) 
    16611659        self.iterateOverModel(updatePolyValues) 
    1662  
    1663         self._model_model.blockSignals(False) 
     1660        self._model_model.itemChanged.connect(self.onMainParamsChange) 
    16641661 
    16651662        # Adjust the table cells width. 
     
    16961693            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    16971694            self._poly_model.item(row_i, 1).setText(param_repr) 
     1695            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    16981696            if self.has_poly_error_column: 
    16991697                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
    17001698                self._poly_model.item(row_i, 2).setText(error_repr) 
    1701  
    17021699 
    17031700        def createErrorColumn(row_i): 
     
    17201717        # block signals temporarily, so we don't end up 
    17211718        # updating charts with every single model change on the end of fitting 
    1722         self._poly_model.blockSignals(True) 
     1719        self._poly_model.itemChanged.disconnect() 
    17231720        self.iterateOverPolyModel(updateFittedValues) 
    1724         self._poly_model.blockSignals(False) 
     1721        self._poly_model.itemChanged.connect(self.onPolyModelChange) 
    17251722 
    17261723        if self.has_poly_error_column: 
     
    17321729 
    17331730        # switch off reponse to model change 
    1734         self._poly_model.blockSignals(True) 
    17351731        self._poly_model.insertColumn(2, error_column) 
    1736         self._poly_model.blockSignals(False) 
    17371732        FittingUtilities.addErrorPolyHeadersToModel(self._poly_model) 
    17381733 
     
    17671762            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    17681763            self._magnet_model.item(row, 1).setText(param_repr) 
     1764            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    17691765            if self.has_magnet_error_column: 
    17701766                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
     
    17861782        # block signals temporarily, so we don't end up 
    17871783        # updating charts with every single model change on the end of fitting 
    1788         self._magnet_model.blockSignals(True) 
     1784        self._magnet_model.itemChanged.disconnect() 
    17891785        self.iterateOverMagnetModel(updateFittedValues) 
    1790         self._magnet_model.blockSignals(False) 
     1786        self._magnet_model.itemChanged.connect(self.onMagnetModelChange) 
    17911787 
    17921788        if self.has_magnet_error_column: 
     
    17981794 
    17991795        # switch off reponse to model change 
    1800         self._magnet_model.blockSignals(True) 
    18011796        self._magnet_model.insertColumn(2, error_column) 
    1802         self._magnet_model.blockSignals(False) 
    18031797        FittingUtilities.addErrorHeadersToModel(self._magnet_model) 
    18041798 
     
    18121806        self.cmdPlot.setText("Show Plot") 
    18131807        # Force data recalculation so existing charts are updated 
     1808        self.showPlot() 
    18141809        self.recalculatePlotData() 
    1815         self.showPlot() 
    18161810 
    18171811    def onSmearingOptionsUpdate(self): 
     
    20792073        self.shell_names = self.shellNamesList() 
    20802074 
    2081         # Get new rows for QModel 
    2082         new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 
    2083  
    20842075        # Add heading row 
    20852076        FittingUtilities.addHeadingRowToModel(self._model_model, model_name) 
    20862077 
    2087         # Update QModel 
    2088         for row in new_rows: 
    2089             self._model_model.appendRow(row) 
     2078        # Update the QModel 
     2079        FittingUtilities.addParametersToModel( 
     2080                self.model_parameters, 
     2081                self.kernel_module, 
     2082                self.is2D, 
     2083                self._model_model, 
     2084                self.lstParams) 
    20902085 
    20912086    def fromStructureFactorToQModel(self, structure_factor): 
     
    20962091            return 
    20972092 
    2098         s_kernel = self.models[structure_factor]() 
    2099         p_kernel = self.kernel_module 
    2100  
    2101         if p_kernel is None: 
    2102             # Not a product model, just S(Q) 
    2103             self.kernel_module = s_kernel 
    2104             params = modelinfo.ParameterTable(self.kernel_module._model_info.parameters.kernel_parameters) 
    2105             new_rows = FittingUtilities.addSimpleParametersToModel(params, self.is2D) 
     2093        if self.kernel_module is None: 
     2094            # Structure factor is the only selected model; build it and show all its params 
     2095            self.kernel_module = self.models[structure_factor]() 
     2096            s_params = self.kernel_module._model_info.parameters 
     2097            s_params_orig = s_params 
     2098 
    21062099        else: 
     2100            s_kernel = self.models[structure_factor]() 
     2101            p_kernel = self.kernel_module 
     2102 
    21072103            p_pars_len = len(p_kernel._model_info.parameters.kernel_parameters) 
    21082104            s_pars_len = len(s_kernel._model_info.parameters.kernel_parameters) 
     
    21132109 
    21142110            # S(Q) params from the product model are not necessarily the same as those from the S(Q) model; any 
    2115             # conflicting names with P(Q) params will cause a rename; we also lose radius_effective (for now...) 
    2116  
    2117             # TODO: merge rest of beta approx implementation in 
    2118             # This is to ensure compatibility when we merge beta approx support in...! 
    2119  
    2120             # radius_effective is always s_params[0] 
    2121  
    2122             # if radius_effective_mode is in all_params, then all_params contains radius_effective and we want to 
    2123             # keep it in the model 
    2124  
    2125             # if radius_effective_mode is NOT in all_params, then radius_effective should NOT be kept, because the user 
    2126             # cannot specify it themselves; but, make sure we only remove it if it's actually there in the first place 
    2127             # (sasmodels master removes it already) 
     2111            # conflicting names with P(Q) params will cause a rename 
     2112 
    21282113            if "radius_effective_mode" in all_param_names: 
    21292114                # Show all parameters 
     
    21382123                    s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len-1]) 
    21392124 
    2140             # Get new rows for QModel 
    2141             # Any renamed parameters are stored as data in the relevant item, for later handling 
    2142             new_rows = FittingUtilities.addSimpleParametersToModel(s_params, self.is2D, s_params_orig) 
    2143  
    2144             # TODO: merge rest of beta approx implementation in 
    2145             # These parameters are not part of P(Q) nor S(Q), but are added only to the product model (e.g. specifying 
    2146             # structure factor calculation mode) 
    2147             # product_params = all_params[p_pars_len+s_pars_len:] 
    2148  
    21492125        # Add heading row 
    21502126        FittingUtilities.addHeadingRowToModel(self._model_model, structure_factor) 
    21512127 
    2152         # Update QModel 
    2153         for row in new_rows: 
    2154             self._model_model.appendRow(row) 
    2155             # disable fitting of parameters not listed in self.kernel_module (probably radius_effective) 
    2156             # if row[0].text() not in self.kernel_module.params.keys(): 
    2157             #     row_num = self._model_model.rowCount() - 1 
    2158             #     FittingUtilities.markParameterDisabled(self._model_model, row_num) 
     2128        # Get new rows for QModel 
     2129        # Any renamed parameters are stored as data in the relevant item, for later handling 
     2130        FittingUtilities.addSimpleParametersToModel( 
     2131                s_params, 
     2132                self.is2D, 
     2133                s_params_orig, 
     2134                self._model_model, 
     2135                self.lstParams) 
    21592136 
    21602137    def haveParamsToFit(self): 
     
    28132790            self._model_model.removeRows(first_row, remove_rows) 
    28142791 
    2815         new_rows = FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index, first_row) 
     2792        new_rows = FittingUtilities.addShellsToModel( 
     2793                self.model_parameters, 
     2794                self._model_model, 
     2795                index, 
     2796                first_row, 
     2797                self.lstParams) 
     2798 
    28162799        self._num_shell_params = len(new_rows) 
    2817  
    28182800        self.current_shell_displayed = index 
    28192801 
  • src/sas/qtgui/Plotting/Plotter.py

    rb764ae5 rc2f3ca2  
    3030        # Dictionary of {plot_id:Data1d} 
    3131        self.plot_dict = {} 
    32  
     32        # Dictionaty of {plot_id:line} 
     33 
     34        self.plot_lines = {} 
    3335        # Window for text add 
    3436        self.addText = AddText(self) 
     
    182184        self.plot_dict[self._data.id] = self.data 
    183185 
     186        self.plot_lines[self._data.id] = line 
     187 
    184188        # Now add the legend with some customizations. 
    185189 
     
    196200 
    197201        # refresh canvas 
    198         self.canvas.draw_idle() 
     202        self.canvas.draw() 
    199203        # This is an important processEvent. 
    200204        # This allows charts to be properly updated in order 
     
    416420        This effectlvely refreshes the chart with changes to one of its plots 
    417421        """ 
     422        import logging 
    418423        self.removePlot(id) 
    419424        self.plot(data=new_plot) 
     
    470475        """ 
    471476        selected_plot = self.plot_dict[id] 
    472  
     477        selected_line = self.plot_lines[id] 
    473478        # Old style color - single integer for enum color 
    474479        # New style color - #hhhhhh 
Note: See TracChangeset for help on using the changeset viewer.