Changeset 06b0138 in sasview for src/sas/qtgui/Perspectives/Fitting


Ignore:
Timestamp:
Jun 8, 2017 3:12:46 AM (8 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:
70080a0
Parents:
aca8418
Message:

Polydispersity support: cleanup and unit tests SASVIEW-575

Location:
src/sas/qtgui/Perspectives/Fitting
Files:
5 edited

Legend:

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

    raca8418 r06b0138  
    7070                    continue 
    7171                width = kernel_module.getParam(p.name+'.width') 
    72                 #npts = kernel_module.getParam(p.name+'.npts') 
    73                 #nsigs = kernel_module.getParam(p.name+'.nsigmas') 
    7472                type = kernel_module.getParam(p.name+'.type') 
    7573 
  • src/sas/qtgui/Perspectives/Fitting/FittingWidget.py

    raca8418 r06b0138  
    498498            parameter_name = parameter_name.rsplit()[-1] 
    499499 
    500         # Extract changed value. Assumes proper validation by QValidator/Delegate 
    501         # TODO: abstract away hardcoded column numbers 
     500        # Extract changed value. 
    502501        if model_column == POLY_COL_NAME: 
    503502            # Is the parameter checked for fitting? 
    504503            value = item.checkState() 
    505             # TODO: add the param to self.params_for_fitting 
    506504            parameter_name = parameter_name+'.width' 
    507505            if value == QtCore.Qt.Checked: 
     
    511509                    self.parameters_to_fit.remove(parameter_name) 
    512510            return 
    513         elif model_column == POLY_COL_FUNCTION: 
    514             value = item.text() 
    515             # TODO: Modify Npts/Nsigs based on function choice 
    516511        elif model_column in [POLY_COL_MIN, POLY_COL_MAX]: 
    517512            try: 
     
    566561        qmax = self.q_range_max 
    567562        params_to_fit = self.parameters_to_fit 
    568  
    569         print "OPTIMIZING: ", params_to_fit 
    570563 
    571564        # Potential weights added directly to data 
     
    780773        self._poly_model.blockSignals(False) 
    781774 
    782         return 
     775        #return 
    783776 
    784777        if self.has_poly_error_column: 
    785778            return 
     779 
     780        # Duck type delegate variables 
     781        self.lstPoly.itemDelegate().POLY_MIN = 3 
     782        self.lstPoly.itemDelegate().POLY_MAX = 4 
     783        self.lstPoly.itemDelegate().POLY_NPTS = 5 
     784        self.lstPoly.itemDelegate().POLY_NSIGS = 6 
     785        self.lstPoly.itemDelegate().POLY_FUNCTION = 7 
    786786 
    787787        error_column = [] 
     
    12901290        Creates a checked row of for a polydisperse parameter 
    12911291        """ 
     1292        # Not suitable for multishell 
     1293        if '[' in param.name: 
     1294            return 
    12921295        # Values from the sasmodel 
    12931296        width = self.kernel_module.getParam(param.name+'.width') 
     
    13061309        func.setCurrentIndex(func.findText(DEFAULT_POLYDISP_FUNCTION)) 
    13071310        # Index in the view 
    1308         func_index = self.lstPoly.model().index(row, 6) 
     1311        #func_index = self.lstPoly.model().index(row, 6) 
    13091312 
    13101313    def onPolyComboIndexChange(self, combo_string, row_index): 
     
    13181321            try: 
    13191322                self.loadPolydispArray() 
    1320             except ValueError: 
     1323            except (ValueError, IOError): 
    13211324                # Don't do anything if file lookup failed 
    13221325                return 
     
    13691372        self._magnet_model.clear() 
    13701373        [self.addCheckedMagneticListToModel(param, self._magnet_model) for param in \ 
    1371             self.model_parameters.call_parameters if param != 'magnetic'] 
     1374            self.model_parameters.call_parameters if param.type == 'magnetic'] 
    13721375        FittingUtilities.addHeadersToModel(self._magnet_model) 
    13731376 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingUtilitiesTest.py

    rdc5ef15 r06b0138  
    1010from sasmodels import generate 
    1111from sasmodels import modelinfo 
     12from sasmodels.sasview_model import load_standard_models 
    1213 
    1314# Tested module 
     
    9495        # Use a single-shell parameter 
    9596        model_name = "barbell" 
    96         kernel_module = generate.load_kernel_module(model_name) 
     97        models = load_standard_models() 
     98 
     99        kernel_module = generate.load_kernel_module(model_name) 
     100        kernel_module_o = None 
     101        for model in models: 
     102            if model.name == model_name: 
     103                kernel_module_o = model() 
     104        self.assertIsNotNone(kernel_module_o) 
    97105        barbell_parameters = modelinfo.make_parameter_table(getattr(kernel_module, 'parameters', [])) 
    98106 
    99         params = FittingUtilities.addParametersToModel(barbell_parameters, True) 
     107        params = FittingUtilities.addParametersToModel(barbell_parameters, kernel_module_o, True) 
    100108 
    101109        # Test the resulting model 
     
    109117        model_name = "core_multi_shell" 
    110118        kernel_module = generate.load_kernel_module(model_name) 
     119        kernel_module_o = None 
     120        for model in models: 
     121            if model.name == model_name: 
     122                kernel_module_o = model() 
     123        self.assertIsNotNone(kernel_module_o) 
    111124        multi_parameters = modelinfo.make_parameter_table(getattr(kernel_module, 'parameters', [])) 
    112125 
    113         params = FittingUtilities.addParametersToModel(multi_parameters, False) 
     126        params = FittingUtilities.addParametersToModel(multi_parameters, kernel_module_o, False) 
    114127 
    115128        # Test the resulting model 
     
    127140        model_name = "core_multi_shell" 
    128141        kernel_module = generate.load_kernel_module(model_name) 
     142        models = load_standard_models() 
     143        kernel_module_o = None 
     144        for model in models: 
     145            if model.name == model_name: 
     146                kernel_module_o = model() 
     147        self.assertIsNotNone(kernel_module_o) 
    129148        multi_parameters = modelinfo.make_parameter_table(getattr(kernel_module, 'parameters', [])) 
    130149 
    131         params = FittingUtilities.addParametersToModel(multi_parameters, True) 
     150        params = FittingUtilities.addParametersToModel(multi_parameters, kernel_module_o, True) 
    132151 
    133152        # Test the resulting model 
  • src/sas/qtgui/Perspectives/Fitting/UnitTesting/FittingWidgetTest.py

    rfd1ae6d1 r06b0138  
    3535        """Destroy the GUI""" 
    3636        self.widget.close() 
    37         self.widget = None 
     37        del self.widget 
    3838 
    3939    def testDefaults(self): 
     
    8484        """ 
    8585        Test if models have been loaded properly 
    86         :return: 
    8786        """ 
    8887        fittingWindow =  self.widget 
    8988 
     89        self.assertIsInstance(fittingWindow.lstPoly.itemDelegate(), QtGui.QStyledItemDelegate) 
    9090        #Test loading from json categories 
    9191        fittingWindow.SASModelToQModel("cylinder") 
     
    9595        self.assertEqual(str(pd_index.data().toString()), "Distribution of length") 
    9696 
     97        # test the delegate a bit 
     98        delegate = fittingWindow.lstPoly.itemDelegate() 
     99        self.assertEqual(len(delegate.POLYDISPERSE_FUNCTIONS), 5) 
     100        self.assertEqual(delegate.POLY_EDITABLE_PARAMS, [2, 3, 4, 5]) 
     101        self.assertEqual(delegate.POLY_FUNCTION, 6) 
     102        self.assertIsInstance(delegate.combo_updated, QtCore.pyqtBoundSignal) 
     103 
    97104    def testSelectStructureFactor(self): 
    98105        """ 
    99106        Test if structure factors have been loaded properly 
    100         :return: 
    101107        """ 
    102108        fittingWindow =  self.widget 
     
    340346            #self.assertTrue(isinstance(self.widget.lstPoly.indexWidget(func_index), QtGui.QComboBox)) 
    341347            self.assertIn('Distribution of', self.widget._poly_model.item(row, 0).text()) 
     348        #self.widget.close() 
     349 
     350    def testPolyModelChange(self): 
     351        """ 
     352        Polydispersity model changed - test all possible scenarios 
     353        """ 
     354        self.widget.show() 
     355        # Change the category index so we have a model with polydisp 
     356        category_index = self.widget.cbCategory.findText("Cylinder") 
     357        self.widget.cbCategory.setCurrentIndex(category_index) 
     358 
     359        # click on a poly parameter checkbox 
     360        index = self.widget._poly_model.index(0,0) 
     361        # Set the checbox 
     362        self.widget._poly_model.item(0,0).setCheckState(2) 
     363        # Assure the parameter is added 
     364        self.assertEqual(self.widget.parameters_to_fit, ['radius_bell.width']) 
     365 
     366        # Add another parameter 
     367        self.widget._poly_model.item(2,0).setCheckState(2) 
     368        # Assure the parameters are added 
     369        self.assertEqual(self.widget.parameters_to_fit, ['radius_bell.width', 'length.width']) 
     370 
     371        # Change the min/max values 
     372        self.assertEqual(self.widget.kernel_module.details['radius_bell'][1], 0.0) 
     373        self.widget._poly_model.item(0,2).setText("1.0") 
     374        self.assertEqual(self.widget.kernel_module.details['radius_bell'][1], 1.0) 
     375 
     376        # Change the number of points 
     377        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 35) 
     378        self.widget._poly_model.item(0,4).setText("22") 
     379        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 22) 
     380        # try something stupid 
     381        self.widget._poly_model.item(0,4).setText("butt") 
     382        # see that this didn't annoy the control at all 
     383        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 22) 
     384 
     385        # Change the number of sigmas 
     386        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 3) 
     387        self.widget._poly_model.item(0,5).setText("222") 
     388        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 222) 
     389        # try something stupid again 
     390        self.widget._poly_model.item(0,4).setText("beer") 
     391        # no efect 
     392        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 222) 
     393 
     394    def testOnPolyComboIndexChange(self): 
     395        """ 
     396        Test the slot method for polydisp. combo box index change 
     397        """ 
     398        self.widget.show() 
     399        # Change the category index so we have a model with polydisp 
     400        category_index = self.widget.cbCategory.findText("Cylinder") 
     401        self.widget.cbCategory.setCurrentIndex(category_index) 
     402 
     403        # call method with default settings 
     404        self.widget.onPolyComboIndexChange('gaussian', 0) 
     405        # check values 
     406        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 35) 
     407        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 3) 
     408        # Change the index 
     409        self.widget.onPolyComboIndexChange('rectangle', 0) 
     410        # check values 
     411        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 35) 
     412        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 1.70325) 
     413        # Change the index 
     414        self.widget.onPolyComboIndexChange('lognormal', 0) 
     415        # check values 
     416        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 80) 
     417        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 8) 
     418        # Change the index 
     419        self.widget.onPolyComboIndexChange('schulz', 0) 
     420        # check values 
     421        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.npts'), 80) 
     422        self.assertEqual(self.widget.kernel_module.getParam('radius_bell.nsigmas'), 8) 
     423 
     424        # mock up file load 
     425        self.widget.loadPolydispArray = MagicMock() 
     426        # Change to 'array' 
     427        self.widget.onPolyComboIndexChange('array', 0) 
     428        # See the mock fire 
     429        self.assertTrue(self.widget.loadPolydispArray.called) 
     430 
     431    def testLoadPolydispArray(self): 
     432        """ 
     433        Test opening of the load file dialog for 'array' polydisp. function 
     434        """ 
     435        filename = os.path.join("UnitTesting", "testdata_noexist.txt") 
     436        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename) 
     437        self.widget.show() 
     438        # Change the category index so we have a model with polydisp 
     439        category_index = self.widget.cbCategory.findText("Cylinder") 
     440        self.widget.cbCategory.setCurrentIndex(category_index) 
     441 
     442        self.widget.onPolyComboIndexChange('array', 0) 
     443        # check values - unchanged since the file doesn't exist 
     444        self.assertTrue(self.widget._poly_model.item(0, 1).isEnabled()) 
     445        with self.assertRaises(AttributeError): 
     446            self.widget.disp_model() 
     447 
     448        # good file 
     449        filename = os.path.join("UnitTesting", "testdata.txt") 
     450        QtGui.QFileDialog.getOpenFileName = MagicMock(return_value=filename) 
     451 
     452        self.widget.onPolyComboIndexChange('array', 0) 
     453        # check values - disabled control, present weights 
     454        self.assertFalse(self.widget._poly_model.item(0, 1).isEnabled()) 
     455        self.assertEqual(self.widget.disp_model.weights[0], 2.83954) 
     456        self.assertEqual(len(self.widget.disp_model.weights), 19) 
     457        self.assertEqual(len(self.widget.disp_model.values), 19) 
     458        self.assertEqual(self.widget.disp_model.values[0], 0.0) 
     459        self.assertEqual(self.widget.disp_model.values[18], 3.67347) 
    342460 
    343461    def testSetMagneticModel(self): 
  • src/sas/qtgui/Perspectives/Fitting/ViewDelegate.py

    raca8418 r06b0138  
    44import sas.qtgui.Utilities.GuiUtils as GuiUtils 
    55 
    6 # Main parameter table view columns 
    7 PARAM_PROPERTY=0 
    8 PARAM_VALUE=1 
    9 PARAM_MIN=2 
    10 PARAM_MAX=3 
    11 PARAM_UNIT=4 
    12  
    13 # polydispersity functions 
    14 POLYDISPERSE_FUNCTIONS=['rectangle', 'array', 'lognormal', 'gaussian', 'schulz'] 
    15 # polydispersity columns 
    16 POLY_PARAMETER=0 
    17 POLY_PD=1 
    18 POLY_MIN=2 
    19 POLY_MAX=3 
    20 POLY_NPTS=4 
    21 POLY_NSIGS=5 
    22 POLY_FUNCTION=6 
    23 POLY_EDITABLE_PARAMS = [POLY_MIN, POLY_MAX, POLY_NPTS, POLY_NSIGS] 
    24  
    25  
    266class ModelViewDelegate(QtGui.QStyledItemDelegate): 
    277    """ 
    288    Custom delegate for appearance and behavior control of the model view 
    299    """ 
     10    # Main parameter table view columns 
     11    PARAM_PROPERTY=0 
     12    PARAM_VALUE=1 
     13    PARAM_MIN=2 
     14    PARAM_MAX=3 
     15    PARAM_UNIT=4 
     16 
    3017    def paint(self, painter, option, index): 
    3118        """ 
    3219        Overwrite generic painter for certain columns 
    3320        """ 
    34         if index.column() in (PARAM_UNIT, PARAM_MIN, PARAM_MAX): 
     21        if index.column() in (self.PARAM_UNIT, self.PARAM_MIN, self.PARAM_MAX): 
    3522            # Units - present in nice HTML 
    3623            options = QtGui.QStyleOptionViewItemV4(option) 
     
    6956        if not index.isValid(): 
    7057            return 0 
    71         if index.column() == PARAM_VALUE: #only in the value column 
     58        if index.column() == self.PARAM_VALUE: #only in the value column 
    7259            editor = QtGui.QLineEdit(widget) 
    7360            validator = QtGui.QDoubleValidator() 
     
    8168        Overwrite generic model update method for certain columns 
    8269        """ 
    83         if index.column() in (PARAM_MIN, PARAM_MAX): 
     70        if index.column() in (self.PARAM_MIN, self.PARAM_MAX): 
    8471            try: 
    8572                value_float = float(editor.text()) 
     
    9582    Custom delegate for appearance and behavior control of the polydispersity view 
    9683    """ 
     84    # polydispersity functions 
     85    POLYDISPERSE_FUNCTIONS=['rectangle', 'array', 'lognormal', 'gaussian', 'schulz'] 
     86    # polydispersity columns 
     87    POLY_PARAMETER=0 
     88    POLY_PD=1 
     89    POLY_MIN=2 
     90    POLY_MAX=3 
     91    POLY_NPTS=4 
     92    POLY_NSIGS=5 
     93    POLY_FUNCTION=6 
     94    POLY_EDITABLE_PARAMS = [POLY_MIN, POLY_MAX, POLY_NPTS, POLY_NSIGS] 
     95 
    9796    combo_updated = QtCore.pyqtSignal(str, int) 
     97 
    9898    def createEditor(self, widget, option, index): 
    9999        # Remember the current choice 
     
    101101        if not index.isValid(): 
    102102            return 0 
    103         if index.column() == POLY_FUNCTION: 
     103        if index.column() == self.POLY_FUNCTION: 
    104104            editor = QtGui.QComboBox(widget) 
    105             for function in POLYDISPERSE_FUNCTIONS: 
     105            for function in self.POLYDISPERSE_FUNCTIONS: 
    106106                editor.addItem(function) 
    107107            current_index = editor.findText(current_text) 
     
    109109            editor.currentIndexChanged.connect(lambda: self.combo_updated.emit(str(editor.currentText()), index.row())) 
    110110            return editor 
    111         elif index.column() in POLY_EDITABLE_PARAMS: 
     111        elif index.column() in self.POLY_EDITABLE_PARAMS: 
    112112            editor = QtGui.QLineEdit(widget) 
    113113            validator = QtGui.QDoubleValidator() 
     
    121121        Overwrite generic painter for certain columns 
    122122        """ 
    123         if index.column() in (POLY_MIN, POLY_MAX): 
     123        if index.column() in (self.POLY_MIN, self.POLY_MAX): 
    124124            # Units - present in nice HTML 
    125125            options = QtGui.QStyleOptionViewItemV4(option) 
Note: See TracChangeset for help on using the changeset viewer.