Changes in / [0c0491d:d9410c5] in sasview
- Location:
- src/sas/qtgui
- Files:
-
- 1 deleted
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/MainWindow/DataExplorer.py
r60d55a7 rfd7ef36 560 560 # Now query the model item for available plots 561 561 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()] 562 564 563 565 new_plots = [] 564 566 for item, plot in plots.items(): 565 if not self.updatePlot(plot): 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: 566 573 # Don't plot intermediate results, e.g. P(Q), S(Q) 567 match = GuiUtils.theory_plot_ID_pattern.match(plot .id)574 match = GuiUtils.theory_plot_ID_pattern.match(plot_id) 568 575 # 2nd match group contains the identifier for the intermediate result, if present (e.g. "[P(Q)]") 569 576 if match and match.groups()[1] != None: … … 699 706 self.active_plots[plot_set.id] = old_plot 700 707 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 708 def updatePlot(self, new_data): 709 """ 710 Modify existing plot for immediate response 711 """ 712 data = new_data[0] 710 713 assert type(data).__name__ in ['Data1D', 'Data2D'] 711 714 … … 716 719 if data_id in ids_keys: 717 720 self.active_plots[data_id].replacePlot(data_id, data) 718 return True719 721 elif data_id in ids_vals: 720 722 list(self.active_plots.values())[ids_vals.index(data_id)].replacePlot(data_id, data) 721 return True722 return False723 723 724 724 def chooseFiles(self): -
src/sas/qtgui/Perspectives/Fitting/FittingLogic.py
rdcabba7 rb4d05bd 161 161 Create a new 1D data instance based on fitting results 162 162 """ 163 164 return self._create1DPlot(tab_id, return_data['x'], return_data['y'], 165 return_data['model'], return_data['data']) 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) 166 172 167 173 def new2DPlot(self, return_data): … … 169 175 Create a new 2D data instance based on fitting results 170 176 """ 171 image = return_data['image']172 data = return_data['data']173 model = return_data['model']177 image, data, page_id, model, state, toggle_mode_on,\ 178 elapsed, index, fid, qmin, qmax, weight, \ 179 update_chisqr, source = return_data 174 180 175 181 np.nan_to_num(image) … … 177 183 new_plot.name = model.name + '2d' 178 184 new_plot.title = "Analytical model 2D " 179 new_plot.id = str( return_data['page_id']) + " " + data.name180 new_plot.group_id = str( return_data['page_id']) + " Model2D"185 new_plot.id = str(page_id) + " " + data.name 186 new_plot.group_id = str(page_id) + " Model2D" 181 187 new_plot.detector = data.detector 182 188 new_plot.source = data.source … … 212 218 (pq_plot, sq_plot). If either are unavailable, the corresponding plot is None. 213 219 """ 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 214 227 215 228 pq_plot = None 216 229 sq_plot = None 217 230 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)") 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)") 226 235 227 236 return pq_plot, sq_plot -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
r70f4458 rb764ae5 8 8 from sas.qtgui.Plotting.PlotterData import Data1D 9 9 from sas.qtgui.Plotting.PlotterData import Data2D 10 11 from sas.qtgui.Perspectives.Fitting.AssociatedComboBox import AssociatedComboBox12 10 13 11 model_header_captions = ['Parameter', 'Value', 'Min', 'Max', 'Units'] … … 63 61 return (param_name, param_length) 64 62 65 def 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 93 def 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. 63 def addParametersToModel(parameters, kernel_module, is2D): 64 """ 65 Update local ModelModel with sasmodel parameters 98 66 """ 99 67 multishell_parameters = getIterParams(parameters) … … 104 72 else: 105 73 params = parameters.iq_parameters 106 107 rows = [] 74 item = [] 108 75 for param in params: 109 76 # don't include shell parameters 110 77 if param.name == multishell_param_name: 111 78 continue 112 113 79 # Modify parameter name from <param>[n] to <param>1 114 80 item_name = param.name 115 81 if param in multishell_parameters: 116 82 continue 83 # item_name = replaceShellName(param.name, 1) 117 84 118 85 item1 = QtGui.QStandardItem(item_name) 119 86 item1.setCheckable(True) 120 87 item1.setEditable(False) 121 88 # item_err = QtGui.QStandardItem() 122 89 # check for polydisp params 123 90 if param.polydisperse: … … 126 93 item1_1 = QtGui.QStandardItem("Distribution") 127 94 item1_1.setEditable(False) 128 129 95 # Find param in volume_params 130 96 for p in parameters.form_volume_parameters: … … 133 99 width = kernel_module.getParam(p.name+'.width') 134 100 ptype = kernel_module.getParam(p.name+'.type') 101 135 102 item1_2 = QtGui.QStandardItem(str(width)) 136 103 item1_2.setEditable(False) … … 143 110 poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 144 111 break 145 146 112 # Add the polydisp item as a child 147 113 item1.appendRow([poly_item]) 148 149 114 # Param values 150 115 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() 151 119 item3 = QtGui.QStandardItem(str(param.limits[0])) 152 120 item4 = QtGui.QStandardItem(str(param.limits[1])) 153 item5 = QtGui.QStandardItem( str(param.units))121 item5 = QtGui.QStandardItem(param.units) 154 122 item5.setEditable(False) 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 169 def 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) 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 177 129 """ 178 130 if is2D: … … 180 132 else: 181 133 params = parameters.iq_parameters 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): 134 item = [] 135 for param in params: 197 136 # Create the top level, checkable item 198 item_name = param _orig.name137 item_name = param.name 199 138 item1 = QtGui.QStandardItem(item_name) 200 item1.setData(param.name, QtCore.Qt.UserRole)201 139 item1.setCheckable(True) 202 140 item1.setEditable(False) 203 204 141 # Param values 205 142 # TODO: add delegate for validation of cells 206 143 item2 = QtGui.QStandardItem(str(param.default)) 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 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 224 150 225 151 def markParameterDisabled(model, row): … … 256 182 model.appendRow(item_list) 257 183 258 def 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 274 184 def addHeadersToModel(model): 275 185 """ … … 317 227 model.header_tooltips = copy.copy(poly_header_error_tooltips) 318 228 319 def 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. 229 def addShellsToModel(parameters, model, index): 230 """ 231 Find out multishell parameters and update the model with the requested number of them 325 232 """ 326 233 multishell_parameters = getIterParams(parameters) 327 234 328 rows = []329 235 for i in range(index): 330 236 for par in multishell_parameters: … … 344 250 item1_3 = QtGui.QStandardItem(str(p.limits[0])) 345 251 item1_4 = QtGui.QStandardItem(str(p.limits[1])) 346 item1_5 = QtGui.QStandardItem( str(p.units))252 item1_5 = QtGui.QStandardItem(p.units) 347 253 poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 348 254 break … … 352 258 item3 = QtGui.QStandardItem(str(par.limits[0])) 353 259 item4 = QtGui.QStandardItem(str(par.limits[1])) 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 260 item5 = QtGui.QStandardItem(par.units) 261 model.appendRow([item1, item2, item3, item4, item5]) 375 262 376 263 def calculateChi2(reference_data, current_data): -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r5fb714b r66d4370 91 91 fittingFinishedSignal = QtCore.pyqtSignal(tuple) 92 92 batchFittingFinishedSignal = QtCore.pyqtSignal(tuple) 93 Calc1DFinishedSignal = QtCore.pyqtSignal( dict)94 Calc2DFinishedSignal = QtCore.pyqtSignal( dict)93 Calc1DFinishedSignal = QtCore.pyqtSignal(tuple) 94 Calc2DFinishedSignal = QtCore.pyqtSignal(tuple) 95 95 96 96 def __init__(self, parent=None, data=None, tab_id=1): … … 219 219 # Utility variable to enable unselectable option in category combobox 220 220 self._previous_category_index = 0 221 # Utility variables for multishell display 222 self._n_shells_row = 0 223 self._num_shell_params = 0 221 # Utility variable for multishell display 222 self._last_model_row = 0 224 223 # Dictionary of {model name: model class} for the current category 225 224 self.models = {} … … 677 676 Return list of all parameters for the current model 678 677 """ 679 return [self._model_model.item(row).text() 680 for row in range(self._model_model.rowCount()) 681 if self.isCheckable(row)] 678 return [self._model_model.item(row).text() for row in range(self._model_model.rowCount())] 682 679 683 680 def modifyViewOnRow(self, row, font=None, brush=None): … … 707 704 assert isinstance(constraint, Constraint) 708 705 assert 0 <= row <= self._model_model.rowCount() 709 assert self.isCheckable(row)710 706 711 707 item = QtGui.QStandardItem() … … 728 724 max_col = self.lstParams.itemDelegate().param_max 729 725 for row in self.selectedParameters(): 730 assert(self.isCheckable(row))731 726 param = self._model_model.item(row, 0).text() 732 727 value = self._model_model.item(row, 1).text() … … 771 766 max_col = self.lstParams.itemDelegate().param_max 772 767 for row in range(self._model_model.rowCount()): 773 if not self.isCheckable(row):774 continue775 768 if not self.rowHasConstraint(row): 776 769 continue … … 801 794 For the given row, return its constraint, if any 802 795 """ 803 if self.isCheckable(row):796 try: 804 797 item = self._model_model.item(row, 1) 805 try: 806 return item.child(0).data() 807 except AttributeError: 808 # return none when no constraints 809 pass 810 return None 798 return item.child(0).data() 799 except AttributeError: 800 # return none when no constraints 801 return None 811 802 812 803 def rowHasConstraint(self, row): … … 814 805 Finds out if row of the main model has a constraint child 815 806 """ 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 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 822 812 return False 823 813 … … 826 816 Finds out if row of the main model has an active constraint child 827 817 """ 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 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 834 823 return False 835 824 … … 838 827 Finds out if row of the main model has an active, nontrivial constraint child 839 828 """ 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 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 846 834 return False 847 835 … … 1209 1197 self.updateData() 1210 1198 1211 # update in param model1212 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 1219 1199 def onMagnetModelChange(self, item): 1220 1200 """ … … 1507 1487 # update charts 1508 1488 self.onPlot() 1509 #self.recalculatePlotData()1510 1511 1489 1512 1490 # Read only value - we can get away by just printing it here … … 1591 1569 # internal so can use closure for param_dict 1592 1570 param_name = str(self._model_model.item(row, 0).text()) 1593 if not self.isCheckable(row) orparam_name not in list(param_dict.keys()):1571 if param_name not in list(param_dict.keys()): 1594 1572 return 1595 1573 # modify the param value 1596 1574 param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 1597 1575 self._model_model.item(row, 1).setText(param_repr) 1598 self.kernel_module.setParam(param_name, param_dict[param_name][0])1599 1576 if self.has_error_column: 1600 1577 error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) … … 1604 1581 # Utility function for updateof polydispersity part of the main model 1605 1582 param_name = str(self._model_model.item(row, 0).text())+'.width' 1606 if not self.isCheckable(row) orparam_name not in list(param_dict.keys()):1583 if param_name not in list(param_dict.keys()): 1607 1584 return 1608 1585 # modify the param value … … 1638 1615 poly_item.insertColumn(2, [QtGui.QStandardItem("")]) 1639 1616 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 1640 1621 if not self.has_error_column: 1641 1622 # create top-level error column … … 1644 1625 self.iterateOverModel(createErrorColumn) 1645 1626 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) 1646 1630 self._model_model.insertColumn(2, error_column) 1631 self._model_model.blockSignals(True) 1647 1632 1648 1633 FittingUtilities.addErrorHeadersToModel(self._model_model) … … 1653 1638 self.has_error_column = True 1654 1639 1655 # block signals temporarily, so we don't end up1656 # updating charts with every single model change on the end of fitting1657 self._model_model.itemChanged.disconnect()1658 1640 self.iterateOverModel(updateFittedValues) 1659 1641 self.iterateOverModel(updatePolyValues) 1660 self._model_model.itemChanged.connect(self.onMainParamsChange) 1642 1643 self._model_model.blockSignals(False) 1661 1644 1662 1645 # Adjust the table cells width. … … 1693 1676 param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 1694 1677 self._poly_model.item(row_i, 1).setText(param_repr) 1695 self.kernel_module.setParam(param_name, param_dict[param_name][0])1696 1678 if self.has_poly_error_column: 1697 1679 error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 1698 1680 self._poly_model.item(row_i, 2).setText(error_repr) 1681 1699 1682 1700 1683 def createErrorColumn(row_i): … … 1717 1700 # block signals temporarily, so we don't end up 1718 1701 # updating charts with every single model change on the end of fitting 1719 self._poly_model. itemChanged.disconnect()1702 self._poly_model.blockSignals(True) 1720 1703 self.iterateOverPolyModel(updateFittedValues) 1721 self._poly_model. itemChanged.connect(self.onPolyModelChange)1704 self._poly_model.blockSignals(False) 1722 1705 1723 1706 if self.has_poly_error_column: … … 1729 1712 1730 1713 # switch off reponse to model change 1714 self._poly_model.blockSignals(True) 1731 1715 self._poly_model.insertColumn(2, error_column) 1716 self._poly_model.blockSignals(False) 1732 1717 FittingUtilities.addErrorPolyHeadersToModel(self._poly_model) 1733 1718 … … 1762 1747 param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 1763 1748 self._magnet_model.item(row, 1).setText(param_repr) 1764 self.kernel_module.setParam(param_name, param_dict[param_name][0])1765 1749 if self.has_magnet_error_column: 1766 1750 error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) … … 1782 1766 # block signals temporarily, so we don't end up 1783 1767 # updating charts with every single model change on the end of fitting 1784 self._magnet_model. itemChanged.disconnect()1768 self._magnet_model.blockSignals(True) 1785 1769 self.iterateOverMagnetModel(updateFittedValues) 1786 self._magnet_model. itemChanged.connect(self.onMagnetModelChange)1770 self._magnet_model.blockSignals(False) 1787 1771 1788 1772 if self.has_magnet_error_column: … … 1794 1778 1795 1779 # switch off reponse to model change 1780 self._magnet_model.blockSignals(True) 1796 1781 self._magnet_model.insertColumn(2, error_column) 1782 self._magnet_model.blockSignals(False) 1797 1783 FittingUtilities.addErrorHeadersToModel(self._magnet_model) 1798 1784 … … 1806 1792 self.cmdPlot.setText("Show Plot") 1807 1793 # Force data recalculation so existing charts are updated 1794 self.recalculatePlotData() 1808 1795 self.showPlot() 1809 self.recalculatePlotData()1810 1796 1811 1797 def onSmearingOptionsUpdate(self): … … 1972 1958 # Crete/overwrite model items 1973 1959 self._model_model.clear() 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 factor1980 self.kernel_module = None1981 self.fromStructureFactorToQModel(structure_factor)1982 else:1983 # No models selected1984 return1960 1961 # First, add parameters from the main model 1962 if model_name is not None: 1963 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) 1985 1971 else: 1986 self.fromModelToQModel(model_name)1987 self.addExtraShells()1988 1989 1972 # Allow the SF combobox visibility for the given sasmodel 1990 1973 self.enableStructureFactorControl(structure_factor) 1991 1992 # Add S(Q)1993 1974 if self.cbStructureFactor.isEnabled(): 1994 1975 structure_factor = self.cbStructureFactor.currentText() 1995 1976 self.fromStructureFactorToQModel(structure_factor) 1996 1977 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() 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() 2003 1989 2004 1990 # Adjust the table cells width … … 2073 2059 self.shell_names = self.shellNamesList() 2074 2060 2075 # Add heading row2076 FittingUtilities.addHeadingRowToModel(self._model_model, model_name)2077 2078 2061 # Update the QModel 2079 FittingUtilities.addParametersToModel(2080 self.model_parameters, 2081 self.kernel_module,2082 self.is2D,2083 self._model_model,2084 self.lstParams)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() 2085 2068 2086 2069 def fromStructureFactorToQModel(self, structure_factor): … … 2090 2073 if structure_factor is None or structure_factor=="None": 2091 2074 return 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) 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() 2136 2093 2137 2094 def haveParamsToFit(self): … … 2159 2116 model_row = item.row() 2160 2117 name_index = self._model_model.index(model_row, 0) 2161 name_item = self._model_model.itemFromIndex(name_index)2162 2118 2163 2119 # Extract changed value. … … 2168 2124 return 2169 2125 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)) 2126 parameter_name = str(self._model_model.data(name_index)) # sld, background etc. 2175 2127 2176 2128 # Update the parameter value - note: this supports +/-inf as well … … 2406 2358 new_plots.append(sq_data) 2407 2359 2360 # Update/generate plots 2408 2361 for plot in new_plots: 2409 2362 self.communicate.plotUpdateSignal.emit([plot]) … … 2605 2558 def updateFunctionCaption(row): 2606 2559 # Utility function for update of polydispersity function name in the main model 2607 if not self.isCheckable(row):2608 return2609 self._model_model.blockSignals(True)2610 2560 param_name = str(self._model_model.item(row, 0).text()) 2611 self._model_model.blockSignals(False)2612 2561 if param_name != param.name: 2613 2562 return 2614 2563 # Modify the param value 2615 self._model_model.blockSignals(True)2616 2564 if self.has_error_column: 2617 2565 # err column changes the indexing … … 2619 2567 else: 2620 2568 self._model_model.item(row, 0).child(0).child(0,4).setText(combo_string) 2621 self._model_model.blockSignals(False)2622 2569 2623 2570 if combo_string == 'array': … … 2779 2726 2780 2727 self.lstParams.setIndexWidget(shell_index, func) 2781 self._ n_shells_row = shell_row - 12728 self._last_model_row = self._model_model.rowCount() 2782 2729 2783 2730 # Set the index to the state-kept value … … 2790 2737 """ 2791 2738 # Find row location of the combobox 2792 first_row = self._n_shells_row + 12793 remove_rows = self._ num_shell_params2739 last_row = self._last_model_row 2740 remove_rows = self._model_model.rowCount() - last_row 2794 2741 2795 2742 if remove_rows > 1: 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) 2743 self._model_model.removeRows(last_row, remove_rows) 2744 2745 FittingUtilities.addShellsToModel(self.model_parameters, self._model_model, index) 2806 2746 self.current_shell_displayed = index 2807 2747 -
src/sas/qtgui/Perspectives/Fitting/ModelThread.py
rdcabba7 r2df558e 101 101 elapsed = time.time() - self.starttime 102 102 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 111 103 if LocalConfig.USING_TWISTED: 112 return res 113 else: 114 self.completefn(res) 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 115 135 116 136 class Calc1D(CalcThread): … … 216 236 elapsed = time.time() - self.starttime 217 237 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 227 238 if LocalConfig.USING_TWISTED: 228 return res 229 else: 230 self.completefn(res) 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)) 231 264 232 265 def results(self): -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
r3fbd77b r66d4370 256 256 self.widget.cbStructureFactor.setCurrentIndex(structure_index) 257 257 258 # We have 3 more param rows now (radius_effective is removed), and a new heading258 # We have 4 more rows now 259 259 self.assertEqual(self.widget._model_model.rowCount(), rowcount+4) 260 260 … … 276 276 last_index = self.widget.cbStructureFactor.count() 277 277 self.widget.cbStructureFactor.setCurrentIndex(last_index-1) 278 # Do we have all the rows (incl. radius_effective & heading row)?279 self.assertEqual(self.widget._model_model.rowCount(), 5)278 # Do we have all the rows? 279 self.assertEqual(self.widget._model_model.rowCount(), 4) 280 280 281 281 # Are the command buttons properly enabled? … … 509 509 Test opening of the load file dialog for 'array' polydisp. function 510 510 """ 511 512 # open a non-existent file513 511 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)516 512 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=(filename,'')) 517 513 self.widget.show() … … 529 525 530 526 # 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 suite533 # TODO: individually534 527 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")539 528 QtWidgets.QFileDialog.getOpenFileName = MagicMock(return_value=(filename,'')) 540 529 … … 602 591 603 592 # Assure we have the combobox available 604 cbox_row = self.widget._n_shells_row605 func_index = self.widget._model_model.index( cbox_row, 1)593 last_row = self.widget._last_model_row 594 func_index = self.widget._model_model.index(last_row-1, 1) 606 595 self.assertIsInstance(self.widget.lstParams.indexWidget(func_index), QtWidgets.QComboBox) 607 608 # get number of rows before changing shell count609 last_row = self.widget._model_model.rowCount()610 596 611 597 # Change the combo box index … … 1041 1027 1042 1028 # Check the model 1043 self.assertEqual(self.widget._model_model.rowCount(), 7)1029 self.assertEqual(self.widget._model_model.rowCount(), 6) 1044 1030 self.assertEqual(self.widget._model_model.columnCount(), 5) 1045 1031 … … 1157 1143 # two rows selected 1158 1144 index1 = self.widget.lstParams.model().index(1, 0, QtCore.QModelIndex()) 1159 index2 = self.widget.lstParams.model().index( 3, 0, QtCore.QModelIndex())1145 index2 = self.widget.lstParams.model().index(2, 0, QtCore.QModelIndex()) 1160 1146 selection_model = self.widget.lstParams.selectionModel() 1161 1147 selection_model.select(index1, selection_model.Select | selection_model.Rows) … … 1193 1179 # several random parameters 1194 1180 self.assertEqual(self.widget.getRowFromName('scale'), 0) 1195 self.assertEqual(self.widget.getRowFromName('length'), 6)1181 self.assertEqual(self.widget.getRowFromName('length'), 5) 1196 1182 1197 1183 def testGetParamNames(self): … … 1230 1216 # Create a constraint object 1231 1217 const = Constraint(parent=None, value=7.0) 1232 row = 31218 row = 2 1233 1219 1234 1220 spy = QtSignalSpy(self.widget, self.widget.constraintAddedSignal) … … 1249 1235 # assign complex constraint now 1250 1236 const = Constraint(parent=None, param='radius', func='5*sld') 1251 row = 51237 row = 4 1252 1238 # call the method tested 1253 1239 self.widget.addConstraintToRow(constraint=const, row=row) … … 1308 1294 self.widget.cbModel.setCurrentIndex(model_index) 1309 1295 1296 # select two rows 1310 1297 row1 = 1 1311 row2 = 5 1312 1313 param1 = "background" 1314 param2 = "radius" 1315 1316 #default_value1 = "0.001" 1317 default_value2 = "20" 1318 1319 # select two rows 1298 row2 = 4 1320 1299 index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 1321 1300 index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) … … 1334 1313 1335 1314 # delete one of the constraints 1336 self.widget.deleteConstraintOnParameter(param= param1)1315 self.widget.deleteConstraintOnParameter(param='background') 1337 1316 1338 1317 # see that the other constraint is still present 1339 cons = self.widget.getConstraintForRow( row2)1340 self.assertEqual(cons.param, param2)1341 self.assertEqual(cons.value, default_value2)1318 cons = self.widget.getConstraintForRow(4) # 4 = radius 1319 self.assertEqual(cons.param, "radius") 1320 self.assertEqual(cons.value, "20") 1342 1321 1343 1322 # kill the other constraint … … 1345 1324 1346 1325 # see that the other constraint is still present 1347 self.assertEqual(self.widget.getConstraintsForModel(), [( param2, None)])1326 self.assertEqual(self.widget.getConstraintsForModel(), [('radius', None)]) 1348 1327 1349 1328 def testGetConstraintForRow(self): … … 1365 1344 self.widget.cbModel.setCurrentIndex(model_index) 1366 1345 1346 # select two rows 1367 1347 row1 = 1 1368 row2 = 5 1369 1370 # select two rows 1348 row2 = 4 1371 1349 index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 1372 1350 index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) … … 1378 1356 self.widget.addSimpleConstraint() 1379 1357 1380 con_list = [False, True, False, False, False,True, False]1358 con_list = [False, True, False, False, True, False] 1381 1359 new_list = [] 1382 1360 for row in range(self.widget._model_model.rowCount()): … … 1396 1374 self.widget.cbModel.setCurrentIndex(model_index) 1397 1375 1376 # select two rows 1398 1377 row1 = 1 1399 row2 = 5 1400 1401 # select two rows 1378 row2 = 4 1402 1379 index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 1403 1380 index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) … … 1413 1390 constraint_objects[0].active = False 1414 1391 1415 con_list = [False, False, False, False, False,True, False]1392 con_list = [False, False, False, False, True, False] 1416 1393 new_list = [] 1417 1394 for row in range(self.widget._model_model.rowCount()): … … 1434 1411 self.assertEqual(self.widget.getConstraintsForModel(),[]) 1435 1412 1413 # select two rows 1436 1414 row1 = 1 1437 row2 = 5 1438 1439 param1 = "background" 1440 param2 = "radius" 1441 1442 default_value1 = "0.001" 1443 default_value2 = "20" 1444 1445 # select two rows 1415 row2 = 4 1446 1416 index1 = self.widget.lstParams.model().index(row1, 0, QtCore.QModelIndex()) 1447 1417 index2 = self.widget.lstParams.model().index(row2, 0, QtCore.QModelIndex()) … … 1455 1425 # simple constraints 1456 1426 # self.assertEqual(self.widget.getConstraintsForModel(), [('background', '0.001'), ('radius', '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)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") 1463 1433 1464 1434 objects = self.widget.getConstraintObjectsForModel() 1465 1435 self.assertEqual(len(objects), 2) 1466 self.assertEqual(objects[1].value, default_value2) 1467 self.assertEqual(objects[0].param, param1) 1468 1436 self.assertEqual(objects[1].value, '20') 1437 self.assertEqual(objects[0].param, 'background') 1438 1439 # add complex constraint 1440 const = Constraint(parent=None, param='scale', func='5*sld') 1469 1441 row = 0 1470 param = "scale"1471 func = "5*sld"1472 1473 # add complex constraint1474 const = Constraint(parent=None, param=param, func=func)1475 1442 self.widget.addConstraintToRow(constraint=const, row=row) 1476 1443 #self.assertEqual(self.widget.getConstraintsForModel(),[('scale', '5*sld'), ('background', '0.001'), ('radius', None)]) 1477 cons = self.widget.getConstraintForRow( row2)1478 self.assertEqual(cons.param, param2)1479 self.assertEqual(cons.value, default_value2)1444 cons = self.widget.getConstraintForRow(4) # 4 = radius 1445 self.assertEqual(cons.param, "radius") 1446 self.assertEqual(cons.value, "20") 1480 1447 1481 1448 objects = self.widget.getConstraintObjectsForModel() 1482 1449 self.assertEqual(len(objects), 3) 1483 self.assertEqual(objects[0].func, func)1450 self.assertEqual(objects[0].func, '5*sld') 1484 1451 1485 1452 def testReplaceConstraintName(self): -
src/sas/qtgui/Plotting/Plotter.py
rc2f3ca2 rb764ae5 30 30 # Dictionary of {plot_id:Data1d} 31 31 self.plot_dict = {} 32 # Dictionaty of {plot_id:line} 33 34 self.plot_lines = {} 32 35 33 # Window for text add 36 34 self.addText = AddText(self) … … 184 182 self.plot_dict[self._data.id] = self.data 185 183 186 self.plot_lines[self._data.id] = line187 188 184 # Now add the legend with some customizations. 189 185 … … 200 196 201 197 # refresh canvas 202 self.canvas.draw ()198 self.canvas.draw_idle() 203 199 # This is an important processEvent. 204 200 # This allows charts to be properly updated in order … … 420 416 This effectlvely refreshes the chart with changes to one of its plots 421 417 """ 422 import logging423 418 self.removePlot(id) 424 419 self.plot(data=new_plot) … … 475 470 """ 476 471 selected_plot = self.plot_dict[id] 477 selected_line = self.plot_lines[id] 472 478 473 # Old style color - single integer for enum color 479 474 # New style color - #hhhhhh
Note: See TracChangeset
for help on using the changeset viewer.