Changeset 0c0491d in sasview


Ignore:
Timestamp:
Sep 7, 2018 10:56:02 AM (2 months ago)
Author:
wojciech
Branches:
ESS_GUI, ESS_GUI_Pr_fixes, ESS_GUI_project_save
Children:
34cf92c
Parents:
d9410c5 (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' of https://github.com/SasView/sasview into ESS_GUI_Pr_fixes

Location:
src/sas
Files:
1 added
9 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 rb69b549  
    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): 
     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            model.appendRow(row) 
     219            if cbox: 
     220                view.setIndexWidget(item2.index(), cbox) 
     221        rows.append(row) 
     222 
     223    return rows 
    150224 
    151225def markParameterDisabled(model, row): 
     
    182256    model.appendRow(item_list) 
    183257 
     258def addHeadingRowToModel(model, name): 
     259    """adds a non-interactive top-level row to the model""" 
     260    header_row = [QtGui.QStandardItem() for i in range(5)] 
     261    header_row[0].setText(name) 
     262 
     263    font = header_row[0].font() 
     264    font.setBold(True) 
     265    header_row[0].setFont(font) 
     266 
     267    for item in header_row: 
     268        item.setEditable(False) 
     269        item.setCheckable(False) 
     270        item.setSelectable(False) 
     271 
     272    model.appendRow(header_row) 
     273 
    184274def addHeadersToModel(model): 
    185275    """ 
     
    227317    model.header_tooltips = copy.copy(poly_header_error_tooltips) 
    228318 
    229 def addShellsToModel(parameters, model, index): 
    230     """ 
    231     Find out multishell parameters and update the model with the requested number of them 
     319def addShellsToModel(parameters, model, index, row_num=None, view=None): 
     320    """ 
     321    Find out multishell parameters and update the model with the requested number of them. 
     322    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. 
     324    Returns a list of lists of QStandardItem objects. 
    232325    """ 
    233326    multishell_parameters = getIterParams(parameters) 
    234327 
     328    rows = [] 
    235329    for i in range(index): 
    236330        for par in multishell_parameters: 
     
    250344                    item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
    251345                    item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
    252                     item1_5 = QtGui.QStandardItem(p.units) 
     346                    item1_5 = QtGui.QStandardItem(str(p.units)) 
    253347                    poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
    254348                    break 
     
    258352            item3 = QtGui.QStandardItem(str(par.limits[0])) 
    259353            item4 = QtGui.QStandardItem(str(par.limits[1])) 
    260             item5 = QtGui.QStandardItem(par.units) 
    261             model.appendRow([item1, item2, item3, item4, item5]) 
     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) 
     358            row = [item1, item2, item3, item4, item5] 
     359            cbox = createFixedChoiceComboBox(par, row) 
     360 
     361            # Always add to the model 
     362            if row_num is None: 
     363                model.appendRow(row) 
     364            else: 
     365                model.insertRow(row_num, row) 
     366                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) 
     373 
     374    return rows 
    262375 
    263376def calculateChi2(reference_data, current_data): 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r66d4370 rf0365a2e  
    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 
     
    11971209            self.updateData() 
    11981210 
     1211        # update in param model 
     1212        if model_column in [delegate.poly_pd, delegate.poly_error, delegate.poly_min, delegate.poly_max]: 
     1213            row = self.getRowFromName(parameter_name) 
     1214            param_item = self._model_model.item(row) 
     1215            self._model_model.blockSignals(True) 
     1216            param_item.child(0).child(0, model_column).setText(item.text()) 
     1217            self._model_model.blockSignals(False) 
     1218 
    11991219    def onMagnetModelChange(self, item): 
    12001220        """ 
     
    14871507        # update charts 
    14881508        self.onPlot() 
     1509        #self.recalculatePlotData() 
     1510 
    14891511 
    14901512        # Read only value - we can get away by just printing it here 
     
    15691591            # internal so can use closure for param_dict 
    15701592            param_name = str(self._model_model.item(row, 0).text()) 
    1571             if param_name not in list(param_dict.keys()): 
     1593            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15721594                return 
    15731595            # modify the param value 
    15741596            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    15751597            self._model_model.item(row, 1).setText(param_repr) 
     1598            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    15761599            if self.has_error_column: 
    15771600                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
     
    15811604            # Utility function for updateof polydispersity part of the main model 
    15821605            param_name = str(self._model_model.item(row, 0).text())+'.width' 
    1583             if param_name not in list(param_dict.keys()): 
     1606            if not self.isCheckable(row) or param_name not in list(param_dict.keys()): 
    15841607                return 
    15851608            # modify the param value 
     
    16151638            poly_item.insertColumn(2, [QtGui.QStandardItem("")]) 
    16161639 
    1617         # block signals temporarily, so we don't end up 
    1618         # updating charts with every single model change on the end of fitting 
    1619         self._model_model.blockSignals(True) 
    1620  
    16211640        if not self.has_error_column: 
    16221641            # create top-level error column 
     
    16251644            self.iterateOverModel(createErrorColumn) 
    16261645 
    1627             # we need to enable signals for this, otherwise the final column mysteriously disappears (don't ask, I don't 
    1628             # know) 
    1629             self._model_model.blockSignals(False) 
    16301646            self._model_model.insertColumn(2, error_column) 
    1631             self._model_model.blockSignals(True) 
    16321647 
    16331648            FittingUtilities.addErrorHeadersToModel(self._model_model) 
     
    16381653            self.has_error_column = True 
    16391654 
     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() 
    16401658        self.iterateOverModel(updateFittedValues) 
    16411659        self.iterateOverModel(updatePolyValues) 
    1642  
    1643         self._model_model.blockSignals(False) 
     1660        self._model_model.itemChanged.connect(self.onMainParamsChange) 
    16441661 
    16451662        # Adjust the table cells width. 
     
    16761693            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    16771694            self._poly_model.item(row_i, 1).setText(param_repr) 
     1695            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    16781696            if self.has_poly_error_column: 
    16791697                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
    16801698                self._poly_model.item(row_i, 2).setText(error_repr) 
    1681  
    16821699 
    16831700        def createErrorColumn(row_i): 
     
    17001717        # block signals temporarily, so we don't end up 
    17011718        # updating charts with every single model change on the end of fitting 
    1702         self._poly_model.blockSignals(True) 
     1719        self._poly_model.itemChanged.disconnect() 
    17031720        self.iterateOverPolyModel(updateFittedValues) 
    1704         self._poly_model.blockSignals(False) 
     1721        self._poly_model.itemChanged.connect(self.onPolyModelChange) 
    17051722 
    17061723        if self.has_poly_error_column: 
     
    17121729 
    17131730        # switch off reponse to model change 
    1714         self._poly_model.blockSignals(True) 
    17151731        self._poly_model.insertColumn(2, error_column) 
    1716         self._poly_model.blockSignals(False) 
    17171732        FittingUtilities.addErrorPolyHeadersToModel(self._poly_model) 
    17181733 
     
    17471762            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
    17481763            self._magnet_model.item(row, 1).setText(param_repr) 
     1764            self.kernel_module.setParam(param_name, param_dict[param_name][0]) 
    17491765            if self.has_magnet_error_column: 
    17501766                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
     
    17661782        # block signals temporarily, so we don't end up 
    17671783        # updating charts with every single model change on the end of fitting 
    1768         self._magnet_model.blockSignals(True) 
     1784        self._magnet_model.itemChanged.disconnect() 
    17691785        self.iterateOverMagnetModel(updateFittedValues) 
    1770         self._magnet_model.blockSignals(False) 
     1786        self._magnet_model.itemChanged.connect(self.onMagnetModelChange) 
    17711787 
    17721788        if self.has_magnet_error_column: 
     
    17781794 
    17791795        # switch off reponse to model change 
    1780         self._magnet_model.blockSignals(True) 
    17811796        self._magnet_model.insertColumn(2, error_column) 
    1782         self._magnet_model.blockSignals(False) 
    17831797        FittingUtilities.addErrorHeadersToModel(self._magnet_model) 
    17841798 
     
    17921806        self.cmdPlot.setText("Show Plot") 
    17931807        # Force data recalculation so existing charts are updated 
     1808        self.showPlot() 
    17941809        self.recalculatePlotData() 
    1795         self.showPlot() 
    17961810 
    17971811    def onSmearingOptionsUpdate(self): 
     
    19581972        # Crete/overwrite model items 
    19591973        self._model_model.clear() 
    1960  
    1961         # First, add parameters from the main model 
    1962         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: 
    19631986            self.fromModelToQModel(model_name) 
    1964  
    1965         # Then, add structure factor derived parameters 
    1966         if structure_factor is not None and structure_factor != "None": 
    1967             if model_name is None: 
    1968                 # Instantiate the current sasmodel for SF-only models 
    1969                 self.kernel_module = self.models[structure_factor]() 
    1970             self.fromStructureFactorToQModel(structure_factor) 
    1971         else: 
     1987            self.addExtraShells() 
     1988 
    19721989            # Allow the SF combobox visibility for the given sasmodel 
    19731990            self.enableStructureFactorControl(structure_factor) 
     1991         
     1992            # Add S(Q) 
    19741993            if self.cbStructureFactor.isEnabled(): 
    19751994                structure_factor = self.cbStructureFactor.currentText() 
    19761995                self.fromStructureFactorToQModel(structure_factor) 
    19771996 
    1978         # Then, add multishells 
    1979         if model_name is not None: 
    1980             # Multishell models need additional treatment 
    1981             self.addExtraShells() 
    1982  
    1983         # Add polydispersity to the model 
    1984         self.poly_params = {} 
    1985         self.setPolyModel() 
    1986         # Add magnetic parameters to the model 
    1987         self.magnet_params = {} 
    1988         self.setMagneticModel() 
     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() 
    19892003 
    19902004        # Adjust the table cells width 
     
    20592073        self.shell_names = self.shellNamesList() 
    20602074 
     2075        # Add heading row 
     2076        FittingUtilities.addHeadingRowToModel(self._model_model, model_name) 
     2077 
    20612078        # Update the QModel 
    2062         new_rows = FittingUtilities.addParametersToModel(self.model_parameters, self.kernel_module, self.is2D) 
    2063  
    2064         for row in new_rows: 
    2065             self._model_model.appendRow(row) 
    2066         # Update the counter used for multishell display 
    2067         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) 
    20682085 
    20692086    def fromStructureFactorToQModel(self, structure_factor): 
     
    20732090        if structure_factor is None or structure_factor=="None": 
    20742091            return 
    2075         structure_module = generate.load_kernel_module(structure_factor) 
    2076         structure_parameters = modelinfo.make_parameter_table(getattr(structure_module, 'parameters', [])) 
    2077  
    2078         structure_kernel = self.models[structure_factor]() 
    2079         form_kernel = self.kernel_module 
    2080  
    2081         self.kernel_module = MultiplicationModel(form_kernel, structure_kernel) 
    2082  
    2083         new_rows = FittingUtilities.addSimpleParametersToModel(structure_parameters, self.is2D) 
    2084         for row in new_rows: 
    2085             self._model_model.appendRow(row) 
    2086             # disable fitting of parameters not listed in self.kernel_module (probably radius_effective) 
    2087             if row[0].text() not in self.kernel_module.params.keys(): 
    2088                 row_num = self._model_model.rowCount() - 1 
    2089                 FittingUtilities.markParameterDisabled(self._model_model, row_num) 
    2090  
    2091         # Update the counter used for multishell display 
    2092         self._last_model_row = self._model_model.rowCount() 
     2092 
     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 
     2099        else: 
     2100            s_kernel = self.models[structure_factor]() 
     2101            p_kernel = self.kernel_module 
     2102 
     2103            p_pars_len = len(p_kernel._model_info.parameters.kernel_parameters) 
     2104            s_pars_len = len(s_kernel._model_info.parameters.kernel_parameters) 
     2105 
     2106            self.kernel_module = MultiplicationModel(p_kernel, s_kernel) 
     2107            all_params = self.kernel_module._model_info.parameters.kernel_parameters 
     2108            all_param_names = [param.name for param in all_params] 
     2109 
     2110            # S(Q) params from the product model are not necessarily the same as those from the S(Q) model; any 
     2111            # conflicting names with P(Q) params will cause a rename 
     2112 
     2113            if "radius_effective_mode" in all_param_names: 
     2114                # Show all parameters 
     2115                s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len]) 
     2116                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters) 
     2117            else: 
     2118                # Ensure radius_effective is not displayed 
     2119                s_params_orig = modelinfo.ParameterTable(s_kernel._model_info.parameters.kernel_parameters[1:]) 
     2120                if "radius_effective" in all_param_names: 
     2121                    s_params = modelinfo.ParameterTable(all_params[p_pars_len+1:p_pars_len+s_pars_len]) 
     2122                else: 
     2123                    s_params = modelinfo.ParameterTable(all_params[p_pars_len:p_pars_len+s_pars_len-1]) 
     2124 
     2125        # Add heading row 
     2126        FittingUtilities.addHeadingRowToModel(self._model_model, structure_factor) 
     2127 
     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) 
    20932136 
    20942137    def haveParamsToFit(self): 
     
    21162159        model_row = item.row() 
    21172160        name_index = self._model_model.index(model_row, 0) 
     2161        name_item = self._model_model.itemFromIndex(name_index) 
    21182162 
    21192163        # Extract changed value. 
     
    21242168            return 
    21252169 
    2126         parameter_name = str(self._model_model.data(name_index)) # sld, background etc. 
     2170        # if the item has user data, this is the actual parameter name (e.g. to handle duplicate names) 
     2171        if name_item.data(QtCore.Qt.UserRole): 
     2172            parameter_name = str(name_item.data(QtCore.Qt.UserRole)) 
     2173        else: 
     2174            parameter_name = str(self._model_model.data(name_index)) 
    21272175 
    21282176        # Update the parameter value - note: this supports +/-inf as well 
     
    23582406            new_plots.append(sq_data) 
    23592407 
    2360         # Update/generate plots 
    23612408        for plot in new_plots: 
    23622409            self.communicate.plotUpdateSignal.emit([plot]) 
     
    25582605        def updateFunctionCaption(row): 
    25592606            # Utility function for update of polydispersity function name in the main model 
     2607            if not self.isCheckable(row): 
     2608                return 
     2609            self._model_model.blockSignals(True) 
    25602610            param_name = str(self._model_model.item(row, 0).text()) 
     2611            self._model_model.blockSignals(False) 
    25612612            if param_name !=  param.name: 
    25622613                return 
    25632614            # Modify the param value 
     2615            self._model_model.blockSignals(True) 
    25642616            if self.has_error_column: 
    25652617                # err column changes the indexing 
     
    25672619            else: 
    25682620                self._model_model.item(row, 0).child(0).child(0,4).setText(combo_string) 
     2621            self._model_model.blockSignals(False) 
    25692622 
    25702623        if combo_string == 'array': 
     
    27262779 
    27272780        self.lstParams.setIndexWidget(shell_index, func) 
    2728         self._last_model_row = self._model_model.rowCount() 
     2781        self._n_shells_row = shell_row - 1 
    27292782 
    27302783        # Set the index to the state-kept value 
     
    27372790        """ 
    27382791        # Find row location of the combobox 
    2739         last_row = self._last_model_row 
    2740         remove_rows = self._model_model.rowCount() - last_row 
     2792        first_row = self._n_shells_row + 1 
     2793        remove_rows = self._num_shell_params 
    27412794 
    27422795        if remove_rows > 1: 
    2743             self._model_model.removeRows(last_row, remove_rows) 
    2744  
    2745         FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index) 
     2796            self._model_model.removeRows(first_row, remove_rows) 
     2797 
     2798        new_rows = FittingUtilities.addShellsToModel( 
     2799                self.model_parameters, 
     2800                self._model_model, 
     2801                index, 
     2802                first_row, 
     2803                self.lstParams) 
     2804 
     2805        self._num_shell_params = len(new_rows) 
    27462806        self.current_shell_displayed = index 
    27472807 
  • 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 
  • src/sas/qtgui/Perspectives/Inversion/InversionPerspective.py

    r3c6ecd9 rb1f6063  
    309309                                            and not self.isCalculating) 
    310310        self.removeButton.setEnabled(self.logic.data_is_loaded) 
    311         self.explorerButton.setEnabled(self.logic.data_is_loaded 
    312                                        and np.all(self.logic.data.dy != 0)) 
     311        self.explorerButton.setEnabled(self.logic.data_is_loaded) 
    313312        self.stopButton.setVisible(self.isCalculating) 
    314313        self.regConstantSuggestionButton.setEnabled( 
     
    641640        self.calcThread.ready(2.5) 
    642641 
     642        #Perform estimate should be done on value enter this should solve delay problem 
     643        self.performEstimate() 
     644 
    643645    def stopCalcThread(self): 
    644646        """ Stops a thread if it exists and is running """ 
  • src/sas/sascalc/pr/invertor.py

    rb8080e1 r6701a0b  
    7171        A[j][i] = (Fourier transformed base function for point j) 
    7272 
    73     We them choose a number of r-points, n_r, to evaluate the second 
     73    We then choose a number of r-points, n_r, to evaluate the second 
    7474    derivative of P(r) at. This is used as our regularization term. 
    7575    For a vector r of length n_r, the following n_r rows are set to :: 
     
    144144        x, y, err, d_max, q_min, q_max and alpha 
    145145        """ 
    146         if   name == 'x': 
     146        if name == 'x': 
    147147            if 0.0 in value: 
    148148                msg = "Invertor: one of your q-values is zero. " 
     
    227227        return None 
    228228 
     229    def add_errors(self, yvalues): 
     230        """ 
     231        Adds errors to data set is they are not avaialble 
     232        :return: 
     233        """ 
     234        stats_errors = np.zeros(len(yvalues)) 
     235        for i in range(len(yvalues)): 
     236            # Scale the error so that we can fit over several decades of Q 
     237            scale = 0.05 * np.sqrt(yvalues[i]) 
     238            min_err = 0.01 * yvalues[i] 
     239            stats_errors[i] = scale * np.sqrt(np.fabs(yvalues[i])) + min_err 
     240        logger.warning("Simulated errors have been added to the data set\n") 
     241        return stats_errors 
     242 
    229243    def clone(self): 
    230244        """ 
     
    244258        invertor.x = self.x 
    245259        invertor.y = self.y 
    246         invertor.err = self.err 
     260        if np.size(self.err) == 0 or np.all(self.err) == 0: 
     261            invertor.err = self.add_errors(self.y) 
     262        else: 
     263            invertor.err = self.err 
    247264        invertor.est_bck = self.est_bck 
    248265        invertor.background = self.background 
     
    268285            A[i][j] = (Fourier transformed base function for point j) 
    269286 
    270         We them choose a number of r-points, n_r, to evaluate the second 
     287        We then choose a number of r-points, n_r, to evaluate the second 
    271288        derivative of P(r) at. This is used as our regularization term. 
    272289        For a vector r of length n_r, the following n_r rows are set to :: 
Note: See TracChangeset for help on using the changeset viewer.