Changeset 01b4877 in sasview for src/sas


Ignore:
Timestamp:
Sep 7, 2018 8: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

Location:
src/sas/qtgui
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/MainWindow/DataExplorer.py

    rfd7ef36 r60d55a7  
    560560        # Now query the model item for available plots 
    561561        plots = GuiUtils.plotsFromFilename(filename, model) 
    562         ids_keys = list(self.active_plots.keys()) 
    563         ids_vals = [val.data.id for val in self.active_plots.values()] 
    564562 
    565563        new_plots = [] 
    566564        for item, plot in plots.items(): 
    567             plot_id = plot.id 
    568             if plot_id in ids_keys: 
    569                 self.active_plots[plot_id].replacePlot(plot_id, plot) 
    570             elif plot_id in ids_vals: 
    571                 list(self.active_plots.values())[ids_vals.index(plot_id)].replacePlot(plot_id, plot) 
    572             else: 
     565            if not self.updatePlot(plot): 
    573566                # Don't plot intermediate results, e.g. P(Q), S(Q) 
    574                 match = GuiUtils.theory_plot_ID_pattern.match(plot_id) 
     567                match = GuiUtils.theory_plot_ID_pattern.match(plot.id) 
    575568                # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 
    576569                if match and match.groups()[1] != None: 
     
    706699                self.active_plots[plot_set.id] = old_plot 
    707700 
    708     def updatePlot(self, new_data): 
    709         """ 
    710         Modify existing plot for immediate response 
    711         """ 
    712         data = new_data[0] 
     701    def updatePlot(self, data): 
     702        """ 
     703        Modify existing plot for immediate response and returns True. 
     704        Returns false, if the plot does not exist already. 
     705        """ 
     706        try: # there might be a list or a single value being passed 
     707            data = data[0] 
     708        except TypeError: 
     709            pass 
    713710        assert type(data).__name__ in ['Data1D', 'Data2D'] 
    714711 
     
    719716        if data_id in ids_keys: 
    720717            self.active_plots[data_id].replacePlot(data_id, data) 
     718            return True 
    721719        elif data_id in ids_vals: 
    722720            list(self.active_plots.values())[ids_vals.index(data_id)].replacePlot(data_id, data) 
     721            return True 
     722        return False 
    723723 
    724724    def chooseFiles(self): 
  • src/sas/qtgui/Perspectives/Fitting/FittingLogic.py

    rb4d05bd rdcabba7  
    161161        Create a new 1D data instance based on fitting results 
    162162        """ 
    163         # Unpack return data from Calc1D 
    164         x, y, page_id, state, weight,\ 
    165         fid, toggle_mode_on, \ 
    166         elapsed, index, model, \ 
    167         data, update_chisqr, source, \ 
    168         unsmeared_output, unsmeared_data, unsmeared_error, \ 
    169         pq_values, sq_values = return_data 
    170  
    171         return self._create1DPlot(tab_id, x, y, model, data) 
     163 
     164        return self._create1DPlot(tab_id, return_data['x'], return_data['y'], 
     165                                  return_data['model'], return_data['data']) 
    172166 
    173167    def new2DPlot(self, return_data): 
     
    175169        Create a new 2D data instance based on fitting results 
    176170        """ 
    177         image, data, page_id, model, state, toggle_mode_on,\ 
    178         elapsed, index, fid, qmin, qmax, weight, \ 
    179         update_chisqr, source = return_data 
     171        image = return_data['image'] 
     172        data = return_data['data'] 
     173        model = return_data['model'] 
    180174 
    181175        np.nan_to_num(image) 
     
    183177        new_plot.name = model.name + '2d' 
    184178        new_plot.title = "Analytical model 2D " 
    185         new_plot.id = str(page_id) + " " + data.name 
    186         new_plot.group_id = str(page_id) + " Model2D" 
     179        new_plot.id = str(return_data['page_id']) + " " + data.name 
     180        new_plot.group_id = str(return_data['page_id']) + " Model2D" 
    187181        new_plot.detector = data.detector 
    188182        new_plot.source = data.source 
     
    218212        (pq_plot, sq_plot). If either are unavailable, the corresponding plot is None. 
    219213        """ 
    220         # Unpack return data from Calc1D 
    221         x, y, page_id, state, weight, \ 
    222         fid, toggle_mode_on, \ 
    223         elapsed, index, model, \ 
    224         data, update_chisqr, source, \ 
    225         unsmeared_output, unsmeared_data, unsmeared_error, \ 
    226         pq_values, sq_values = return_data 
    227214 
    228215        pq_plot = None 
    229216        sq_plot = None 
    230217 
    231         if pq_values is not None: 
    232             pq_plot = self._create1DPlot(tab_id, x, pq_values, model, data, component="P(Q)") 
    233         if sq_values is not None: 
    234             sq_plot = self._create1DPlot(tab_id, x, sq_values, model, data, component="S(Q)") 
     218        if return_data.get('pq_values', None) is not None: 
     219            pq_plot = self._create1DPlot(tab_id, return_data['x'], 
     220                    return_data['pq_values'], return_data['model'], 
     221                    return_data['data'], component="P(Q)") 
     222        if return_data.get('sq_values', None) is not None: 
     223            sq_plot = self._create1DPlot(tab_id, return_data['x'], 
     224                    return_data['sq_values'], return_data['model'], 
     225                    return_data['data'], component="S(Q)") 
    235226 
    236227        return pq_plot, sq_plot 
  • src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py

    rb764ae5 r01b4877  
    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): 
    127     """ 
    128     Update local ModelModel with sasmodel parameters 
     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, row_num=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) 
    129177    """ 
    130178    if is2D: 
     
    132180    else: 
    133181        params = parameters.iq_parameters 
    134     item = [] 
    135     for param in params: 
     182 
     183    if parameters_original: 
     184        # 'parameters_original' contains the parameters as they are to be DISPLAYED, while 'parameters' 
     185        # contains the parameters as they were renamed; this is for handling name collisions in product model. 
     186        # The 'real name' of the parameter will be stored in the item's user data. 
     187        if is2D: 
     188            params_orig = [p for p in parameters_original.kernel_parameters if p.type != 'magnetic'] 
     189        else: 
     190            params_orig = parameters_original.iq_parameters 
     191    else: 
     192        # no difference in names anyway 
     193        params_orig = params 
     194 
     195    rows = [] 
     196    for param, param_orig in zip(params, params_orig): 
    136197        # Create the top level, checkable item 
    137         item_name = param.name 
     198        item_name = param_orig.name 
    138199        item1 = QtGui.QStandardItem(item_name) 
     200        item1.setData(param.name, QtCore.Qt.UserRole) 
    139201        item1.setCheckable(True) 
    140202        item1.setEditable(False) 
     203 
    141204        # Param values 
    142205        # TODO: add delegate for validation of cells 
    143206        item2 = QtGui.QStandardItem(str(param.default)) 
    144         item4 = QtGui.QStandardItem(str(param.limits[0])) 
    145         item5 = QtGui.QStandardItem(str(param.limits[1])) 
    146         item6 = QtGui.QStandardItem(param.units) 
    147         item6.setEditable(False) 
    148         item.append([item1, item2, item4, item5, item6]) 
    149     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            if row_num is None: 
     219                model.appendRow(row) 
     220            else: 
     221                model.insertRow(row_num, row) 
     222                row_num += 1 
     223 
     224            if cbox: 
     225                view.setIndexWidget(item2.index(), cbox) 
     226 
     227        rows.append(row) 
     228 
     229    return rows 
    150230 
    151231def markParameterDisabled(model, row): 
     
    182262    model.appendRow(item_list) 
    183263 
     264def addHeadingRowToModel(model, name): 
     265    """adds a non-interactive top-level row to the model""" 
     266    header_row = [QtGui.QStandardItem() for i in range(5)] 
     267    header_row[0].setText(name) 
     268 
     269    font = header_row[0].font() 
     270    font.setBold(True) 
     271    header_row[0].setFont(font) 
     272 
     273    for item in header_row: 
     274        item.setEditable(False) 
     275        item.setCheckable(False) 
     276        item.setSelectable(False) 
     277 
     278    model.appendRow(header_row) 
     279 
    184280def addHeadersToModel(model): 
    185281    """ 
     
    227323    model.header_tooltips = copy.copy(poly_header_error_tooltips) 
    228324 
    229 def addShellsToModel(parameters, model, index): 
    230     """ 
    231     Find out multishell parameters and update the model with the requested number of them 
     325def addShellsToModel(parameters, model, index, row_num=None, view=None): 
     326    """ 
     327    Find out multishell parameters and update the model with the requested number of them. 
     328    Inserts them after the row at row_num, if not None; otherwise, appends to end. 
     329    If view param is not None, supports fixed-choice params. 
     330    Returns a list of lists of QStandardItem objects. 
    232331    """ 
    233332    multishell_parameters = getIterParams(parameters) 
    234333 
     334    rows = [] 
    235335    for i in range(index): 
    236336        for par in multishell_parameters: 
     
    250350                    item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
    251351                    item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
    252                     item1_5 = QtGui.QStandardItem(p.units) 
     352                    item1_5 = QtGui.QStandardItem(str(p.units)) 
    253353                    poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
    254354                    break 
     
    258358            item3 = QtGui.QStandardItem(str(par.limits[0])) 
    259359            item4 = QtGui.QStandardItem(str(par.limits[1])) 
    260             item5 = QtGui.QStandardItem(par.units) 
    261             model.appendRow([item1, item2, item3, item4, item5]) 
     360            item5 = QtGui.QStandardItem(str(par.units)) 
     361            item5.setEditable(False) 
     362 
     363            # Check if fixed-choice (returns combobox, if so, also makes some items uneditable) 
     364            row = [item1, item2, item3, item4, item5] 
     365            cbox = createFixedChoiceComboBox(par, row) 
     366 
     367            # Always add to the model 
     368            if row_num is None: 
     369                model.appendRow(row) 
     370            else: 
     371                model.insertRow(row_num, row) 
     372                row_num += 1 
     373 
     374            # Apply combobox if required 
     375            if None not in (view, cbox): 
     376                view.setIndexWidget(item2.index(), cbox) 
     377 
     378            rows.append(row) 
     379 
     380    return rows 
    262381 
    263382def calculateChi2(reference_data, current_data): 
  • 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 
  • src/sas/qtgui/Perspectives/Fitting/ModelThread.py

    r2df558e rdcabba7  
    101101        elapsed = time.time() - self.starttime 
    102102 
     103        res = dict(image = output, data = self.data, page_id = self.page_id, 
     104            model = self.model, state = self.state, 
     105            toggle_mode_on = self.toggle_mode_on, elapsed = elapsed, 
     106            index = index_model, fid = self.fid, 
     107            qmin = self.qmin, qmax = self.qmax, 
     108            weight = self.weight, update_chisqr = self.update_chisqr, 
     109            source = self.source) 
     110 
    103111        if LocalConfig.USING_TWISTED: 
    104             return (output, 
    105                     self.data, 
    106                     self.page_id, 
    107                     self.model, 
    108                     self.state, 
    109                     self.toggle_mode_on, 
    110                     elapsed, 
    111                     index_model, 
    112                     self.fid, 
    113                     self.qmin, 
    114                     self.qmax, 
    115                     self.weight, 
    116                     self.update_chisqr, 
    117                     self.source) 
    118         else: 
    119             self.completefn((output, 
    120                            self.data, 
    121                            self.page_id, 
    122                            self.model, 
    123                            self.state, 
    124                            self.toggle_mode_on, 
    125                            elapsed, 
    126                            index_model, 
    127                            self.fid, 
    128                            self.qmin, 
    129                            self.qmax, 
    130                            self.weight, 
    131                            #qstep=self.qstep, 
    132                            self.update_chisqr, 
    133                            self.source)) 
    134  
     112            return res 
     113        else: 
     114            self.completefn(res) 
    135115 
    136116class Calc1D(CalcThread): 
     
    236216        elapsed = time.time() - self.starttime 
    237217 
     218        res = dict(x = self.data.x[index], y = output[index], 
     219            page_id = self.page_id, state = self.state, weight = self.weight, 
     220            fid = self.fid, toggle_mode_on = self.toggle_mode_on, 
     221            elapsed = elapsed, index = index, model = self.model, 
     222            data = self.data, update_chisqr = self.update_chisqr, 
     223            source = self.source, unsmeared_output = unsmeared_output, 
     224            unsmeared_data = unsmeared_data, unsmeared_error = unsmeared_error, 
     225            pq_values = pq_values, sq_values = sq_values) 
     226 
    238227        if LocalConfig.USING_TWISTED: 
    239             return (self.data.x[index], output[index], 
    240                     self.page_id, 
    241                     self.state, 
    242                     self.weight, 
    243                     self.fid, 
    244                     self.toggle_mode_on, 
    245                     elapsed, index, self.model, 
    246                     self.data, 
    247                     self.update_chisqr, 
    248                     self.source, 
    249                     unsmeared_output, unsmeared_data, unsmeared_error, 
    250                     pq_values, sq_values) 
    251         else: 
    252             self.completefn((self.data.x[index], output[index], 
    253                         self.page_id, 
    254                         self.state, 
    255                         self.weight, 
    256                         self.fid, 
    257                         self.toggle_mode_on, 
    258                         elapsed, index, self.model, 
    259                         self.data, 
    260                         self.update_chisqr, 
    261                         self.source, 
    262                         unsmeared_output, unsmeared_data, unsmeared_error, 
    263                         pq_values, sq_values)) 
     228            return res 
     229        else: 
     230            self.completefn(res) 
    264231 
    265232    def results(self): 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py

    r66d4370 r4ea8020  
    256256        self.widget.cbStructureFactor.setCurrentIndex(structure_index) 
    257257 
    258         # We have 4 more rows now 
     258        # We have 3 more param rows now (radius_effective is removed), and a new heading 
    259259        self.assertEqual(self.widget._model_model.rowCount(), rowcount+4) 
    260260 
     
    276276        last_index = self.widget.cbStructureFactor.count() 
    277277        self.widget.cbStructureFactor.setCurrentIndex(last_index-1) 
    278         # Do we have all the rows? 
    279         self.assertEqual(self.widget._model_model.rowCount(), 4) 
     278        # Do we have all the rows (incl. radius_effective & heading row)? 
     279        self.assertEqual(self.widget._model_model.rowCount(), 5) 
    280280 
    281281        # Are the command buttons properly enabled? 
     
    509509        Test opening of the load file dialog for 'array' polydisp. function 
    510510        """ 
     511 
     512        # open a non-existent file 
    511513        filename = os.path.join("UnitTesting", "testdata_noexist.txt") 
     514        with self.assertRaises(OSError, msg="testdata_noexist.txt should be a non-existent file"): 
     515            os.stat(filename) 
    512516        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=(filename,'')) 
    513517        self.widget.show() 
     
    525529 
    526530        # good file 
     531        # TODO: this depends on the working directory being src/sas/qtgui, 
     532        # TODO: which isn't convenient if you want to run this test suite 
     533        # TODO: individually 
    527534        filename = os.path.join("UnitTesting", "testdata.txt") 
     535        try: 
     536            os.stat(filename) 
     537        except OSError: 
     538            self.assertTrue(False, "testdata.txt does not exist") 
    528539        QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=(filename,'')) 
    529540 
     
    591602 
    592603        # Assure we have the combobox available 
    593         last_row = self.widget._last_model_row 
    594         func_index = self.widget._model_model.index(last_row-1, 1) 
     604        cbox_row = self.widget._n_shells_row 
     605        func_index = self.widget._model_model.index(cbox_row, 1) 
    595606        self.assertIsInstance(self.widget.lstParams.indexWidget(func_index), QtWidgets.QComboBox) 
     607 
     608        # get number of rows before changing shell count 
     609        last_row = self.widget._model_model.rowCount() 
    596610 
    597611        # Change the combo box index 
     
    10271041 
    10281042         # Check the model 
    1029         self.assertEqual(self.widget._model_model.rowCount(), 6) 
     1043        self.assertEqual(self.widget._model_model.rowCount(), 7) 
    10301044        self.assertEqual(self.widget._model_model.columnCount(), 5) 
    10311045 
     
    11431157        # two rows selected 
    11441158        index1 = self.widget.lstParams.model().index(1, 0, QtCore.QModelIndex()) 
    1145         index2 = self.widget.lstParams.model().index(2, 0, QtCore.QModelIndex()) 
     1159        index2 = self.widget.lstParams.model().index(3, 0, QtCore.QModelIndex()) 
    11461160        selection_model = self.widget.lstParams.selectionModel() 
    11471161        selection_model.select(index1, selection_model.Select | selection_model.Rows) 
     
    11791193        # several random parameters 
    11801194        self.assertEqual(self.widget.getRowFromName('scale'), 0) 
    1181         self.assertEqual(self.widget.getRowFromName('length'), 5) 
     1195        self.assertEqual(self.widget.getRowFromName('length'), 6) 
    11821196 
    11831197    def testGetParamNames(self): 
     
    12161230        # Create a constraint object 
    12171231        const = Constraint(parent=None, value=7.0) 
    1218         row = 2 
     1232        row = 3 
    12191233 
    12201234        spy = QtSignalSpy(self.widget, self.widget.constraintAddedSignal) 
     
    12351249        # assign complex constraint now 
    12361250        const = Constraint(parent=None, param='radius', func='5*sld') 
    1237         row = 4 
     1251        row = 5 
    12381252        # call the method tested 
    12391253        self.widget.addConstraintToRow(constraint=const, row=row) 
     
    12941308        self.widget.cbModel.setCurrentIndex(model_index) 
    12951309 
     1310        row1 = 1 
     1311        row2 = 5 
     1312 
     1313        param1 = "background" 
     1314        param2 = "radius" 
     1315 
     1316        #default_value1 = "0.001" 
     1317        default_value2 = "20" 
     1318 
    12961319        # select two rows 
    1297         row1 = 1 
    1298         row2 = 4 
    12991320        index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 
    13001321        index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) 
     
    13131334 
    13141335        # delete one of the constraints 
    1315         self.widget.deleteConstraintOnParameter(param='background') 
     1336        self.widget.deleteConstraintOnParameter(param=param1) 
    13161337 
    13171338        # see that the other constraint is still present 
    1318         cons = self.widget.getConstraintForRow(4) # 4 = radius 
    1319         self.assertEqual(cons.param, "radius") 
    1320         self.assertEqual(cons.value, "20") 
     1339        cons = self.widget.getConstraintForRow(row2) 
     1340        self.assertEqual(cons.param, param2) 
     1341        self.assertEqual(cons.value, default_value2) 
    13211342 
    13221343        # kill the other constraint 
     
    13241345 
    13251346        # see that the other constraint is still present 
    1326         self.assertEqual(self.widget.getConstraintsForModel(), [('radius', None)]) 
     1347        self.assertEqual(self.widget.getConstraintsForModel(), [(param2, None)]) 
    13271348 
    13281349    def testGetConstraintForRow(self): 
     
    13441365        self.widget.cbModel.setCurrentIndex(model_index) 
    13451366 
     1367        row1 = 1 
     1368        row2 = 5 
     1369 
    13461370        # select two rows 
    1347         row1 = 1 
    1348         row2 = 4 
    13491371        index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 
    13501372        index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) 
     
    13561378        self.widget.addSimpleConstraint() 
    13571379 
    1358         con_list = [False, True, False, False, True, False] 
     1380        con_list = [False, True, False, False, False, True, False] 
    13591381        new_list = [] 
    13601382        for row in range(self.widget._model_model.rowCount()): 
     
    13741396        self.widget.cbModel.setCurrentIndex(model_index) 
    13751397 
     1398        row1 = 1 
     1399        row2 = 5 
     1400 
    13761401        # select two rows 
    1377         row1 = 1 
    1378         row2 = 4 
    13791402        index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 
    13801403        index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) 
     
    13901413        constraint_objects[0].active = False 
    13911414 
    1392         con_list = [False, False, False, False, True, False] 
     1415        con_list = [False, False, False, False, False, True, False] 
    13931416        new_list = [] 
    13941417        for row in range(self.widget._model_model.rowCount()): 
     
    14111434        self.assertEqual(self.widget.getConstraintsForModel(),[]) 
    14121435 
     1436        row1 = 1 
     1437        row2 = 5 
     1438 
     1439        param1 = "background" 
     1440        param2 = "radius" 
     1441 
     1442        default_value1 = "0.001" 
     1443        default_value2 = "20" 
     1444 
    14131445        # select two rows 
    1414         row1 = 1 
    1415         row2 = 4 
    14161446        index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 
    14171447        index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) 
     
    14251455        # simple constraints 
    14261456        # self.assertEqual(self.widget.getConstraintsForModel(), [('background', '0.001'), ('radius', '20')]) 
    1427         cons = self.widget.getConstraintForRow(1) # 1 - background 
    1428         self.assertEqual(cons.param, "background") 
    1429         self.assertEqual(cons.value, "0.001") 
    1430         cons = self.widget.getConstraintForRow(4) # 4 = radius 
    1431         self.assertEqual(cons.param, "radius") 
    1432         self.assertEqual(cons.value, "20") 
     1457        cons = self.widget.getConstraintForRow(row1) 
     1458        self.assertEqual(cons.param, param1) 
     1459        self.assertEqual(cons.value, default_value1) 
     1460        cons = self.widget.getConstraintForRow(row2) 
     1461        self.assertEqual(cons.param, param2) 
     1462        self.assertEqual(cons.value, default_value2) 
    14331463 
    14341464        objects = self.widget.getConstraintObjectsForModel() 
    14351465        self.assertEqual(len(objects), 2) 
    1436         self.assertEqual(objects[1].value, '20') 
    1437         self.assertEqual(objects[0].param, 'background') 
     1466        self.assertEqual(objects[1].value, default_value2) 
     1467        self.assertEqual(objects[0].param, param1) 
     1468 
     1469        row = 0 
     1470        param = "scale" 
     1471        func = "5*sld" 
    14381472 
    14391473        # add complex constraint 
    1440         const = Constraint(parent=None, param='scale', func='5*sld') 
    1441         row = 0 
     1474        const = Constraint(parent=None, param=param, func=func) 
    14421475        self.widget.addConstraintToRow(constraint=const, row=row) 
    14431476        #self.assertEqual(self.widget.getConstraintsForModel(),[('scale', '5*sld'), ('background', '0.001'), ('radius', None)]) 
    1444         cons = self.widget.getConstraintForRow(4) # 4 = radius 
    1445         self.assertEqual(cons.param, "radius") 
    1446         self.assertEqual(cons.value, "20") 
     1477        cons = self.widget.getConstraintForRow(row2) 
     1478        self.assertEqual(cons.param, param2) 
     1479        self.assertEqual(cons.value, default_value2) 
    14471480 
    14481481        objects = self.widget.getConstraintObjectsForModel() 
    14491482        self.assertEqual(len(objects), 3) 
    1450         self.assertEqual(objects[0].func, '5*sld') 
     1483        self.assertEqual(objects[0].func, func) 
    14511484 
    14521485    def testReplaceConstraintName(self): 
  • 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.