Changeset be8f4b0 in sasview for src/sas/qtgui
- Timestamp:
- Jan 16, 2018 4:50:31 AM (7 years ago)
- Branches:
- ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- 47d7d2d
- Parents:
- 676f137
- Location:
- src/sas/qtgui
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py
r676f137 rbe8f4b0 8 8 9 9 from sas.qtgui.Perspectives.Fitting.UI.ConstraintWidgetUI import Ui_ConstraintWidgetUI 10 from sas.qtgui.Perspectives.Fitting.FittingWidget import FittingWidget 10 11 11 12 class ConstraintWidget(QtWidgets.QWidget, Ui_ConstraintWidgetUI): 12 13 """ 13 Constraints Dialog to select the desired parameter/model constraints 14 Constraints Dialog to select the desired parameter/model constraints. 14 15 """ 15 16 … … 20 21 self.currentType = "FitPage" 21 22 23 # Set up the widgets 24 self.initializeWidgets() 25 22 26 # Set up signals/slots 23 27 self.initializeSignals() 24 28 25 29 # Create the list of tabs 26 self.updateFitList() 30 self.initializeFitList() 31 32 def acceptsData(self): 33 """ Tells the caller this widget doesn't accept data """ 34 return False 35 36 def initializeWidgets(self): 37 """ 38 Set up various widget states 39 """ 40 labels = ['FitPage', 'Model', 'Data', 'Mnemonics'] 41 # tab widget - headers 42 self.tblTabList.setColumnCount(len(labels)) 43 self.tblTabList.setHorizontalHeaderLabels(labels) 44 self.tblTabList.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) 45 46 self.tblTabList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 47 self.tblTabList.customContextMenuRequested.connect(self.showModelContextMenu) 48 49 # disabled constraint 50 labels = ['Constraint'] 51 self.tblConstraints.setColumnCount(len(labels)) 52 self.tblConstraints.setHorizontalHeaderLabels(labels) 53 self.tblConstraints.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) 54 self.tblConstraints.setEnabled(False) 55 56 self.tblConstraints.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) 57 self.tblConstraints.customContextMenuRequested.connect(self.showConstrContextMenu) 27 58 28 59 def initializeSignals(self): … … 32 63 self.btnSingle.toggled.connect(self.onFitTypeChange) 33 64 self.btnBatch.toggled.connect(self.onFitTypeChange) 34 self.cb Series.indexChanged.connect(self.onSpecialCaseChange)65 self.cbCases.currentIndexChanged.connect(self.onSpecialCaseChange) 35 66 self.cmdFit.clicked.connect(self.onFit) 36 67 self.cmdHelp.clicked.connect(self.onHelp) 68 self.parent.tabsModifiedSignal.connect(self.initializeFitList) 69 70 def updateSignalsFromTab(self, tab=None): 71 """ 72 Intercept update signals from fitting tabs 73 """ 74 if tab is not None: 75 ObjectLibrary.getObject(tab).constraintAddedSignal.connect(self.initializeFitList) 76 ObjectLibrary.getObject(tab).newModelSignal.connect(self.initializeFitList) 37 77 38 78 def onFitTypeChange(self, checked): … … 61 101 pass 62 102 63 def updateFitList(self): 103 def isTabImportable(self, tab): 104 """ 105 Determines if the tab can be imported and included in the widget 106 """ 107 if not self.currentType in tab: return False 108 object = ObjectLibrary.getObject(tab) 109 if not isinstance(object, FittingWidget): return False 110 if object.data is None: return False 111 return True 112 113 def showModelContextMenu(self, position): 114 """ 115 Show context specific menu in the tab table widget. 116 """ 117 menu = QtWidgets.QMenu() 118 rows = [s.row() for s in self.tblTabList.selectionModel().selectedRows()] 119 num_rows = len(rows) 120 if num_rows <= 0: 121 return 122 # Select for fitting 123 param_string = "Fit Page " if num_rows==1 else "Fit Pages " 124 to_string = "to its current value" if num_rows==1 else "to their current values" 125 126 self.actionSelect = QtWidgets.QAction(self) 127 self.actionSelect.setObjectName("actionSelect") 128 self.actionSelect.setText(QtCore.QCoreApplication.translate("self", "Select "+param_string+" for fitting")) 129 # Unselect from fitting 130 self.actionDeselect = QtWidgets.QAction(self) 131 self.actionDeselect.setObjectName("actionDeselect") 132 self.actionDeselect.setText(QtCore.QCoreApplication.translate("self", "De-select "+param_string+" from fitting")) 133 134 self.actionRemoveConstraint = QtWidgets.QAction(self) 135 self.actionRemoveConstraint.setObjectName("actionRemoveConstrain") 136 self.actionRemoveConstraint.setText(QtCore.QCoreApplication.translate("self", "Remove all constraints on selected models")) 137 138 self.actionMutualMultiConstrain = QtWidgets.QAction(self) 139 self.actionMutualMultiConstrain.setObjectName("actionMutualMultiConstrain") 140 self.actionMutualMultiConstrain.setText(QtCore.QCoreApplication.translate("self", "Mutual constrain of parameters in selected models...")) 141 142 menu.addAction(self.actionSelect) 143 menu.addAction(self.actionDeselect) 144 menu.addSeparator() 145 146 #menu.addAction(self.actionRemoveConstraint) 147 if num_rows >= 2: 148 menu.addAction(self.actionMutualMultiConstrain) 149 150 # Define the callbacks 151 #self.actionConstrain.triggered.connect(self.addSimpleConstraint) 152 #self.actionRemoveConstraint.triggered.connect(self.deleteConstraint) 153 #self.actionMutualMultiConstrain.triggered.connect(self.showMultiConstraint) 154 self.actionSelect.triggered.connect(self.selectModels) 155 self.actionDeselect.triggered.connect(self.deselectModels) 156 try: 157 menu.exec_(self.tblTabList.viewport().mapToGlobal(position)) 158 except AttributeError as ex: 159 logging.error("Error generating context menu: %s" % ex) 160 return 161 162 def showConstrContextMenu(self, position): 163 """ 164 Show context specific menu in the tab table widget. 165 """ 166 menu = QtWidgets.QMenu() 167 rows = [s.row() for s in self.tblConstraints.selectionModel().selectedRows()] 168 num_rows = len(rows) 169 if num_rows <= 0: 170 return 171 # Select for fitting 172 param_string = "constraint " if num_rows==1 else "constraints " 173 to_string = "to its current value" if num_rows==1 else "to their current values" 174 175 self.actionSelect = QtWidgets.QAction(self) 176 self.actionSelect.setObjectName("actionSelect") 177 self.actionSelect.setText(QtCore.QCoreApplication.translate("self", "Select "+param_string+" for fitting")) 178 # Unselect from fitting 179 self.actionDeselect = QtWidgets.QAction(self) 180 self.actionDeselect.setObjectName("actionDeselect") 181 self.actionDeselect.setText(QtCore.QCoreApplication.translate("self", "De-select "+param_string+" from fitting")) 182 183 self.actionRemoveConstraint = QtWidgets.QAction(self) 184 self.actionRemoveConstraint.setObjectName("actionRemoveConstrain") 185 self.actionRemoveConstraint.setText(QtCore.QCoreApplication.translate("self", "Remove "+param_string)) 186 187 menu.addAction(self.actionSelect) 188 menu.addAction(self.actionDeselect) 189 menu.addSeparator() 190 menu.addAction(self.actionRemoveConstraint) 191 192 # Define the callbacks 193 #self.actionConstrain.triggered.connect(self.addSimpleConstraint) 194 self.actionRemoveConstraint.triggered.connect(self.deleteConstraint) 195 #self.actionMutualMultiConstrain.triggered.connect(self.showMultiConstraint) 196 self.actionSelect.triggered.connect(self.selectConstraints) 197 self.actionDeselect.triggered.connect(self.deselectConstraints) 198 try: 199 menu.exec_(self.tblConstraints.viewport().mapToGlobal(position)) 200 except AttributeError as ex: 201 logging.error("Error generating context menu: %s" % ex) 202 return 203 204 def selectConstraints(self): 205 """ 206 Selected constraints are chosen for fitting 207 """ 208 status = QtCore.Qt.Checked 209 self.setRowSelection(self.tblConstraints, status) 210 211 def deselectConstraints(self): 212 """ 213 Selected constraints are removed for fitting 214 """ 215 status = QtCore.Qt.Unchecked 216 self.setRowSelection(self.tblConstraints, status) 217 218 def selectModels(self): 219 """ 220 Selected models are chosen for fitting 221 """ 222 status = QtCore.Qt.Checked 223 self.setRowSelection(self.tblTabList, status) 224 225 def deselectModels(self): 226 """ 227 Selected models are removed for fitting 228 """ 229 status = QtCore.Qt.Unchecked 230 self.setRowSelection(self.tblTabList, status) 231 232 def selectedParameters(self, widget): 233 """ Returns list of selected (highlighted) parameters """ 234 return [s.row() for s in widget.selectionModel().selectedRows()] 235 236 def setRowSelection(self, widget, status=QtCore.Qt.Unchecked): 237 """ 238 Selected models are chosen for fitting 239 """ 240 # Convert to proper indices and set requested enablement 241 for row in self.selectedParameters(widget): 242 widget.item(row, 0).setCheckState(status) 243 244 def deleteConstraint(self):#, row): 245 """ 246 Delete all selected constraints. 247 """ 248 constraints_to_delete = [] 249 for row in self.selectedParameters(self.tblConstraints): 250 constraints_to_delete.append(self.tblConstraints.item(row, 0).data(0)) 251 for constraint in constraints_to_delete: 252 moniker = constraint[:constraint.index(':')] 253 param = constraint[constraint.index(':')+1:constraint.index('=')].strip() 254 tab = self.available_tabs[moniker] 255 tab.deleteConstraintOnParameter(param) 256 # Constraints removed - refresh the table widget 257 self.initializeFitList() 258 259 def updateFitLine(self, tab): 260 """ 261 Update a single line of the table widget with tab info 262 """ 263 model = ObjectLibrary.getObject(tab).kernel_module 264 if model is None: 265 return 266 tab_name = tab 267 model_name = model.id 268 moniker = model.name 269 model_data = ObjectLibrary.getObject(tab).data 270 model_filename = model_data.filename 271 self.available_tabs[moniker] = ObjectLibrary.getObject(tab) 272 273 # Update the model table widget 274 item = QtWidgets.QTableWidgetItem(tab_name) 275 item.setCheckState(QtCore.Qt.Checked) 276 pos = self.tblTabList.rowCount() 277 self.tblTabList.insertRow(pos) 278 self.tblTabList.setItem(pos, 0, item) 279 self.tblTabList.setItem(pos, 1, QtWidgets.QTableWidgetItem(model_name)) 280 self.tblTabList.setItem(pos, 2, QtWidgets.QTableWidgetItem(model_filename)) 281 self.tblTabList.setItem(pos, 3, QtWidgets.QTableWidgetItem(moniker)) 282 283 #self.available_tabs[pos] = (model, model_data) 284 #self.available_tabs[moniker] = tab 285 286 # Check if any constraints present in tab 287 constraints = ObjectLibrary.getObject(tab).getConstraintsForModel() 288 if not constraints: 289 return 290 self.tblConstraints.setEnabled(True) 291 for constraint in constraints: 292 # Create the text for widget item 293 label = moniker + ":"+ constraint[0] + " = " + constraint[1] 294 295 # Show the text in the constraint table 296 item = QtWidgets.QTableWidgetItem(label) 297 item.setCheckState(QtCore.Qt.Checked) 298 pos = self.tblConstraints.rowCount() 299 self.tblConstraints.insertRow(pos) 300 self.tblConstraints.setItem(pos, 0, item) 301 self.available_constraints[pos] = constraints 302 303 def initializeFitList(self): 64 304 """ 65 305 Fill the list of model/data sets for fitting/constraining 66 306 """ 67 307 # look at the object library to find all fit tabs 308 # Show the content of the current "model" 68 309 objects = ObjectLibrary.listObjects() 310 311 # Tab dict 312 # moniker -> (kernel_module, data) 313 self.available_tabs = {} 314 # Constraint dict 315 # moniker -> [constraints] 316 self.available_constraints = {} 317 318 # Reset the table widgets 319 self.tblTabList.setRowCount(0) 320 self.tblConstraints.setRowCount(0) 321 322 # Fit disabled 323 self.cmdFit.setEnabled(False) 324 69 325 if not objects: 70 326 return 71 tabs = [tab for tab in ObjectLibrary.listObjects() if self.currentType in tab] 72 73 pass 74 75 def updateConstraintList(self): 76 """ 77 Fill the list of constraints for the current selection of model/data sets 78 """ 79 pass 80 81 327 328 tabs = [tab for tab in ObjectLibrary.listObjects() if self.isTabImportable(tab)] 329 for tab in tabs: 330 self.updateFitLine(tab) 331 self.updateSignalsFromTab(tab) 332 # We have at least 1 fit page, allow fitting 333 self.cmdFit.setEnabled(True) -
src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
r676f137 rbe8f4b0 18 18 """ 19 19 """ 20 tabsModifiedSignal = QtCore.pyqtSignal() 20 21 name = "Fitting" # For displaying in the combo box in DataExplorer 21 22 def __init__(self, parent=None, data=None): … … 117 118 self.maxIndex += 1 118 119 self.addTab(tab, tab_name) 120 self.tabsModifiedSignal.emit() 119 121 120 122 def addConstraintTab(self): … … 122 124 Add a new C&S fitting tab 123 125 """ 124 tab = ConstraintWidget(parent=self .parent)126 tab = ConstraintWidget(parent=self) 125 127 # Add this tab to the object library so it can be retrieved by scripting/jupyter 126 128 tab_name = self.getCSTabName() # TODO update the tab name scheme … … 182 184 self.removeTab(index) 183 185 del self.tabs[index] 186 self.tabsModifiedSignal.emit() 184 187 except IndexError: 185 188 # The tab might have already been deleted previously -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r676f137 rbe8f4b0 82 82 Main widget for selecting form and structure factor models 83 83 """ 84 #constraintAddedSignal = QtCore.pyqtSignal(list) 84 constraintAddedSignal = QtCore.pyqtSignal(list) 85 newModelSignal = QtCore.pyqtSignal() 85 86 def __init__(self, parent=None, data=None, tab_id=1): 86 87 … … 574 575 row = self.rowFromName(constraint.param) 575 576 self._model_model.item(row, 1).setChild(0, item) 576 #self.constraintAddedSignal.emit([row])577 self.constraintAddedSignal.emit([row]) 577 578 578 579 # Show visual hints for the constraint … … 626 627 max = self._model_model.item(row, max_col).text() 627 628 # Create a Constraint object 628 constraint = Constraint(param=param, value=value, min=min, max=max )629 constraint = Constraint(param=param, value=value, min=min, max=max, func=value) 629 630 # Create a new item and add the Constraint object as a child 630 631 item = QtGui.QStandardItem() … … 634 635 self._model_model.item(row, min_col).setText(value) 635 636 self._model_model.item(row, max_col).setText(value) 636 #self.constraintAddedSignal.emit([row])637 self.constraintAddedSignal.emit([row]) 637 638 # Show visual hints for the constraint 638 639 font = QtGui.QFont() … … 647 648 Delete constraints from selected parameters. 648 649 """ 650 self.deleteConstraintOnParameter(param=None) 651 652 def deleteConstraintOnParameter(self, param=None): 653 """ 654 Delete the constraint on model parameter 'param' 655 """ 649 656 min_col = self.lstParams.itemDelegate().param_min 650 657 max_col = self.lstParams.itemDelegate().param_max 651 for row in self.selectedParameters():658 for row in range(self._model_model.rowCount()): 652 659 # Get the Constraint object from of the model item 653 660 item = self._model_model.item(row, 1) … … 659 666 if not isinstance(constraint, Constraint): 660 667 continue 668 if param and constraint.param != param: 669 continue 670 # Now we got the right row. Delete the constraint and clean up 661 671 # Retrieve old values and put them on the model 662 672 if constraint.min is not None: … … 666 676 # Remove constraint item 667 677 item.removeRow(0) 668 #self.constraintAddedSignal.emit([row])678 self.constraintAddedSignal.emit([row]) 669 679 self.modifyViewOnRow(row) 680 break 681 670 682 self.communicate.statusBarUpdateSignal.emit('Constraint removed') 671 683 pass 684 672 685 673 686 def getConstraintForRow(self, row): … … 687 700 """ 688 701 item = self._model_model.item(row,1) 689 return True if (item.hasChildren() and isinstance(item.child(0).data(), Constraint)) else False 702 if item.hasChildren(): 703 c = item.child(0).data() 704 if isinstance(c, Constraint) and c.func: 705 return True 706 return False 707 #return True if (item.hasChildren() and isinstance(item.child(0).data(), Constraint)) else False 690 708 691 709 def selectParameters(self): … … 726 744 self.kernel_module.name = model_name 727 745 param_number = self._model_model.rowCount() 746 def preamble(s): 747 func = self._model_model.item(s, 1).child(0).data().func 748 value = self._model_model.item(s, 1).child(0).data().value 749 if func == value: 750 return "" 751 return model_name + "." 728 752 params = [(self._model_model.item(s, 0).text(), 729 model_name+"."+self._model_model.item(s, 1).child(0).data().func)753 preamble(s) +self._model_model.item(s, 1).child(0).data().func) 730 754 for s in range(param_number) if self.rowHasConstraint(s)] 731 755 return params … … 806 830 # Update state stack 807 831 self.updateUndo() 832 833 # Let others know 834 self.newModelSignal.emit() 808 835 809 836 def onSelectCategory(self): … … 1523 1550 # Now we claim the model has been loaded 1524 1551 self.model_is_loaded = True 1552 # Change the model name to a monicker 1553 self.kernel_module.name = self.modelName() 1525 1554 1526 1555 # (Re)-create headers -
src/sas/qtgui/Perspectives/Fitting/UI/ConstraintWidgetUI.ui
r676f137 rbe8f4b0 63 63 </sizepolicy> 64 64 </property> 65 <property name="contextMenuPolicy"> 66 <enum>Qt::ActionsContextMenu</enum> 67 </property> 65 68 <property name="alternatingRowColors"> 66 69 <bool>true</bool> … … 69 72 <enum>QAbstractItemView::SelectRows</enum> 70 73 </property> 71 <row>72 <property name="text">73 <string/>74 </property>75 </row>76 <row>77 <property name="text">78 <string/>79 </property>80 </row>81 <row>82 <property name="text">83 <string/>84 </property>85 </row>86 74 </widget> 87 75 </item> … … 122 110 <verstretch>0</verstretch> 123 111 </sizepolicy> 112 </property> 113 <property name="contextMenuPolicy"> 114 <enum>Qt::ActionsContextMenu</enum> 124 115 </property> 125 116 <column> -
src/sas/qtgui/Utilities/ObjectLibrary.py
- Property mode changed from 100755 to 100644
Note: See TracChangeset
for help on using the changeset viewer.