Changeset 22b4962 in sasview


Ignore:
Timestamp:
Mar 28, 2019 12:15:25 PM (8 weeks ago)
Author:
ibressler
Branches:
ESS_GUI_bumps_abstraction
Children:
fec5842
Parents:
46477950
git-author:
Ingo Breßler <dev@…> (03/28/19 12:14:57)
git-committer:
Ingo Breßler <dev@…> (03/28/19 12:15:25)
Message:

FittingOptions?: create form dynamically

  • removed the QStackWidget, should not be required anymore
  • form is cleared and rebuilt on algorithm change
  • enables SasView? to build the form from fitting method meta data
  • no UI form has to be modified for new algorithms
  • TODO FittingOptionsUI.ui can be simplified
  • UnitTests? have to be adjusted accordingly
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/Perspectives/Fitting/FittingOptions.py

    r46477950 r22b4962  
    1919 
    2020# Set the default optimizer 
    21  
    22 def parse_int(value): 
    23     """ 
    24     Converts user input to integer numbers. (from bumps) 
    25     """ 
    26     float_value = float(value) 
    27     if int(float_value) != float_value: 
    28         raise ValueError("integer expected") 
    29     return int(float_value) 
    30  
    31 class ChoiceList(object): 
    32     """ 
    33     Validates user input for a distinct number of options. 
    34     """ 
    35     def __init__(self, *choices): 
    36         self.choices = choices 
    37     def __call__(self, value): 
    38         if not value in self.choices: 
    39             raise ValueError('invalid option "%s": use %s' 
    40                     % (value, '|'.join(self.choices))) 
    41         else: 
    42             return value 
    4321 
    4422class FittingMethodParameter: 
     
    183161            for shortName, defValue in f.settings: 
    184162                longName, dtype = bumps.options.FIT_FIELDS[shortName] 
     163                dtype = self._convertParamType(dtype) 
    185164                param = FittingMethodParameter(shortName, longName, dtype, defValue) 
    186165                params.append(param) 
    187166            self.add(FittingMethodBumps(f.id, f.name, params)) 
     167 
     168    @staticmethod 
     169    def _convertParamType(dtype): 
     170        if dtype is bumps.options.parse_int: 
     171            dtype = int 
     172        elif isinstance(dtype, bumps.options.ChoiceList): 
     173            dtype = tuple(dtype.choices) 
     174        return dtype 
    188175 
    189176class FittingOptions(QtWidgets.QDialog, Ui_FittingOptions): 
     
    225212        self.fittingMethods.add(FittingMethod('mcsas', 'McSAS', [])) # FIXME just testing for now 
    226213        self.fittingMethods.setDefault('Levenberg-Marquardt') 
     214 
    227215        # build up the comboBox finally 
    228216        self.cbAlgorithm.addItems(self.fittingMethods.longNames) 
     
    258246        for param in fm.params.values(): 
    259247            validator = None 
    260             if type(param.type) == types.FunctionType: 
     248            if param.type == int: 
    261249                validator = QtGui.QIntValidator() 
    262250                validator.setBottom(0) 
     
    285273        sender.setStyleSheet('QLineEdit { background-color: %s }' % color) 
    286274 
     275    def _clearLayout(self): 
     276        layout = self.groupBox.layout() 
     277        for i in reversed(list(range(layout.count()))): 
     278            # reversed removal avoids renumbering possibly 
     279            item = layout.itemAt(i) 
     280            try: 
     281                if item.widget().objectName() == "cbAlgorithm": 
     282                    continue 
     283            except AttributeError: 
     284                pass 
     285            item = layout.takeAt(i) 
     286            try: # spaceritem does not have a widget 
     287                item.widget().setParent(None) 
     288                item.widget().deleteLater() 
     289            except AttributeError: 
     290                pass 
     291 
     292    @staticmethod 
     293    def _makeLabel(name): 
     294        lbl = QtWidgets.QLabel(name + ":") 
     295        lbl.setAlignment(QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) 
     296        lbl.setWordWrap(True) 
     297        return lbl 
     298 
     299    @staticmethod 
     300    def _inputWidgetFromType(ptype, parent): 
     301        """ 
     302        Creates a widget for user input based on the given data type to be entered. 
     303        """ 
     304        widget = None 
     305        if ptype in (float, int): 
     306            widget = QtWidgets.QLineEdit(parent) 
     307        elif isinstance(ptype, (tuple, list)): 
     308            widget = QtWidgets.QComboBox(parent) 
     309            widget.addItems(ptype) 
     310        return widget 
     311 
     312    def _fillLayout(self): 
     313        fm = self.fittingMethods[self.currentOptimizer] 
     314        layout = self.groupBox.layout() 
     315        # label for the name of the optimizer, span the whole row 
     316        layout.addWidget(self._makeLabel(fm.longName), layout.rowCount()+1, 0, 1, -1) 
     317        for param in fm.params.values(): 
     318            row, column = layout.rowCount()+1, layout.columnCount() 
     319            layout.addWidget(self._makeLabel(param.longName), row, 0) 
     320            widget = self._inputWidgetFromType(param.type, self) 
     321            if widget is None: 
     322                continue 
     323            widgetName = param.shortName+'_'+fm.shortName 
     324            layout.addWidget(widget, row, 1) 
     325            setattr(self, widgetName, widget) 
     326        layout.addItem(QtWidgets.QSpacerItem(0, 0, vPolicy=QtWidgets.QSizePolicy.Expanding)) 
     327 
    287328    def onAlgorithmChange(self, index): 
    288329        """ 
     
    291332        # Find the algorithm ID from name 
    292333        selectedName = self.currentOptimizer 
     334 
     335        self._clearLayout() 
     336        self._fillLayout() 
     337 
    293338        if selectedName in self.fittingMethods.longNames: 
    294339            self.current_fitter_id = self.fittingMethods[selectedName].shortName 
     
    313358            return 
    314359 
    315         index_for_this_id = self.stackedWidget.indexOf(widget_to_activate) 
    316  
    317360        # Select the requested widget 
    318         self.stackedWidget.setCurrentIndex(index_for_this_id) 
    319361        self.updateWidgetFromConfig() 
    320362        self.assignValidators() 
     
    401443            # Find the widget name of the option 
    402444            # e.g. 'samples' for 'dream' is 'self.samples_dream' 
    403             widget_name = 'self.'+param.shortName+'_'+(fm.shortName) 
    404             if isinstance(param.type, ChoiceList): 
     445            widget_name = 'self.'+param.shortName+'_'+fm.shortName 
     446            if isinstance(param.type, (tuple, list)): 
    405447                control = eval(widget_name) 
    406448                control.setCurrentIndex(control.findText(str(param.value))) 
Note: See TracChangeset for help on using the changeset viewer.