Changeset b00414d in sasview for src


Ignore:
Timestamp:
Jul 25, 2017 7:36:45 AM (7 years ago)
Author:
Piotr Rozyczko <rozyczko@…>
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:
0d13814
Parents:
2a8bd705
Message:

SASVIEW-272: initial implementation of magnetic model/view

Location:
src/sas/qtgui
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/sas/qtgui/MainWindow/UI/MainWindowUI.ui

    r85487ebd rb00414d  
    324324  <action name="actionCategry_Manager"> 
    325325   <property name="text"> 
    326     <string>Categry Manager</string> 
     326    <string>Category Manager</string> 
     327   </property> 
     328   <property name="toolTip"> 
     329    <string>Category Manager</string> 
    327330   </property> 
    328331  </action> 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    r6ff2eb3 rb00414d  
    3636from sas.qtgui.Perspectives.Fitting.ViewDelegate import ModelViewDelegate 
    3737from sas.qtgui.Perspectives.Fitting.ViewDelegate import PolyViewDelegate 
     38from sas.qtgui.Perspectives.Fitting.ViewDelegate import MagnetismViewDelegate 
    3839 
    3940TAB_MAGNETISM = 4 
     
    166167        # Which shell is being currently displayed? 
    167168        self.current_shell_displayed = 0 
     169 
     170        # Error column presence in parameter display 
    168171        self.has_error_column = False 
    169172        self.has_poly_error_column = False 
     173        self.has_magnet_error_column = False 
    170174 
    171175        # signal communicator 
     
    259263        self.setMagneticModel() 
    260264        self.setTableProperties(self.lstMagnetic) 
     265        # Delegates for custom editing and display 
     266        self.lstMagnetic.setItemDelegate(MagnetismViewDelegate(self)) 
    261267 
    262268    def initializeCategoryCombo(self): 
     
    369375 
    370376        # Respond to change in parameters from the UI 
    371         self._model_model.itemChanged.connect(self.updateParamsFromModel) 
     377        self._model_model.itemChanged.connect(self.onMainParamsChange) 
    372378        self._poly_model.itemChanged.connect(self.onPolyModelChange) 
    373  
    374         # TODO after the poly_model prototype accepted 
    375         #self._magnet_model.itemChanged.connect(self.onMagneticModelChange) 
     379        self._magnet_model.itemChanged.connect(self.onMagnetModelChange) 
    376380 
    377381        # Signals from separate tabs asking for replot 
     
    501505                if parameter_name in self.parameters_to_fit: 
    502506                    self.parameters_to_fit.remove(parameter_name) 
     507            self.cmdFit.setEnabled(self.parameters_to_fit != [] and self.logic.data_is_loaded) 
    503508            return 
    504509        elif model_column in [self.lstPoly.itemDelegate().poly_min, self.lstPoly.itemDelegate().poly_max]: 
     
    525530            self.kernel_module.setParam(parameter_name + '.' + \ 
    526531                                        self.lstPoly.itemDelegate().columnDict()[model_column], value) 
     532 
     533    def onMagnetModelChange(self, item): 
     534        """ 
     535        Callback method for updating the sasmodel magnetic parameters with the GUI values 
     536        """ 
     537        model_column = item.column() 
     538        model_row = item.row() 
     539        name_index = self._magnet_model.index(model_row, 0) 
     540        parameter_name = str(self._magnet_model.data(name_index).toPyObject()) 
     541 
     542        if model_column == 0: 
     543            value = item.checkState() 
     544            if value == QtCore.Qt.Checked: 
     545                self.parameters_to_fit.append(parameter_name) 
     546            else: 
     547                if parameter_name in self.parameters_to_fit: 
     548                    self.parameters_to_fit.remove(parameter_name) 
     549            self.cmdFit.setEnabled(self.parameters_to_fit != [] and self.logic.data_is_loaded) 
     550            # Update state stack 
     551            self.updateUndo() 
     552            return 
     553 
     554        # Extract changed value. 
     555        try: 
     556            value = float(item.text()) 
     557        except ValueError: 
     558            # Unparsable field 
     559            return 
     560 
     561        property_index = self._magnet_model.headerData(1, model_column).toInt()[0]-1 # Value, min, max, etc. 
     562 
     563        # Update the parameter value - note: this supports +/-inf as well 
     564        self.kernel_module.params[parameter_name] = value 
     565 
     566        # min/max to be changed in self.kernel_module.details[parameter_name] = ['Ang', 0.0, inf] 
     567        self.kernel_module.details[parameter_name][property_index] = value 
     568 
     569        # Force the chart update when actual parameters changed 
     570        if model_column == 1: 
     571            self.recalculatePlotData() 
     572 
     573        # Update state stack 
     574        self.updateUndo() 
    527575 
    528576    def onHelp(self): 
     
    667715        self.updatePolyModelFromList(param_dict) 
    668716 
     717        self.updateMagnetModelFromList(param_dict) 
     718 
    669719        # update charts 
    670720        self.onPlot() 
     
    758808        if not dict: 
    759809            return 
     810 
     811        def iterateOverPolyModel(func): 
     812            """ 
     813            Take func and throw it inside the poly model row loop 
     814            """ 
     815            for row_i in xrange(self._poly_model.rowCount()): 
     816                func(row_i) 
    760817 
    761818        def updateFittedValues(row_i): 
     
    795852        # updating charts with every single model change on the end of fitting 
    796853        self._poly_model.blockSignals(True) 
    797         self.iterateOverModel(updateFittedValues) 
     854        iterateOverPolyModel(updateFittedValues) 
    798855        self._poly_model.blockSignals(False) 
    799856 
     
    803860        self.lstPoly.itemDelegate().addErrorColumn() 
    804861        error_column = [] 
    805         self.iterateOverModel(createErrorColumn) 
     862        iterateOverPolyModel(createErrorColumn) 
    806863 
    807864        # switch off reponse to model change 
     
    812869 
    813870        self.has_poly_error_column = True 
     871 
     872    def updateMagnetModelFromList(self, param_dict): 
     873        """ 
     874        Update the magnetic model with new parameters, create the errors column 
     875        """ 
     876        assert isinstance(param_dict, dict) 
     877        if not dict: 
     878            return 
     879 
     880        def iterateOverMagnetModel(func): 
     881            """ 
     882            Take func and throw it inside the magnet model row loop 
     883            """ 
     884            for row_i in xrange(self._model_model.rowCount()): 
     885                func(row_i) 
     886 
     887        def updateFittedValues(row): 
     888            # Utility function for main model update 
     889            # internal so can use closure for param_dict 
     890            param_name = str(self._magnet_model.item(row, 0).text()) 
     891            if param_name not in param_dict.keys(): 
     892                return 
     893            # modify the param value 
     894            param_repr = GuiUtils.formatNumber(param_dict[param_name][0], high=True) 
     895            self._magnet_model.item(row, 1).setText(param_repr) 
     896            if self.has_magnet_error_column: 
     897                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
     898                self._magnet_model.item(row, 2).setText(error_repr) 
     899 
     900        def createErrorColumn(row): 
     901            # Utility function for error column update 
     902            item = QtGui.QStandardItem() 
     903            def createItem(param_name): 
     904                error_repr = GuiUtils.formatNumber(param_dict[param_name][1], high=True) 
     905                item.setText(error_repr) 
     906            def curr_param(): 
     907                return str(self._magnet_model.item(row, 0).text()) 
     908 
     909            [createItem(param_name) for param_name in param_dict.keys() if curr_param() == param_name] 
     910 
     911            error_column.append(item) 
     912 
     913        # block signals temporarily, so we don't end up 
     914        # updating charts with every single model change on the end of fitting 
     915        self._magnet_model.blockSignals(True) 
     916        iterateOverMagnetModel(updateFittedValues) 
     917        self._magnet_model.blockSignals(False) 
     918 
     919        if self.has_magnet_error_column: 
     920            return 
     921 
     922        self.lstMagnetic.itemDelegate().addErrorColumn() 
     923        error_column = [] 
     924        iterateOverMagnetModel(createErrorColumn) 
     925 
     926        # switch off reponse to model change 
     927        self._magnet_model.blockSignals(True) 
     928        self._magnet_model.insertColumn(2, error_column) 
     929        self._magnet_model.blockSignals(False) 
     930        FittingUtilities.addErrorHeadersToModel(self._magnet_model) 
     931 
     932        self.has_magnet_error_column = True 
    814933 
    815934    def onPlot(self): 
     
    10391158        self._last_model_row = self._model_model.rowCount() 
    10401159 
    1041     def updateParamsFromModel(self, item): 
     1160    def onMainParamsChange(self, item): 
    10421161        """ 
    10431162        Callback method for updating the sasmodel parameters with the GUI values 
     
    10551174        name_index = self._model_model.index(model_row, 0) 
    10561175 
    1057         # Extract changed value. Assumes proper validation by QValidator/Delegate 
     1176        # Extract changed value. 
    10581177        try: 
    10591178            value = float(item.text()) 
     
    11011220        main_params = self.checkedListFromModel(self._model_model) 
    11021221        poly_params = self.checkedListFromModel(self._poly_model) 
     1222        magnet_params = self.checkedListFromModel(self._magnet_model) 
     1223 
    11031224        # Retrieve poly params names 
    11041225        poly_params = [param.rsplit()[-1] + '.width' for param in poly_params] 
    1105         # TODO : add magnetic params 
    1106  
    1107         self.parameters_to_fit = main_params + poly_params 
     1226 
     1227        self.parameters_to_fit = main_params + poly_params + magnet_params 
    11081228 
    11091229    def checkedListFromModel(self, model): 
  • src/sas/qtgui/Perspectives/Fitting/ViewDelegate.py

    r8eaa101 rb00414d  
    178178            # Just the default paint 
    179179            QtGui.QStyledItemDelegate.paint(self, painter, option, index) 
     180 
     181class MagnetismViewDelegate(QtGui.QStyledItemDelegate): 
     182    """ 
     183    Custom delegate for appearance and behavior control of the magnetism view 
     184    """ 
     185    def __init__(self, parent=None): 
     186        """ 
     187        Overwrite generic constructor to allow for some globals 
     188        """ 
     189        super(QtGui.QStyledItemDelegate, self).__init__() 
     190 
     191        self.mag_parameter = 0 
     192        self.mag_value = 1 
     193        self.mag_min = 2 
     194        self.mag_max = 3 
     195        self.mag_unit = 4 
     196 
     197    def editableParameters(self): 
     198        return [self.mag_min, self.mag_max] 
     199 
     200    def addErrorColumn(self): 
     201        """ 
     202        Modify local column pointers 
     203        Note: the reverse is never required! 
     204        """ 
     205        self.mag_parameter = 0 
     206        self.mag_value = 1 
     207        self.mag_min = 3 
     208        self.mag_max = 4 
     209        self.mag_unit = 5 
     210 
     211    def createEditor(self, widget, option, index): 
     212        # Remember the current choice 
     213        current_text = index.data().toString() 
     214        if not index.isValid(): 
     215            return 0 
     216        if index.column() in self.editableParameters(): 
     217            editor = QtGui.QLineEdit(widget) 
     218            validator = QtGui.QDoubleValidator() 
     219            editor.setValidator(validator) 
     220            return editor 
     221        else: 
     222            QtGui.QStyledItemDelegate.createEditor(self, widget, option, index) 
     223 
     224    def paint(self, painter, option, index): 
     225        """ 
     226        Overwrite generic painter for certain columns 
     227        """ 
     228        if index.column() in (self.mag_min, self.mag_max): 
     229            # Units - present in nice HTML 
     230            options = QtGui.QStyleOptionViewItemV4(option) 
     231            self.initStyleOption(options,index) 
     232 
     233            style = QtGui.QApplication.style() if options.widget is None else options.widget.style() 
     234 
     235            # Prepare document for inserting into cell 
     236            doc = QtGui.QTextDocument() 
     237 
     238            # Convert the unit description into HTML 
     239            text_html = GuiUtils.convertUnitToHTML(str(options.text)) 
     240            doc.setHtml(text_html) 
     241 
     242            # delete the original content 
     243            options.text = "" 
     244            style.drawControl(QtGui.QStyle.CE_ItemViewItem, options, painter, options.widget); 
     245 
     246            context = QtGui.QAbstractTextDocumentLayout.PaintContext() 
     247            textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, options) 
     248 
     249            painter.save() 
     250            painter.translate(textRect.topLeft()) 
     251            painter.setClipRect(textRect.translated(-textRect.topLeft())) 
     252            # Draw the QTextDocument in the cell 
     253            doc.documentLayout().draw(painter, context) 
     254            painter.restore() 
     255        else: 
     256            # Just the default paint 
     257            QtGui.QStyledItemDelegate.paint(self, painter, option, index) 
Note: See TracChangeset for help on using the changeset viewer.