Changeset 21e71f1 in sasview for src/sas/qtgui/Perspectives
- Timestamp:
- Nov 21, 2018 8:39:24 AM (6 years ago)
- Branches:
- ESS_GUI, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc
- Children:
- f2e199e
- Parents:
- 44c15fc (diff), fb39f28 (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. - Location:
- src/sas/qtgui/Perspectives/Fitting
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/qtgui/Perspectives/Fitting/ComplexConstraint.py
r305114c rd72ac57 15 15 from sas.qtgui.Perspectives.Fitting import FittingUtilities 16 16 import sas.qtgui.Utilities.GuiUtils as GuiUtils 17 ALLOWED_OPERATORS = ['=','<','>','>=','<='] 17 from sas.qtgui.Perspectives.Fitting.Constraint import Constraint 18 19 #ALLOWED_OPERATORS = ['=','<','>','>=','<='] 20 ALLOWED_OPERATORS = ['='] 18 21 19 22 # Local UI … … 21 24 22 25 class ComplexConstraint(QtWidgets.QDialog, Ui_ComplexConstraintUI): 26 constraintReadySignal = QtCore.pyqtSignal(tuple) 23 27 def __init__(self, parent=None, tabs=None): 24 28 super(ComplexConstraint, self).__init__() … … 32 36 self.tab_names = None 33 37 self.operator = '=' 38 self._constraint = Constraint() 34 39 35 40 self.warning = self.lblWarning.text() … … 53 58 Signals from various elements 54 59 """ 55 self.cmdOK.clicked.connect(self. accept)60 self.cmdOK.clicked.connect(self.onApply) 56 61 self.cmdHelp.clicked.connect(self.onHelp) 57 62 self.cmdRevert.clicked.connect(self.onRevert) … … 69 74 self.txtName2.setText(self.tab_names[1]) 70 75 71 # Show only parameters not already constrained 76 self.setupParamWidgets() 77 78 # Add menu to the Apply button 79 all_menu = QtWidgets.QMenu() 80 self.actionAddAll = QtWidgets.QAction(self) 81 self.actionAddAll.setObjectName("actionAddAll") 82 self.actionAddAll.setText(QtCore.QCoreApplication.translate("self", "Add all")) 83 ttip = "Add constraints between all identically named parameters in both fitpages" 84 self.actionAddAll.setToolTip(ttip) 85 self.actionAddAll.triggered.connect(self.onSetAll) 86 all_menu.addAction(self.actionAddAll) 87 # https://bugreports.qt.io/browse/QTBUG-13663 88 all_menu.setToolTipsVisible(True) 89 self.cmdOK.setMenu(all_menu) 90 91 def setupParamWidgets(self): 92 """ 93 Fill out comboboxes and set labels with non-constrained parameters 94 """ 72 95 self.cbParam1.clear() 73 items = [param for i,param in enumerate(self.params[0]) if not self.tabs[0].rowHasConstraint(i)] 74 self.cbParam1.addItems(items) 96 items1 = [param for param in self.params[0] if not self.tabs[0].paramHasConstraint(param)] 97 self.cbParam1.addItems(items1) 98 99 # M2 doesn't have to be non-constrained 75 100 self.cbParam2.clear() 76 items = [param for i,param in enumerate(self.params[1]) if not self.tabs[1].rowHasConstraint(i)] 77 self.cbParam2.addItems(items) 101 #items2 = [param for param in self.params[1] if not self.tabs[1].paramHasConstraint(param)] 102 items2 = [param for param in self.params[1]] 103 self.cbParam2.addItems(items2) 78 104 79 105 self.txtParam.setText(self.tab_names[0] + ":" + self.cbParam1.currentText()) … … 84 110 85 111 self.txtConstraint.setText(self.tab_names[1]+"."+self.cbParam2.currentText()) 112 113 # disable Apply if no parameters available 114 if len(items1)==0: 115 self.cmdOK.setEnabled(False) 116 txt = "No parameters in model "+self.tab_names[0] +\ 117 " are available for constraining." 118 self.lblWarning.setText(txt) 119 else: 120 self.cmdOK.setEnabled(True) 121 txt = "" 122 self.lblWarning.setText(txt) 86 123 87 124 def setupTooltip(self): … … 144 181 145 182 # Original indices 183 index2 = index2 if index2 >= 0 else 0 184 index1 = index1 if index1 >= 0 else 0 146 185 self.cbParam1.setCurrentIndex(index2) 147 186 self.cbParam2.setCurrentIndex(index1) … … 205 244 def constraint(self): 206 245 """ 207 Return the generated constraint as tuple (model1, param1, operator, constraint) 208 """ 209 return (self.txtName1.text(), self.cbParam1.currentText(), self.cbOperator.currentText(), self.txtConstraint.text()) 246 Return the generated constraint 247 """ 248 param = self.cbParam1.currentText() 249 value = self.cbParam2.currentText() 250 func = self.txtConstraint.text() 251 value_ex = self.txtName2.text() + "." + self.cbParam2.currentText() 252 model1 = self.txtName1.text() 253 operator = self.cbOperator.currentText() 254 255 con = Constraint(self, 256 param=param, 257 value=value, 258 func=func, 259 value_ex=value_ex, 260 operator=operator) 261 262 return (model1, con) 263 264 def onApply(self): 265 """ 266 Respond to Add constraint action. 267 Send a signal that the constraint is ready to be applied 268 """ 269 cons_tuple = self.constraint() 270 self.constraintReadySignal.emit(cons_tuple) 271 # reload the comboboxes 272 self.setupParamWidgets() 273 274 def onSetAll(self): 275 """ 276 Set constraints on all identically named parameters between two fitpages 277 """ 278 # loop over parameters in constrained model 279 items1 = [param for param in self.params[0] if not self.tabs[0].paramHasConstraint(param)] 280 #items2 = [param for param in self.params[1] if not self.tabs[1].paramHasConstraint(i)] 281 items2 = self.params[1] 282 for item in items1: 283 if item not in items2: continue 284 param = item 285 value = item 286 func = self.txtName2.text() + "." + param 287 value_ex = self.txtName1.text() + "." + param 288 model1 = self.txtName1.text() 289 operator = self.cbOperator.currentText() 290 291 con = Constraint(self, 292 param=param, 293 value=value, 294 func=func, 295 value_ex=value_ex, 296 operator=operator) 297 298 self.constraintReadySignal.emit((model1, con)) 299 300 # reload the comboboxes 301 self.setupParamWidgets() 210 302 211 303 def onHelp(self): -
src/sas/qtgui/Perspectives/Fitting/Constraint.py
r14ec91c5 r09e0c32 5 5 hence made into a class. 6 6 """ 7 def __init__(self, parent=None, param=None, value=0.0, min=None, max=None, func=None): 7 def __init__(self, parent=None, param=None, value=0.0, 8 min=None, max=None, func=None, value_ex=None, 9 operator="="): 8 10 self._value = value 9 11 self._param = param 12 self._value_ex = value_ex 10 13 self._func = func 11 self.active = True12 14 self._min = min 13 15 self._max = max 16 self._operator = operator 17 self.validate = True 18 self.active = True 14 19 15 20 @property 16 21 def value(self): 22 # value/parameter to fit to (e.g. 1.0 or sld) 17 23 return self._value 18 24 … … 22 28 23 29 @property 30 def value_ex(self): 31 # full parameter name to fit to (e.g. M1.sld) 32 return self._value_ex 33 34 @value_ex.setter 35 def value_ex(self, val): 36 self._value_ex = val 37 38 @property 24 39 def param(self): 40 # parameter which is being fitted 25 41 return self._param 26 42 … … 31 47 @property 32 48 def func(self): 49 # Function to be used for constraint 50 # e.g. sqrt(M1.sld+1.0) 33 51 return self._func 34 52 … … 39 57 @property 40 58 def min(self): 59 # min param value for single value constraints 41 60 return self._min 42 61 … … 47 66 @property 48 67 def max(self): 68 # max param value for single value constraints 49 69 return self._max 50 70 … … 53 73 self._max = val 54 74 75 @property 76 def operator(self): 77 # operator to use for constraint 78 return self._operator 79 80 @operator.setter 81 def operator(self, val): 82 self._operator = val 83 -
src/sas/qtgui/Perspectives/Fitting/ConstraintWidget.py
rc4c4957 r21e71f1 23 23 Constraints Dialog to select the desired parameter/model constraints. 24 24 """ 25 fitCompleteSignal = QtCore.pyqtSignal(tuple) 26 batchCompleteSignal = QtCore.pyqtSignal(tuple) 27 fitFailedSignal = QtCore.pyqtSignal(tuple) 25 28 26 29 def __init__(self, parent=None): … … 32 35 # To keep with previous SasView values, use 300 as the start offset 33 36 self.page_id = 301 37 self.tab_id = self.page_id 34 38 35 39 # Are we chain fitting? … … 60 64 Set up various widget states 61 65 """ 66 # disable special cases until properly defined 67 self.label.setVisible(False) 68 self.cbCases.setVisible(False) 69 62 70 labels = ['FitPage', 'Model', 'Data', 'Mnemonic'] 63 71 # tab widget - headers … … 79 87 self.tblConstraints.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch) 80 88 self.tblConstraints.setEnabled(False) 89 header = self.tblConstraints.horizontalHeaderItem(0) 90 header.setToolTip("Double click a row below to edit the constraint.") 81 91 82 92 self.tblConstraints.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) … … 93 103 self.cmdFit.clicked.connect(self.onFit) 94 104 self.cmdHelp.clicked.connect(self.onHelp) 105 self.cmdAdd.clicked.connect(self.showMultiConstraint) 95 106 self.chkChain.toggled.connect(self.onChainFit) 96 107 … … 100 111 self.tblConstraints.cellChanged.connect(self.onConstraintChange) 101 112 113 # Internal signals 114 self.fitCompleteSignal.connect(self.fitComplete) 115 self.batchCompleteSignal.connect(self.batchComplete) 116 self.fitFailedSignal.connect(self.fitFailed) 117 102 118 # External signals 103 119 self.parent.tabsModifiedSignal.connect(self.initializeFitList) … … 156 172 fitter = Fit() 157 173 fitter.fitter_id = self.page_id 158 159 # Notify the parent about fitting started160 self.parent.fittingStartedSignal.emit(tabs_to_fit)161 174 162 175 # prepare fitting problems for each tab … … 168 181 try: 169 182 for tab in tabs_to_fit: 183 if not self.isTabImportable(tab): continue 170 184 tab_object = ObjectLibrary.getObject(tab) 171 185 if tab_object is None: … … 177 191 except ValueError: 178 192 # No parameters selected in one of the tabs 179 no_params_msg = "Fitting can 193 no_params_msg = "Fitting cannot be performed.\n" +\ 180 194 "Not all tabs chosen for fitting have parameters selected for fitting." 181 195 QtWidgets.QMessageBox.warning(self, … … 200 214 batch_inputs = {} 201 215 batch_outputs = {} 216 217 # Notify the parent about fitting started 218 self.parent.fittingStartedSignal.emit(tabs_to_fit) 202 219 203 220 # new fit thread object … … 223 240 224 241 #disable the Fit button 242 self.cmdFit.setStyleSheet('QPushButton {color: red;}') 225 243 self.cmdFit.setText('Running...') 226 244 self.parent.communicate.statusBarUpdateSignal.emit('Fitting started...') … … 292 310 """ 293 311 item = self.tblConstraints.item(row, column) 294 if column == 0: 295 # Update the tabs for fitting list 296 constraint = self.available_constraints[row] 297 constraint.active = (item.checkState() == QtCore.Qt.Checked) 312 if column != 0: return 313 # Update the tabs for fitting list 314 constraint = self.available_constraints[row] 315 constraint.active = (item.checkState() == QtCore.Qt.Checked) 316 # Update the constraint formula 317 constraint = self.available_constraints[row] 318 function = item.text() 319 # remove anything left of '=' to get the constraint 320 function = function[function.index('=')+1:] 321 # No check on function here - trust the user (R) 322 if function != constraint.func: 323 # This becomes rather difficult to validate now. 324 # Turn off validation for Edit Constraint 325 constraint.func = function 326 constraint.validate = False 298 327 299 328 def onTabCellEntered(self, row, column): … … 308 337 def onFitComplete(self, result): 309 338 """ 339 Send the fit complete signal to main thread 340 """ 341 self.fitCompleteSignal.emit(result) 342 343 def fitComplete(self, result): 344 """ 310 345 Respond to the successful fit complete signal 311 346 """ 312 347 #re-enable the Fit button 348 self.cmdFit.setStyleSheet('QPushButton {color: black;}') 313 349 self.cmdFit.setText("Fit") 314 350 self.cmdFit.setEnabled(True) … … 347 383 def onBatchFitComplete(self, result): 348 384 """ 385 Send the fit complete signal to main thread 386 """ 387 self.batchCompleteSignal.emit(result) 388 389 def batchComplete(self, result): 390 """ 349 391 Respond to the successful batch fit complete signal 350 392 """ 351 393 #re-enable the Fit button 394 self.cmdFit.setStyleSheet('QPushButton {color: black;}') 352 395 self.cmdFit.setText("Fit") 353 396 self.cmdFit.setEnabled(True) … … 375 418 def onFitFailed(self, reason): 376 419 """ 420 Send the fit failed signal to main thread 421 """ 422 self.fitFailedSignal.emit(result) 423 424 def fitFailed(self, reason): 425 """ 377 426 Respond to fitting failure. 378 427 """ 379 428 #re-enable the Fit button 429 self.cmdFit.setStyleSheet('QPushButton {color: black;}') 380 430 self.cmdFit.setText("Fit") 381 431 self.cmdFit.setEnabled(True) … … 386 436 msg = "Fitting failed: %s s.\n" % reason 387 437 self.parent.communicate.statusBarUpdateSignal.emit(msg) 388 438 389 439 def isTabImportable(self, tab): 390 440 """ … … 599 649 # Show the text in the constraint table 600 650 item = self.uneditableItem(label) 651 item = QtWidgets.QTableWidgetItem(label) 601 652 item.setFlags(item.flags() ^ QtCore.Qt.ItemIsUserCheckable) 602 653 item.setCheckState(QtCore.Qt.Checked) … … 667 718 return None 668 719 720 def onAcceptConstraint(self, con_tuple): 721 """ 722 Receive constraint tuple from the ComplexConstraint dialog and adds contraint 723 """ 724 #"M1, M2, M3" etc 725 model_name, constraint = con_tuple 726 constrained_tab = self.getObjectByName(model_name) 727 if constrained_tab is None: 728 return 729 730 # Find the constrained parameter row 731 constrained_row = constrained_tab.getRowFromName(constraint.param) 732 733 # Update the tab 734 constrained_tab.addConstraintToRow(constraint, constrained_row) 735 736 # Select this parameter for adjusting/fitting 737 constrained_tab.selectCheckbox(constrained_row) 738 739 669 740 def showMultiConstraint(self): 670 741 """ … … 672 743 """ 673 744 selected_rows = self.selectedParameters(self.tblTabList) 674 assert(len(selected_rows)==2) 745 if len(selected_rows)!=2: 746 msg = "Please select two fit pages from the Source Choice table." 747 msgbox = QtWidgets.QMessageBox(self.parent) 748 msgbox.setIcon(QtWidgets.QMessageBox.Warning) 749 msgbox.setText(msg) 750 msgbox.setWindowTitle("2 fit page constraints") 751 retval = msgbox.exec_() 752 return 675 753 676 754 tab_list = [ObjectLibrary.getObject(self.tblTabList.item(s, 0).data(0)) for s in selected_rows] 677 755 # Create and display the widget for param1 and param2 678 756 cc_widget = ComplexConstraint(self, tabs=tab_list) 757 cc_widget.constraintReadySignal.connect(self.onAcceptConstraint) 758 679 759 if cc_widget.exec_() != QtWidgets.QDialog.Accepted: 680 760 return 681 761 682 constraint = Constraint() 683 model1, param1, operator, constraint_text = cc_widget.constraint() 684 685 constraint.func = constraint_text 686 # param1 is the parameter we're constraining 687 constraint.param = param1 688 689 # Find the right tab 690 constrained_tab = self.getObjectByName(model1) 691 if constrained_tab is None: 692 return 693 694 # Find the constrained parameter row 695 constrained_row = constrained_tab.getRowFromName(param1) 696 697 # Update the tab 698 constrained_tab.addConstraintToRow(constraint, constrained_row) 762 def getFitPage(self): 763 """ 764 Retrieves the state of this page 765 """ 766 param_list = [] 767 768 param_list.append(['is_constraint', 'True']) 769 param_list.append(['data_id', "cs_tab"+str(self.page_id)]) 770 param_list.append(['current_type', self.currentType]) 771 param_list.append(['is_chain_fitting', str(self.is_chain_fitting)]) 772 param_list.append(['special_case', self.cbCases.currentText()]) 773 774 return param_list 775 776 def getFitModel(self): 777 """ 778 Retrieves current model 779 """ 780 model_list = [] 781 782 checked_models = {} 783 for row in range(self.tblTabList.rowCount()): 784 model_name = self.tblTabList.item(row,1).data(0) 785 active = self.tblTabList.item(row,0).checkState()# == QtCore.Qt.Checked 786 checked_models[model_name] = str(active) 787 788 checked_constraints = {} 789 for row in range(self.tblConstraints.rowCount()): 790 model_name = self.tblConstraints.item(row,0).data(0) 791 active = self.tblConstraints.item(row,0).checkState()# == QtCore.Qt.Checked 792 checked_constraints[model_name] = str(active) 793 794 model_list.append(['checked_models', checked_models]) 795 model_list.append(['checked_constraints', checked_constraints]) 796 return model_list 797 798 def createPageForParameters(self, parameters=None): 799 """ 800 Update the page with passed parameter values 801 """ 802 # checked models 803 if not 'checked_models' in parameters: 804 return 805 models = parameters['checked_models'][0] 806 for model, check_state in models.items(): 807 for row in range(self.tblTabList.rowCount()): 808 model_name = self.tblTabList.item(row,1).data(0) 809 if model_name != model: 810 continue 811 # check/uncheck item 812 self.tblTabList.item(row,0).setCheckState(int(check_state)) 813 814 if not 'checked_constraints' in parameters: 815 return 816 # checked constraints 817 models = parameters['checked_constraints'][0] 818 for model, check_state in models.items(): 819 for row in range(self.tblConstraints.rowCount()): 820 model_name = self.tblConstraints.item(row,0).data(0) 821 if model_name != model: 822 continue 823 # check/uncheck item 824 self.tblConstraints.item(row,0).setCheckState(int(check_state)) 825 826 # fit/batch radio 827 isBatch = parameters['current_type'][0] == 'BatchPage' 828 if isBatch: 829 self.btnBatch.toggle() 830 831 # chain 832 is_chain = parameters['is_chain_fitting'][0] == 'True' 833 if isBatch: 834 self.chkChain.setChecked(is_chain) -
src/sas/qtgui/Perspectives/Fitting/FittingPerspective.py
rd2007a8 rfb39f28 1 1 import numpy 2 import copy 2 3 3 4 from PyQt5 import QtCore … … 10 11 import sas.qtgui.Utilities.LocalConfig as LocalConfig 11 12 import sas.qtgui.Utilities.ObjectLibrary as ObjectLibrary 13 import sas.qtgui.Utilities.GuiUtils as GuiUtils 12 14 13 15 from sas.qtgui.Perspectives.Fitting.FittingWidget import FittingWidget … … 37 39 self.maxIndex = 1 38 40 39 ## Index of the current tab40 #self.currentTab = 041 42 41 # The default optimizer 43 42 self.optimizer = 'Levenberg-Marquardt' … … 85 84 self.updateWindowTitle() 86 85 86 # Add new tab mini-button 87 self.plusButton = QtWidgets.QToolButton(self) 88 self.plusButton.setText("+") 89 self.setCornerWidget(self.plusButton) 90 self.plusButton.setToolTip("Add a new Fit Page") 91 self.plusButton.clicked.connect(lambda: self.addFit(None)) 92 87 93 def updateWindowTitle(self): 88 94 """ … … 112 118 def onLatexCopy(self): 113 119 self.currentTab.onCopyToClipboard("Latex") 120 121 def serializeAllFitpage(self): 122 # serialize all active fitpages and return 123 # a dictionary: {data_id: fitpage_state} 124 params = {} 125 for i, tab in enumerate(self.tabs): 126 tab_data = self.getSerializedFitpage(tab) 127 if 'data_id' not in tab_data: continue 128 id = tab_data['data_id'][0] 129 if isinstance(id, list): 130 for i in id: 131 if i in params: 132 params[i].append(tab_data) 133 else: 134 params[i] = [tab_data] 135 else: 136 if id in params: 137 params[id].append(tab_data) 138 else: 139 params[id] = [tab_data] 140 return params 141 142 def serializeCurrentFitpage(self): 143 # serialize current(active) fitpage 144 return self.getSerializedFitpage(self.currentTab) 145 146 def getSerializedFitpage(self, tab): 147 """ 148 get serialize requested fit tab 149 """ 150 fitpage_state = tab.getFitPage() 151 fitpage_state += tab.getFitModel() 152 # put the text into dictionary 153 line_dict = {} 154 for line in fitpage_state: 155 #content = line.split(',') 156 if len(line) > 1: 157 line_dict[line[0]] = line[1:] 158 return line_dict 159 160 def currentTabDataId(self): 161 """ 162 Returns the data ID of the current tab 163 """ 164 tab_id = [] 165 if not self.currentTab.data: 166 return tab_id 167 for item in self.currentTab.all_data: 168 data = GuiUtils.dataFromItem(item) 169 tab_id.append(data.id) 170 171 return tab_id 172 173 def updateFromParameters(self, parameters): 174 """ 175 Pass the update parameters to the current fit page 176 """ 177 self.currentTab.createPageForParameters(parameters) 114 178 115 179 def closeEvent(self, event): … … 246 310 for index_to_delete in index_list: 247 311 index_to_delete_str = str(index_to_delete) 248 if index_to_delete_str in list(self.dataToFitTab.keys()): 249 for tab_name in self.dataToFitTab[index_to_delete_str]: 250 # delete tab #index after corresponding data got removed 251 self.closeTabByName(tab_name) 252 self.dataToFitTab.pop(index_to_delete_str) 312 orig_dict = copy.deepcopy(self.dataToFitTab) 313 for tab_key in orig_dict.keys(): 314 if index_to_delete_str in tab_key: 315 for tab_name in orig_dict[tab_key]: 316 self.closeTabByName(tab_name) 317 self.dataToFitTab.pop(tab_key) 253 318 254 319 def allowBatch(self): 255 320 """ 256 321 Tell the caller that we accept multiple data instances 322 """ 323 return True 324 325 def isSerializable(self): 326 """ 327 Tell the caller that this perspective writes its state 257 328 """ 258 329 return True … … 337 408 pass 338 409 410 def getCurrentStateAsXml(self): 411 """ 412 Returns an XML version of the current state 413 """ 414 state = {} 415 for tab in self.tabs: 416 pass 417 return state 418 339 419 @property 340 420 def currentTab(self): -
src/sas/qtgui/Perspectives/Fitting/FittingWidget.py
r7f41584 r21e71f1 52 52 TAB_POLY = 3 53 53 CATEGORY_DEFAULT = "Choose category..." 54 MODEL_DEFAULT = "Choose model..." 54 55 CATEGORY_STRUCTURE = "Structure Factor" 55 56 CATEGORY_CUSTOM = "Plugin Models" … … 574 575 # Signals from other widgets 575 576 self.communicate.customModelDirectoryChanged.connect(self.onCustomModelChange) 576 self.communicate.saveAnalysisSignal.connect(self.savePageState)577 #self.communicate.loadAnalysisSignal.connect(self.loadPageState)578 577 self.smearing_widget.smearingChangedSignal.connect(self.onSmearingOptionsUpdate) 579 578 … … 623 622 to_string = "to its current value" if num_rows == 1 else "to their current values" 624 623 has_constraints = any([self.rowHasConstraint(i) for i in rows]) 624 has_real_constraints = any([self.rowHasActiveConstraint(i) for i in rows]) 625 625 626 626 self.actionSelect = QtWidgets.QAction(self) … … 640 640 self.actionRemoveConstraint.setText(QtCore.QCoreApplication.translate("self", "Remove constraint")) 641 641 642 self.actionEditConstraint = QtWidgets.QAction(self) 643 self.actionEditConstraint.setObjectName("actionEditConstrain") 644 self.actionEditConstraint.setText(QtCore.QCoreApplication.translate("self", "Edit constraint")) 645 642 646 self.actionMultiConstrain = QtWidgets.QAction(self) 643 647 self.actionMultiConstrain.setObjectName("actionMultiConstrain") … … 654 658 if has_constraints: 655 659 menu.addAction(self.actionRemoveConstraint) 660 if num_rows == 1 and has_real_constraints: 661 menu.addAction(self.actionEditConstraint) 656 662 #if num_rows == 1: 657 663 # menu.addAction(self.actionEditConstraint) … … 664 670 self.actionConstrain.triggered.connect(self.addSimpleConstraint) 665 671 self.actionRemoveConstraint.triggered.connect(self.deleteConstraint) 672 self.actionEditConstraint.triggered.connect(self.editConstraint) 666 673 self.actionMutualMultiConstrain.triggered.connect(self.showMultiConstraint) 667 674 self.actionSelect.triggered.connect(self.selectParameters) … … 701 708 new_func = c_text.replace(param_used, updated_param_used) 702 709 constraint.func = new_func 710 constraint.value_ex = updated_param_used 703 711 # Which row is the constrained parameter in? 704 712 row = self.getRowFromName(constraint.param) 713 714 # what is the parameter to constraint to? 715 constraint.value = param_used 716 717 # Should the new constraint be validated? 718 constraint.validate = mc_widget.validate 705 719 706 720 # Create a new item and add the Constraint object as a child … … 799 813 self.communicate.statusBarUpdateSignal.emit('Constraint added') 800 814 815 def editConstraint(self): 816 """ 817 Delete constraints from selected parameters. 818 """ 819 params_list = [s.data() for s in self.lstParams.selectionModel().selectedRows() 820 if self.isCheckable(s.row())] 821 assert len(params_list) == 1 822 row = self.lstParams.selectionModel().selectedRows()[0].row() 823 constraint = self.getConstraintForRow(row) 824 # Create and display the widget for param1 and param2 825 mc_widget = MultiConstraint(self, params=params_list, constraint=constraint) 826 # Check if any of the parameters are polydisperse 827 if not np.any([FittingUtilities.isParamPolydisperse(p, self.model_parameters, is2D=self.is2D) for p in params_list]): 828 # no parameters are pd - reset the text to not show the warning 829 mc_widget.lblWarning.setText("") 830 if mc_widget.exec_() != QtWidgets.QDialog.Accepted: 831 return 832 833 constraint = Constraint() 834 c_text = mc_widget.txtConstraint.text() 835 836 # widget.params[0] is the parameter we're constraining 837 constraint.param = mc_widget.params[0] 838 # parameter should have the model name preamble 839 model_name = self.kernel_module.name 840 # param_used is the parameter we're using in constraining function 841 param_used = mc_widget.params[1] 842 # Replace param_used with model_name.param_used 843 updated_param_used = model_name + "." + param_used 844 # Update constraint with new values 845 constraint.func = c_text 846 constraint.value_ex = updated_param_used 847 constraint.value = param_used 848 # Should the new constraint be validated? 849 constraint.validate = mc_widget.validate 850 851 # Which row is the constrained parameter in? 852 row = self.getRowFromName(constraint.param) 853 854 # Create a new item and add the Constraint object as a child 855 self.addConstraintToRow(constraint=constraint, row=row) 856 801 857 def deleteConstraint(self): 802 858 """ … … 853 909 return None 854 910 911 def allParamNames(self): 912 """ 913 Returns a list of all parameter names defined on the current model 914 """ 915 all_params = self.kernel_module._model_info.parameters.kernel_parameters 916 all_param_names = [param.name for param in all_params] 917 # Assure scale and background are always included 918 if 'scale' not in all_param_names: 919 all_param_names.append('scale') 920 if 'background' not in all_param_names: 921 all_param_names.append('background') 922 return all_param_names 923 924 def paramHasConstraint(self, param=None): 925 """ 926 Finds out if the given parameter in the main model has a constraint child 927 """ 928 if param is None: return False 929 if param not in self.allParamNames(): return False 930 931 for row in range(self._model_model.rowCount()): 932 if self._model_model.item(row,0).text() != param: continue 933 return self.rowHasConstraint(row) 934 935 # nothing found 936 return False 937 855 938 def rowHasConstraint(self, row): 856 939 """ … … 1018 1101 Checks if the current model has magnetic scattering implemented 1019 1102 """ 1020 has_ params = False1103 has_mag_params = False 1021 1104 if self.kernel_module: 1022 1105 has_mag_params = len(self.kernel_module.magnetic_params) > 0 … … 1029 1112 model = self.cbModel.currentText() 1030 1113 1114 if model == MODEL_DEFAULT: 1115 # if the previous category was not the default, keep it. 1116 # Otherwise, just return 1117 if self._previous_model_index != 0: 1118 # We need to block signals, or else state changes on perceived unchanged conditions 1119 self.cbModel.blockSignals(True) 1120 self.cbModel.setCurrentIndex(self._previous_model_index) 1121 self.cbModel.blockSignals(False) 1122 return 1123 1031 1124 # Assure the control is active 1032 1125 if not self.cbModel.isEnabled(): … … 1035 1128 if not model: 1036 1129 return 1130 1131 self.chkMagnetism.setEnabled(self.canHaveMagnetism()) 1132 self.chkMagnetism.setEnabled(self.canHaveMagnetism()) 1133 self.tabFitting.setTabEnabled(TAB_MAGNETISM, self.chkMagnetism.isChecked() and self.canHaveMagnetism()) 1134 self._previous_model_index = self.cbModel.currentIndex() 1037 1135 1038 1136 # Reset parameters to fit … … 1213 1311 self._model_model.clear() 1214 1312 return 1215 1313 # Wipe out the parameter model 1314 self._model_model.clear() 1216 1315 # Safely clear and enable the model combo 1217 1316 self.cbModel.blockSignals(True) … … 1225 1324 model_list = self.master_category_dict[category] 1226 1325 # Populate the models combobox 1326 self.cbModel.blockSignals(True) 1327 self.cbModel.addItem(MODEL_DEFAULT) 1227 1328 self.cbModel.addItems(sorted([model for (model, _) in model_list])) 1329 self.cbModel.blockSignals(False) 1228 1330 1229 1331 def onPolyModelChange(self, top, bottom): … … 1937 2039 Emits plotRequestedSignal for all plots found in the given model under the provided item name. 1938 2040 """ 1939 fitpage_name = "" if self.tab_id is None else "M"+str(self.tab_id)2041 fitpage_name = self.kernel_module.name 1940 2042 plots = GuiUtils.plotsFromFilename(item_name, item_model) 1941 2043 # Has the fitted data been shown? … … 2425 2527 def isCheckable(self, row): 2426 2528 return self._model_model.item(row, 0).isCheckable() 2529 2530 def selectCheckbox(self, row): 2531 """ 2532 Select the checkbox in given row. 2533 """ 2534 assert 0<= row <= self._model_model.rowCount() 2535 index = self._model_model.index(row, 0) 2536 item = self._model_model.itemFromIndex(index) 2537 item.setCheckState(QtCore.Qt.Checked) 2427 2538 2428 2539 def checkboxSelected(self, item): … … 3430 3541 return report_logic.reportList() 3431 3542 3432 def savePageState(self):3433 """3434 Create and serialize local PageState3435 """3436 filepath = self.saveAsAnalysisFile()3437 if filepath is None or filepath == "":3438 return3439 3440 fitpage_state = self.getFitPage()3441 fitpage_state += self.getFitModel()3442 3443 with open(filepath, 'w') as statefile:3444 for line in fitpage_state:3445 statefile.write(str(line))3446 3447 self.communicate.statusBarUpdateSignal.emit('Analysis saved.')3448 3449 def saveAsAnalysisFile(self):3450 """3451 Show the save as... dialog and return the chosen filepath3452 """3453 default_name = "FitPage"+str(self.tab_id)+".fitv"3454 3455 wildcard = "fitv files (*.fitv)"3456 kwargs = {3457 'caption' : 'Save As',3458 'directory' : default_name,3459 'filter' : wildcard,3460 'parent' : None,3461 }3462 # Query user for filename.3463 filename_tuple = QtWidgets.QFileDialog.getSaveFileName(**kwargs)3464 filename = filename_tuple[0]3465 return filename3466 3467 3543 def loadPageStateCallback(self,state=None, datainfo=None, format=None): 3468 3544 """ … … 3549 3625 3550 3626 param_list.append(['is_data', str(self.data_is_loaded)]) 3551 if self.data_is_loaded: 3552 param_list.append(['data_id', str(self.logic.data.id)]) 3553 param_list.append(['data_name', str(self.logic.data.filename)]) 3554 3627 data_ids = [] 3628 filenames = [] 3629 if self.is_batch_fitting: 3630 for item in self.all_data: 3631 # need item->data->data_id 3632 data = GuiUtils.dataFromItem(item) 3633 data_ids.append(data.id) 3634 filenames.append(data.filename) 3635 else: 3636 if self.data_is_loaded: 3637 data_ids = [str(self.logic.data.id)] 3638 filenames = [str(self.logic.data.filename)] 3639 param_list.append(['is_batch_fitting', str(self.is_batch_fitting)]) 3640 param_list.append(['data_name', filenames]) 3641 param_list.append(['data_id', data_ids]) 3642 param_list.append(['tab_name', self.modelName()]) 3555 3643 # option tab 3556 3644 param_list.append(['q_range_min', str(self.q_range_min)]) … … 3583 3671 """ 3584 3672 param_list = [] 3673 if self.kernel_module is None: 3674 return param_list 3675 3585 3676 param_list.append(['model_name', str(self.cbModel.currentText())]) 3586 3677 … … 3622 3713 except: 3623 3714 pass 3624 3625 param_list.append([param_name, param_checked, param_value, param_error, param_min, param_max]) 3715 # Do we have any constraints on this parameter? 3716 constraint = self.getConstraintForRow(row) 3717 cons = () 3718 if constraint is not None: 3719 value = constraint.value 3720 func = constraint.func 3721 value_ex = constraint.value_ex 3722 param = constraint.param 3723 validate = constraint.validate 3724 3725 cons = (value, param, value_ex, validate, func) 3726 3727 param_list.append([param_name, param_checked, param_value,param_error, param_min, param_max, cons]) 3626 3728 3627 3729 def gatherPolyParams(row): … … 3687 3789 cb_text = cb.text() 3688 3790 3689 context = {}3690 3791 lines = cb_text.split(':') 3691 3792 if lines[0] != 'sasview_parameter_values': … … 3699 3800 line_dict[content[0]] = content[1:] 3700 3801 3802 self.updatePageWithParameters(line_dict) 3803 3804 def createPageForParameters(self, line_dict): 3805 """ 3806 Sets up page with requested model/str factor 3807 and fills it up with sent parameters 3808 """ 3809 if 'fitpage_category' in line_dict: 3810 self.cbCategory.setCurrentIndex(self.cbCategory.findText(line_dict['fitpage_category'][0])) 3811 if 'fitpage_model' in line_dict: 3812 self.cbModel.setCurrentIndex(self.cbModel.findText(line_dict['fitpage_model'][0])) 3813 if 'fitpage_structure' in line_dict: 3814 self.cbStructureFactor.setCurrentIndex(self.cbStructureFactor.findText(line_dict['fitpage_structure'][0])) 3815 3816 # Now that the page is ready for parameters, fill it up 3817 self.updatePageWithParameters(line_dict) 3818 3819 def updatePageWithParameters(self, line_dict): 3820 """ 3821 Update FitPage with parameters in line_dict 3822 """ 3823 if 'model_name' not in line_dict.keys(): 3824 return 3701 3825 model = line_dict['model_name'][0] 3702 3703 if 'model_name' not in line_dict.keys(): 3704 return False 3826 context = {} 3705 3827 3706 3828 if 'multiplicity' in line_dict.keys(): … … 3711 3833 self.updateMultiplicityCombo(multip) 3712 3834 3835 if 'tab_name' in line_dict.keys(): 3836 self.kernel_module.name = line_dict['tab_name'][0] 3713 3837 if 'polydisperse_params' in line_dict.keys(): 3714 3838 self.chkPolydispersity.setChecked(line_dict['polydisperse_params'][0]=='True') … … 3833 3957 ioffset = 0 3834 3958 joffset = 0 3835 if len(param_dict[param_name])> 4:3959 if len(param_dict[param_name])>5: 3836 3960 # error values are not editable - no need to update 3837 3961 ioffset = 1 … … 3846 3970 except: 3847 3971 pass 3972 3973 # constraints 3974 cons = param_dict[param_name][4+ioffset] 3975 if cons is not None and len(cons)==5: 3976 value = cons[0] 3977 param = cons[1] 3978 value_ex = cons[2] 3979 validate = cons[3] 3980 function = cons[4] 3981 constraint = Constraint() 3982 constraint.value = value 3983 constraint.func = function 3984 constraint.param = param 3985 constraint.value_ex = value_ex 3986 constraint.validate = validate 3987 self.addConstraintToRow(constraint=constraint, row=row) 3848 3988 3849 3989 self.setFocus() -
src/sas/qtgui/Perspectives/Fitting/MultiConstraint.py
r305114c r09e0c32 20 20 Logic class for interacting with MultiConstrainedUI view 21 21 """ 22 def __init__(self, parent=None, params=None ):22 def __init__(self, parent=None, params=None, constraint=None): 23 23 """ 24 24 parent: ConstraintWidget object … … 31 31 self.params = params 32 32 self.parent = parent 33 # Text of the constraint 34 self.function = None 35 # Should this constraint be validated? 36 self.validate = True 37 38 self.input_constraint = constraint 39 if self.input_constraint is not None: 40 variable = constraint.value 41 self.function = constraint.func 42 self.params.append(variable) 43 self.model_name = constraint.value_ex 44 # Passed constraint may be too complex for simple validation 45 self.validate = constraint.validate 46 else: 47 self.model_name = self.params[1] 33 48 34 49 self.setupLabels() … … 36 51 37 52 # Set param text control to the second parameter passed 38 self.txtConstraint.setText(self.params[1]) 39 53 if self.input_constraint is None: 54 self.txtConstraint.setText(self.params[1]) 55 else: 56 self.txtConstraint.setText(self.function) 40 57 self.cmdOK.clicked.connect(self.accept) 41 58 self.cmdHelp.clicked.connect(self.onHelp) … … 52 69 # Switch parameters 53 70 self.params[1], self.params[0] = self.params[0], self.params[1] 71 # change fully qualified param name (e.g. M1.sld -> M1.sld_solvent) 72 self.model_name = self.model_name.replace(self.params[0], self.params[1]) 54 73 # Try to swap parameter names in the line edit 55 74 current_text = self.txtConstraint.text() … … 64 83 Setup labels based on current parameters 65 84 """ 66 l1 = s elf.params[0]67 l2 = s elf.params[1]85 l1 = str(self.params[0]) 86 l2 = str(self.params[1]) 68 87 self.txtParam1.setText(l1) 69 88 self.txtParam1_2.setText(l1) … … 82 101 Add visual cues when formula is incorrect 83 102 """ 103 # Don't validate if requested 104 if not self.validate: return 105 84 106 formula_is_valid = False 85 107 formula_is_valid = self.validateConstraint(self.txtConstraint.text()) … … 99 121 return False 100 122 101 param_str = str(self.params[1]) 102 constraint_text = constraint_text.strip() 123 param_str = self.model_name 103 124 104 125 # 1. just the parameter -
src/sas/qtgui/Perspectives/Fitting/UI/ComplexConstraintUI.ui
r1738173 recc5d043 7 7 <x>0</x> 8 8 <y>0</y> 9 <width> 367</width>10 <height> 199</height>9 <width>478</width> 10 <height>257</height> 11 11 </rect> 12 12 </property> … … 69 69 </sizepolicy> 70 70 </property> 71 <property name="sizeAdjustPolicy"> 72 <enum>QComboBox::AdjustToContents</enum> 73 </property> 71 74 <item> 72 75 <property name="text"> … … 100 103 </sizepolicy> 101 104 </property> 105 <property name="sizeAdjustPolicy"> 106 <enum>QComboBox::AdjustToContents</enum> 107 </property> 102 108 <item> 103 109 <property name="text"> … … 161 167 <property name="sizeHint" stdset="0"> 162 168 <size> 163 <width> 40</width>169 <width>88</width> 164 170 <height>20</height> 165 171 </size> … … 168 174 </item> 169 175 <item> 170 <widget class="QPushButton" name="cmdOK"> 176 <widget class="QToolButton" name="cmdOK"> 177 <property name="minimumSize"> 178 <size> 179 <width>93</width> 180 <height>28</height> 181 </size> 182 </property> 183 <property name="toolTip"> 184 <string><html><head/><body><p>Add the constraint as defined by the above expression.</p></body></html></string> 185 </property> 171 186 <property name="text"> 172 <string>OK</string> 173 </property> 174 <property name="default"> 187 <string>Add</string> 188 </property> 189 <property name="popupMode"> 190 <enum>QToolButton::MenuButtonPopup</enum> 191 </property> 192 <property name="toolButtonStyle"> 193 <enum>Qt::ToolButtonTextOnly</enum> 194 </property> 195 <property name="autoRaise"> 175 196 <bool>false</bool> 176 197 </property> 198 <property name="arrowType"> 199 <enum>Qt::DownArrow</enum> 200 </property> 177 201 </widget> 178 202 </item> 179 203 <item> 180 204 <widget class="QPushButton" name="cmdCancel"> 205 <property name="toolTip"> 206 <string><html><head/><body><p>Close the window.</p></body></html></string> 207 </property> 181 208 <property name="text"> 182 <string>C ancel</string>209 <string>Close</string> 183 210 </property> 184 211 </widget> … … 197 224 <resources/> 198 225 <connections> 199 <connection>200 <sender>cmdOK</sender>201 <signal>clicked()</signal>202 <receiver>ComplexConstraintUI</receiver>203 <slot>accept()</slot>204 <hints>205 <hint type="sourcelabel">206 <x>149</x>207 <y>144</y>208 </hint>209 <hint type="destinationlabel">210 <x>179</x>211 <y>82</y>212 </hint>213 </hints>214 </connection>215 226 <connection> 216 227 <sender>cmdCancel</sender> -
src/sas/qtgui/Perspectives/Fitting/UI/ConstraintWidgetUI.ui
r91ad45c recc5d043 7 7 <x>0</x> 8 8 <y>0</y> 9 <width> 428</width>10 <height> 457</height>9 <width>597</width> 10 <height>607</height> 11 11 </rect> 12 12 </property> … … 14 14 <string>Constrained and Simultaneous Fit</string> 15 15 </property> 16 <layout class="QGridLayout" name="gridLayout ">16 <layout class="QGridLayout" name="gridLayout_2"> 17 17 <item row="0" column="0"> 18 18 <widget class="QGroupBox" name="groupBox"> … … 89 89 <string>Constraints</string> 90 90 </property> 91 <layout class="QGridLayout" name="gridLayout _2">91 <layout class="QGridLayout" name="gridLayout"> 92 92 <item row="0" column="0"> 93 <layout class="QHBoxLayout" name="horizontalLayout"> 94 <item> 95 <widget class="QLabel" name="label"> 96 <property name="text"> 97 <string>Special cases</string> 98 </property> 99 </widget> 100 </item> 101 <item> 102 <widget class="QComboBox" name="cbCases"> 93 <layout class="QHBoxLayout" name="horizontalLayout_4"> 94 <item> 95 <layout class="QHBoxLayout" name="horizontalLayout"> 103 96 <item> 104 <property name="text"> 105 <string>None</string> 106 </property> 97 <widget class="QLabel" name="label"> 98 <property name="text"> 99 <string>Special cases</string> 100 </property> 101 </widget> 107 102 </item> 103 <item> 104 <widget class="QComboBox" name="cbCases"> 105 <item> 106 <property name="text"> 107 <string>None</string> 108 </property> 109 </item> 110 </widget> 111 </item> 112 </layout> 113 </item> 114 <item> 115 <spacer name="horizontalSpacer_3"> 116 <property name="orientation"> 117 <enum>Qt::Horizontal</enum> 118 </property> 119 <property name="sizeHint" stdset="0"> 120 <size> 121 <width>40</width> 122 <height>20</height> 123 </size> 124 </property> 125 </spacer> 126 </item> 127 <item> 128 <widget class="QPushButton" name="cmdAdd"> 129 <property name="toolTip"> 130 <string>Define constraints between two fit pages.</string> 131 </property> 132 <property name="text"> 133 <string>Add constraints</string> 134 </property> 108 135 </widget> 109 136 </item> … … 160 187 </size> 161 188 </property> 189 <property name="toolTip"> 190 <string>Perform simultaneous fitting of selected fit pages.</string> 191 </property> 162 192 <property name="text"> 163 193 <string>Fit</string> … … 179 209 </size> 180 210 </property> 211 <property name="toolTip"> 212 <string>Display help on constrained and simultaneous fitting.</string> 213 </property> 181 214 <property name="text"> 182 215 <string>Help</string> -
src/sas/qtgui/Perspectives/Fitting/UI/MultiConstraintUI.ui
r1738173 recc5d043 10 10 <x>0</x> 11 11 <y>0</y> 12 <width> 369</width>13 <height>2 01</height>12 <width>435</width> 13 <height>233</height> 14 14 </rect> 15 15 </property> … … 184 184 <connections> 185 185 <connection> 186 <sender>cmdCancel</sender> 187 <signal>clicked()</signal> 188 <receiver>MultiConstraintUI</receiver> 189 <slot>reject()</slot> 190 <hints> 191 <hint type="sourcelabel"> 192 <x>187</x> 193 <y>121</y> 194 </hint> 195 <hint type="destinationlabel"> 196 <x>184</x> 197 <y>71</y> 198 </hint> 199 </hints> 200 </connection> 201 <connection> 186 202 <sender>cmdOK</sender> 187 203 <signal>clicked()</signal> … … 199 215 </hints> 200 216 </connection> 201 <connection>202 <sender>cmdCancel</sender>203 <signal>clicked()</signal>204 <receiver>MultiConstraintUI</receiver>205 <slot>reject()</slot>206 <hints>207 <hint type="sourcelabel">208 <x>187</x>209 <y>121</y>210 </hint>211 <hint type="destinationlabel">212 <x>184</x>213 <y>71</y>214 </hint>215 </hints>216 </connection>217 217 </connections> 218 218 </ui> -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/ComplexConstraintTest.py
r725d9c06 rd72ac57 34 34 category_index = self.tab1.cbCategory.findText("Shape Independent") 35 35 self.tab1.cbCategory.setCurrentIndex(category_index) 36 model_index = self.tab1.cbModel.findText("be_polyelectrolyte") 37 self.tab1.cbModel.setCurrentIndex(model_index) 38 36 39 category_index = self.tab2.cbCategory.findText("Cylinder") 37 40 self.tab2.cbCategory.setCurrentIndex(category_index) 41 model_index = self.tab2.cbModel.findText("barbell") 42 self.tab2.cbModel.setCurrentIndex(model_index) 38 43 39 44 tabs = [self.tab1, self.tab2] … … 127 132 """ 128 133 # default data 129 self.assertEqual(self.widget.constraint(), ('M1', 'scale', '=', 'M1.scale')) 134 c = self.widget.constraint() 135 self.assertEqual(c[0], 'M1') 136 self.assertEqual(c[1].func, 'M1.scale') 130 137 131 138 # Change parameter and operand 132 self.widget.cbOperator.setCurrentIndex(3) 133 self.widget.cbParam1.setCurrentIndex(3) 134 self.assertEqual(self.widget.constraint(), ('M1', 'bjerrum_length', '>=', 'M1.scale')) 139 #self.widget.cbOperator.setCurrentIndex(3) 140 self.widget.cbParam2.setCurrentIndex(3) 141 c = self.widget.constraint() 142 self.assertEqual(c[0], 'M1') 143 self.assertEqual(c[1].func, 'M1.sld_solvent') 144 #self.assertEqual(c[1].operator, '>=') 135 145 136 146 def testOnHelp(self): -
src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py
rec4a143 rbaeac95 175 175 category_index = self.widget.cbCategory.findText("Shape Independent") 176 176 self.widget.cbCategory.setCurrentIndex(category_index) 177 model_index = self.widget.cbModel.findText("be_polyelectrolyte") 178 self.widget.cbModel.setCurrentIndex(model_index) 177 179 178 180 # test the model combo content 179 self.assertEqual(self.widget.cbModel.count(), 28)181 self.assertEqual(self.widget.cbModel.count(), 30) 180 182 181 183 # Try to change back to default … … 183 185 184 186 # Observe no such luck 185 self.assertEqual(self.widget.cbCategory.currentIndex(), 6)186 self.assertEqual(self.widget.cbModel.count(), 29)187 self.assertEqual(self.widget.cbCategory.currentIndex(), 7) 188 self.assertEqual(self.widget.cbModel.count(), 30) 187 189 188 190 # Set the structure factor … … 201 203 category_index = self.widget.cbCategory.findText("Shape Independent") 202 204 self.widget.cbCategory.setCurrentIndex(category_index) 205 model_index = self.widget.cbModel.findText("be_polyelectrolyte") 206 self.widget.cbModel.setCurrentIndex(model_index) 203 207 204 208 # check the enablement of controls … … 215 219 # 216 220 # Now change the model 217 self.widget.cbModel.setCurrentIndex( 2)221 self.widget.cbModel.setCurrentIndex(4) 218 222 self.assertEqual(self.widget.cbModel.currentText(),'dab') 219 223 … … 226 230 self.widget.data_is_loaded = True 227 231 # Reset the sasmodel index 228 self.widget.cbModel.setCurrentIndex( 1)232 self.widget.cbModel.setCurrentIndex(2) 229 233 self.assertEqual(self.widget.cbModel.currentText(),'broad_peak') 230 234 … … 377 381 category_index = self.widget.cbCategory.findText("Shape Independent") 378 382 self.widget.cbCategory.setCurrentIndex(category_index) 383 model_index = self.widget.cbModel.findText("be_polyelectrolyte") 384 self.widget.cbModel.setCurrentIndex(model_index) 385 379 386 # Check the poly model 380 387 self.assertEqual(self.widget._poly_model.rowCount(), 0) … … 383 390 # Change the category index so we have a model available 384 391 self.widget.cbCategory.setCurrentIndex(2) 392 self.widget.cbModel.setCurrentIndex(1) 385 393 386 394 # Check the poly model … … 556 564 category_index = self.widget.cbCategory.findText("Sphere") 557 565 self.widget.cbCategory.setCurrentIndex(category_index) 566 model_index = self.widget.cbModel.findText("adsorbed_layer") 567 self.widget.cbModel.setCurrentIndex(model_index) 558 568 559 569 # Check the magnetic model … … 634 644 category_index = self.widget.cbCategory.findText("Sphere") 635 645 self.widget.cbCategory.setCurrentIndex(category_index) 646 model_index = self.widget.cbModel.findText("adsorbed_layer") 647 self.widget.cbModel.setCurrentIndex(model_index) 636 648 637 649 # Check the enablement/text … … 973 985 category_index = self.widget.cbCategory.findText("Sphere") 974 986 self.widget.cbCategory.setCurrentIndex(category_index) 987 model_index = self.widget.cbModel.findText("adsorbed_layer") 988 self.widget.cbModel.setCurrentIndex(model_index) 975 989 self.widget.main_params_to_fit = ['scale'] 976 990 … … 986 1000 self.assertListEqual(fp.main_params_to_fit, ['scale']) 987 1001 988 def testPushFitPage(self):1002 def notestPushFitPage(self): 989 1003 """ 990 1004 Push current state of fitpage onto stack … … 997 1011 self.widget.data = item 998 1012 category_index = self.widget.cbCategory.findText("Sphere") 1013 model_index = self.widget.cbModel.findText("adsorbed_layer") 1014 self.widget.cbModel.setCurrentIndex(model_index) 999 1015 1000 1016 # Asses the initial state of stack -
src/sas/qtgui/Perspectives/Fitting/FittingUtilities.py
r65759c7 r7f41584 368 368 cbox = createFixedChoiceComboBox(par, row) 369 369 370 # Apply combobox if required 371 if None not in (view, cbox): 372 # set the min/max cell to be empty 373 item3.setText("") 374 item4.setText("") 375 370 376 # Always add to the model 371 377 if row_num is None: … … 375 381 row_num += 1 376 382 377 # Apply combobox if required 378 if None not in (view, cbox): 383 if cbox is not None: 379 384 view.setIndexWidget(item2.index(), cbox) 380 385 -
src/sas/qtgui/Perspectives/Fitting/ViewDelegate.py
r722b7d6 r7f41584 95 95 # Set some columns uneditable 96 96 return None 97 if index.column() in (self.param_min, self.param_max): 98 # Check if the edit role is set 99 if not (index.flags() & QtCore.Qt.ItemIsEditable): 100 return None 97 101 98 102 return super(ModelViewDelegate, self).createEditor(widget, option, index) -
src/sas/qtgui/Perspectives/Fitting/media/fitting_help.rst
r00a40bd r3b0b17e 125 125 126 126 For a complete list of all the library models available in SasView, see 127 the `Model Documentation < ../../../index.html>`_ .127 the `Model Documentation <models/index.html>`_ . 128 128 129 129 It is also possible to add your own models.
Note: See TracChangeset
for help on using the changeset viewer.