Ignore:
Timestamp:
Mar 3, 2017 9:07:04 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:
5236449
Parents:
6f7f652
Message:

Redo the parameter table view as treeview to enable additional polydispersity data display

File:
1 edited

Legend:

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

    r6f7f652 r86f88d1  
    1515TAB_MAGNETISM = 4 
    1616TAB_POLY = 3 
     17CATEGORY_DEFAULT="Choose category..." 
    1718 
    1819class FittingWidget(QtGui.QWidget, Ui_FittingWidgetUI): 
     
    2930        super(FittingWidget, self).__init__() 
    3031 
     32        # Necessary globals 
    3133        self.model_is_loaded = False 
    3234        self._data = data 
    3335        self.is2D = False 
    34         self.modelHasShells = False 
     36        self.model_has_shells = False 
    3537        self.data_assigned = False 
    36  
     38        self._previous_category_index = 0 
     39        self._last_model_row = 0 
     40 
     41        # Main GUI setup up 
    3742        self.setupUi(self) 
    38  
    3943        self.setWindowTitle("Fitting") 
    4044 
    41         # set the main models 
     45        # Set the main models 
    4246        self._model_model = QtGui.QStandardItemModel() 
    4347        self._poly_model = QtGui.QStandardItemModel() 
    4448        self._magnet_model = QtGui.QStandardItemModel() 
     49        # Proxy model for custom views on the main _model_model 
     50        self.proxyModel = QtGui.QSortFilterProxyModel() 
    4551 
    4652        # Param model displayed in param list 
     
    4854        self._readCategoryInfo() 
    4955        self.model_parameters = None 
     56        self.lstParams.setAlternatingRowColors(True) 
    5057 
    5158        # Poly model displayed in poly list 
     
    6875        # Generate the category list for display 
    6976        category_list = sorted(self.master_category_dict.keys()) 
    70         self.cbCategory.addItem("Choose category...") 
     77        self.cbCategory.addItem(CATEGORY_DEFAULT) 
    7178        self.cbCategory.addItems(category_list) 
    7279        self.cbCategory.addItem("Structure Factor") 
    7380        self.cbCategory.setCurrentIndex(0) 
    7481 
    75         # Connect GUI element signals 
    76         self.cbStructureFactor.currentIndexChanged.connect(self.selectStructureFactor) 
    77         self.cbCategory.currentIndexChanged.connect(self.selectCategory) 
    78         self.cbModel.currentIndexChanged.connect(self.selectModel) 
    79         self.chk2DView.toggled.connect(self.toggle2D) 
    80         self.chkPolydispersity.toggled.connect(self.togglePoly) 
    81         self.chkMagnetism.toggled.connect(self.toggleMagnetism) 
    82  
    83         # Set initial control enablement 
     82        # Connect signals to controls 
     83        self.initializeSignals() 
     84 
     85        # Initial control state 
     86        self.initializeControls() 
     87 
     88    @property 
     89    def data(self): 
     90        return self._data 
     91 
     92    @data.setter 
     93    def data(self, value): 
     94        """ data setter """ 
     95        self._data = value 
     96        self.data_assigned = True 
     97        # TODO: update ranges, chi2 etc 
     98 
     99    def acceptsData(self): 
     100        """ Tells the caller this widget can accept new dataset """ 
     101        return not self.data_assigned 
     102 
     103    def disableModelCombo(self): 
     104        self.cbModel.setEnabled(False) 
     105        self.label_3.setEnabled(False) 
     106 
     107    def enableModelCombo(self): 
     108        self.cbModel.setEnabled(True) 
     109        self.label_3.setEnabled(True) 
     110 
     111    def disableStructureCombo(self): 
     112        self.cbStructureFactor.setEnabled(False) 
     113        self.label_4.setEnabled(False) 
     114 
     115    def enableStructureCombo(self): 
     116        self.cbStructureFactor.setEnabled(True) 
     117        self.label_4.setEnabled(True) 
     118 
     119    def initializeControls(self): 
     120        """ 
     121        Set initial control enablement 
     122        """ 
    84123        self.cmdFit.setEnabled(False) 
    85124        self.cmdPlot.setEnabled(True) 
     
    90129        self.chkMagnetism.setEnabled(False) 
    91130        self.chkMagnetism.setCheckState(False) 
    92  
     131        # tabs 
    93132        self.tabFitting.setTabEnabled(TAB_POLY, False) 
    94133        self.tabFitting.setTabEnabled(TAB_MAGNETISM, False) 
    95  
    96134        # set initial labels 
    97135        self.lblMinRangeDef.setText("---") 
     
    99137        self.lblChi2Value.setText("---") 
    100138 
    101     @property 
    102     def data(self): 
    103         return self._data 
    104  
    105     @data.setter 
    106     def data(self, value): 
    107         """ data setter """ 
    108         self._data = value 
    109         self.data_assigned = True 
    110         # TODO: update ranges, chi2 etc 
    111  
    112     def acceptsData(self): 
    113         """ Tells the caller this widget can accept new dataset """ 
    114         return not self.data_assigned 
    115  
    116     def disableModelCombo(self): 
    117         self.cbModel.setEnabled(False) 
    118         self.label_3.setEnabled(False) 
    119  
    120     def enableModelCombo(self): 
    121         self.cbModel.setEnabled(True) 
    122         self.label_3.setEnabled(True) 
    123  
    124     def disableStructureCombo(self): 
    125         self.cbStructureFactor.setEnabled(False) 
    126         self.label_4.setEnabled(False) 
    127  
    128     def enableStructureCombo(self): 
    129         self.cbStructureFactor.setEnabled(True) 
    130         self.label_4.setEnabled(True) 
     139    def initializeSignals(self): 
     140        """ 
     141        Connect GUI element signals 
     142        """ 
     143        self.cbStructureFactor.currentIndexChanged.connect(self.selectStructureFactor) 
     144        self.cbCategory.currentIndexChanged.connect(self.selectCategory) 
     145        self.cbModel.currentIndexChanged.connect(self.selectModel) 
     146        self.chk2DView.toggled.connect(self.toggle2D) 
     147        self.chkPolydispersity.toggled.connect(self.togglePoly) 
     148        self.chkMagnetism.toggled.connect(self.toggleMagnetism) 
    131149 
    132150    def setDefaultStructureCombo(self): 
     
    145163        """ 
    146164        category = self.cbCategory.currentText() 
     165        # Check if the user chose "Choose category entry" 
     166        if str(category) == CATEGORY_DEFAULT: 
     167            # if the previous category was not the default, keep it. 
     168            # Otherwise, just return 
     169            if self._previous_category_index != 0: 
     170                self.cbCategory.setCurrentIndex(self._previous_category_index) 
     171            return 
     172 
    147173        if category == "Structure Factor": 
    148174            self.disableModelCombo() 
     
    156182        self.disableStructureCombo() 
    157183 
     184        self._previous_category_index = self.cbCategory.currentIndex() 
    158185        model_list = self.master_category_dict[str(category)] 
    159186        models = [] 
     
    235262            iter_param = iter_params[0].length_control 
    236263        return (iter_param, iter_length) 
    237          
     264 
     265    def addBackgroundToModel(self, model): 
     266        """ 
     267        Adds background parameter with default values to the model 
     268        """ 
     269        assert(isinstance(model, QtGui.QStandardItemModel)) 
     270 
     271        checked_list = ['background', '0.001', '-inf', 'inf', '1/cm'] 
     272        self.addCheckedListToModel(model, checked_list) 
     273 
     274    def addScaleToModel(self, model): 
     275        """ 
     276        Adds scale parameter with default values to the model 
     277        """ 
     278        assert(isinstance(model, QtGui.QStandardItemModel)) 
     279 
     280        checked_list = ['scale', '1.0', '0.0', 'inf', ''] 
     281        self.addCheckedListToModel(model, checked_list) 
     282 
     283    def addCheckedListToModel(self, model, param_list): 
     284        assert(isinstance(model, QtGui.QStandardItemModel)) 
     285        item_list = [QtGui.QStandardItem(item) for item in param_list] 
     286        item_list[0].setCheckable(True) 
     287        model.appendRow(item_list) 
     288 
     289    def addHeadersToModel(self, model): 
     290        """ 
     291        Adds predefined headers to the model 
     292        """ 
     293        model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 
     294        model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("Value")) 
     295        model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 
     296        model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 
     297        model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("[Units]")) 
     298 
     299    def addPolyHeadersToModel(self, model): 
     300        """ 
     301        Adds predefined headers to the model 
     302        """ 
     303        model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 
     304        model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("PD[ratio]")) 
     305        model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 
     306        model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 
     307        model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("Npts")) 
     308        model.setHeaderData(5, QtCore.Qt.Horizontal, QtCore.QVariant("Nsigs")) 
     309        model.setHeaderData(6, QtCore.Qt.Horizontal, QtCore.QVariant("Function")) 
     310 
    238311    def setModelModel(self, model_name): 
    239312        """ 
     
    248321        self.model_parameters = modelinfo.make_parameter_table(getattr(kernel_module, 'parameters', [])) 
    249322 
    250         #TODO: scaale and background are implicit in sasmodels and needs to be added 
    251         item1 = QtGui.QStandardItem('scale') 
    252         item1.setCheckable(True) 
    253         item2 = QtGui.QStandardItem('1.0') 
    254         item3 = QtGui.QStandardItem('0.0') 
    255         item4 = QtGui.QStandardItem('inf') 
    256         item5 = QtGui.QStandardItem('') 
    257         self._model_model.appendRow([item1, item2, item3, item4, item5]) 
    258  
    259         item1 = QtGui.QStandardItem('background') 
    260         item1.setCheckable(True) 
    261         item2 = QtGui.QStandardItem('0.001') 
    262         item3 = QtGui.QStandardItem('-inf') 
    263         item4 = QtGui.QStandardItem('inf') 
    264         item5 = QtGui.QStandardItem('1/cm') 
    265         self._model_model.appendRow([item1, item2, item3, item4, item5]) 
    266  
    267         multishell_parameters = self.getIterParams(self.model_parameters) 
    268         multishell_param_name, _ = self.getMultiplicity(self.model_parameters) 
     323        #TODO: scale and background are implicit in sasmodels and needs to be added 
     324        self.addScaleToModel(self._model_model) 
     325        self.addBackgroundToModel(self._model_model) 
     326 
     327        self.addParametersToModel(self.model_parameters, self._model_model) 
     328 
     329        self.addHeadersToModel(self._model_model) 
     330 
     331        self.addExtraShells() 
     332 
     333        self.setPolyModel() 
     334        self.setMagneticModel() 
     335        self.model_is_loaded = True 
     336 
     337    def addParametersToModel(self, parameters, model): 
     338        """ 
     339        Update local ModelModel with sasmodel parameters 
     340        """ 
     341        multishell_parameters = self.getIterParams(parameters) 
     342        multishell_param_name, _ = self.getMultiplicity(parameters) 
    269343 
    270344        #TODO: iq_parameters are used here. If orientation paramateres or magnetic are needed 
    271345        # kernel_paramters should be used instead 
    272         #For orientation and magentic parameters param.type needs to be checked 
    273         for param in self.model_parameters.iq_parameters: 
     346        for param in parameters.iq_parameters: 
    274347            # don't include shell parameters 
    275348            if param.name == multishell_param_name: 
     
    279352            if param in multishell_parameters: 
    280353                item_name = self.replaceShellName(param.name, 1) 
     354 
    281355            item1 = QtGui.QStandardItem(item_name) 
    282356            item1.setCheckable(True) 
     357            # check for polydisp params 
     358            if param.polydisperse: 
     359                poly_item = QtGui.QStandardItem("Polydispersity") 
     360                item1_1 = QtGui.QStandardItem("Distribution") 
     361                # Find param in volume_params 
     362                for p in parameters.form_volume_parameters: 
     363                    if p.name == param.name: 
     364                        item1_2 = QtGui.QStandardItem(str(p.default)) 
     365                        item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
     366                        item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
     367                        item1_5 = QtGui.QStandardItem(p.units) 
     368                        poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
     369                        break 
     370 
     371                item1.appendRow([poly_item]) 
     372 
    283373            item2 = QtGui.QStandardItem(str(param.default)) 
    284374            item3 = QtGui.QStandardItem(str(param.limits[0])) 
    285375            item4 = QtGui.QStandardItem(str(param.limits[1])) 
    286376            item5 = QtGui.QStandardItem(param.units) 
    287             self._model_model.appendRow([item1, item2, item3, item4, item5]) 
    288  
    289         self._model_model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 
    290         self._model_model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("Value")) 
    291         self._model_model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 
    292         self._model_model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 
    293         self._model_model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("[Units]")) 
    294  
    295         self.addExtraShells() 
    296  
    297         self.setPolyModel() 
    298         self.setMagneticModel() 
    299         self.model_is_loaded = True 
     377            model.appendRow([item1, item2, item3, item4, item5]) 
     378 
     379        self._last_model_row = self._model_model.rowCount() 
     380 
     381    def modelToFittingParameters(self): 
     382        """ 
     383        Prepare the fitting data object, based on current ModelModel 
     384        """ 
     385        pass 
    300386 
    301387    def replaceShellName(self, param_name, value): 
     
    331417        Set polydispersity values 
    332418        """ 
    333         if self.model_parameters: 
    334             for row, param in enumerate(self.model_parameters.form_volume_parameters): 
    335                 item1 = QtGui.QStandardItem("Distribution of "+param.name) 
    336                 item1.setCheckable(True) 
    337                 item2 = QtGui.QStandardItem("0") 
    338                 item3 = QtGui.QStandardItem("") 
    339                 item4 = QtGui.QStandardItem("") 
    340                 item5 = QtGui.QStandardItem("35") 
    341                 item6 = QtGui.QStandardItem("3") 
    342                 item7 = QtGui.QStandardItem("") 
    343  
    344                 self._poly_model.appendRow([item1, item2, item3, item4, item5, item6, item7]) 
    345  
    346                 #TODO: Need to find cleaner way to input functions 
    347                 func = QtGui.QComboBox() 
    348                 func.addItems(['rectangle','array','lognormal','gaussian','schulz',]) 
    349                 func_index = self.lstPoly.model().index(row,6) 
    350                 self.lstPoly.setIndexWidget(func_index,func) 
    351  
    352         self._poly_model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 
    353         self._poly_model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("PD[ratio]")) 
    354         self._poly_model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 
    355         self._poly_model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 
    356         self._poly_model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("Npts")) 
    357         self._poly_model.setHeaderData(5, QtCore.Qt.Horizontal, QtCore.QVariant("Nsigs")) 
    358         self._poly_model.setHeaderData(6, QtCore.Qt.Horizontal, QtCore.QVariant("Function")) 
     419        ### TODO: apply proper proxy model filtering from the main _model_model 
     420 
     421        if not self.model_parameters: 
     422            return 
     423        self._poly_model.clear() 
     424        for row, param in enumerate(self.model_parameters.form_volume_parameters): 
     425            # Counters should not be included 
     426            if not param.polydisperse: 
     427                continue 
     428 
     429            # Potential multishell params 
     430            #length_control = param.length_control 
     431            #if length_control in param.name: 
     432 
     433            checked_list = ["Distribution of "+param.name, str(param.default), 
     434                            str(param.limits[0]),str(param.limits[1]), 
     435                            "35", "3", ""] 
     436            self.addCheckedListToModel(self._poly_model, checked_list) 
     437 
     438            #TODO: Need to find cleaner way to input functions 
     439            func = QtGui.QComboBox() 
     440            func.addItems(['rectangle','array','lognormal','gaussian','schulz',]) 
     441            func_index = self.lstPoly.model().index(row,6) 
     442            self.lstPoly.setIndexWidget(func_index,func) 
     443 
     444        self.addPolyHeadersToModel(self._poly_model) 
    359445 
    360446    def setMagneticModel(self): 
     
    362448        Set magnetism values on model 
    363449        """ 
    364         if self.model_parameters: 
    365             for row, param in enumerate(self.model_parameters.form_volume_parameters): 
    366                 item1 = QtGui.QStandardItem("Distribution of "+param.name) 
    367                 item1.setCheckable(True) 
    368                 item2 = QtGui.QStandardItem("0") 
    369                 item3 = QtGui.QStandardItem("") 
    370                 item4 = QtGui.QStandardItem("") 
    371                 item5 = QtGui.QStandardItem("35") 
    372                 item6 = QtGui.QStandardItem("3") 
    373                 item7 = QtGui.QStandardItem("") 
    374  
    375                 self._magnet_model.appendRow([item1, item2, item3, item4, item5, item6, item7]) 
    376  
    377                 #TODO: Need to find cleaner way to input functions 
    378                 func = QtGui.QComboBox() 
    379                 func.addItems(['rectangle','array','lognormal','gaussian','schulz',]) 
    380                 func_index = self.lstMagnetic.model().index(row,6) 
    381                 self.lstMagnetic.setIndexWidget(func_index,func) 
    382  
    383         self._magnet_model.setHeaderData(0, QtCore.Qt.Horizontal, QtCore.QVariant("Parameter")) 
    384         self._magnet_model.setHeaderData(1, QtCore.Qt.Horizontal, QtCore.QVariant("PD[ratio]")) 
    385         self._magnet_model.setHeaderData(2, QtCore.Qt.Horizontal, QtCore.QVariant("Min")) 
    386         self._magnet_model.setHeaderData(3, QtCore.Qt.Horizontal, QtCore.QVariant("Max")) 
    387         self._magnet_model.setHeaderData(4, QtCore.Qt.Horizontal, QtCore.QVariant("Npts")) 
    388         self._magnet_model.setHeaderData(5, QtCore.Qt.Horizontal, QtCore.QVariant("Nsigs")) 
    389         self._magnet_model.setHeaderData(6, QtCore.Qt.Horizontal, QtCore.QVariant("Function")) 
     450        if not self.model_parameters: 
     451            return 
     452        self._magnet_model.clear() 
     453        for param in self.model_parameters.call_parameters: 
     454            if param.type != "magnetic": 
     455                continue 
     456            checked_list = [param.name, 
     457                            str(param.default), 
     458                            str(param.limits[0]), 
     459                            str(param.limits[1]), 
     460                            param.units] 
     461            self.addCheckedListToModel(self._magnet_model, checked_list) 
     462 
     463        self.addHeadersToModel(self._magnet_model) 
    390464 
    391465    def addExtraShells(self): 
     
    403477        func = QtGui.QComboBox() 
    404478        func.addItems([str(i+1) for i in xrange(param_length)]) 
     479        func.currentIndexChanged.connect(self.modifyShellsInList) 
    405480 
    406481        # cell 2: combobox 
     
    412487        shell_index = self._model_model.index(shell_row-1, 1) 
    413488        self.lstParams.setIndexWidget(shell_index, func) 
    414         self.lstParams.setSpan(shell_row-1,2,2,4) 
     489 
     490        self._last_model_row = self._model_model.rowCount() 
     491 
     492 
     493    def modifyShellsInList(self, index): 
     494        """ 
     495        Add/remove additional multishell parameters 
     496        """ 
     497        # Find row location of the combobox 
     498        last_row = self._last_model_row 
     499        remove_rows = self._model_model.rowCount() - last_row 
     500 
     501        if remove_rows > 1: 
     502            self._model_model.removeRows(last_row, remove_rows) 
     503 
     504        multishell_parameters = self.getIterParams(self.model_parameters) 
     505 
     506        for i in xrange(index): 
     507            for par in multishell_parameters: 
     508                param_name = self.replaceShellName(par.name, i+2) 
     509                #param_name = str(p.name) + str(i+2) 
     510                item1 = QtGui.QStandardItem(param_name) 
     511                item1.setCheckable(True) 
     512                # check for polydisp params 
     513                if par.polydisperse: 
     514                    poly_item = QtGui.QStandardItem("Polydispersity") 
     515                    item1_1 = QtGui.QStandardItem("Distribution") 
     516                    # Find param in volume_params 
     517                    for p in self.model_parameters.form_volume_parameters: 
     518                        if p.name == par.name: 
     519                            item1_2 = QtGui.QStandardItem(str(p.default)) 
     520                            item1_3 = QtGui.QStandardItem(str(p.limits[0])) 
     521                            item1_4 = QtGui.QStandardItem(str(p.limits[1])) 
     522                            item1_5 = QtGui.QStandardItem(p.units) 
     523                            poly_item.appendRow([item1_1, item1_2, item1_3, item1_4, item1_5]) 
     524                            break 
     525                    item1.appendRow([poly_item]) 
     526 
     527                item2 = QtGui.QStandardItem(str(par.default)) 
     528                item3 = QtGui.QStandardItem(str(par.limits[0])) 
     529                item4 = QtGui.QStandardItem(str(par.limits[1])) 
     530                item5 = QtGui.QStandardItem(par.units) 
     531                self._model_model.appendRow([item1, item2, item3, item4, item5]) 
    415532 
    416533    def togglePoly(self, isChecked): 
Note: See TracChangeset for help on using the changeset viewer.